#include #include #include #include #include #include #include #include #include #define CONFIG_FLASH_SIZE 4 * MIB struct stdio_flash_priv { FILE *fp; char *data; size_t size; }; static size_t stdio_flash_get_size(struct flash_dev *dev); static int stdio_flash_read(struct flash_dev *dev, uint32_t addr, void *data, size_t len); static int stdio_flash_write(struct flash_dev *dev, uint32_t addr, const void *data, size_t len); static int stdio_flash_copy(struct flash_dev *dev, uint32_t dst, uint32_t src, size_t len); static int stdio_flash_erase(struct flash_dev *dev, uint32_t addr); static struct flash_ops stdio_flash_ops = { .get_size = stdio_flash_get_size, .read = stdio_flash_read, .write = stdio_flash_write, .copy = stdio_flash_copy, .erase = stdio_flash_erase, }; static size_t stdio_flash_get_size(struct flash_dev *dev) { struct stdio_flash_priv *priv = dev->priv; return priv->size; } static int stdio_flash_read(struct flash_dev *dev, uint32_t addr, void *data, size_t len) { struct stdio_flash_priv *priv = dev->priv; if (addr > priv->size || len > priv->size - addr) return -1; memcpy(data, priv->data + addr, len); return 0; } static int stdio_flash_write(struct flash_dev *dev, uint32_t addr, const void *data, size_t len) { struct stdio_flash_priv *priv = dev->priv; const char *src; char *dst; size_t i; if (addr > priv->size || len > priv->size - addr) return -1; src = data; dst = priv->data + addr; for (i = 0; i < len; ++i) { dst[i] &= src[i]; } return 0; } static int stdio_flash_copy(struct flash_dev *dev, uint32_t dst, uint32_t src, size_t len) { uint8_t data[64]; size_t nbytes; while (len) { nbytes = min(sizeof data, len); if (stdio_flash_read(dev, src, data, nbytes) < 0) return -1; if (stdio_flash_write(dev, dst, data, nbytes) < 0) return -1; dst += nbytes; src += nbytes; len -= nbytes; } return 0; } static int stdio_flash_erase(struct flash_dev *dev, uint32_t addr) { struct stdio_flash_priv *priv = dev->priv; memset(priv->data + (addr << dev->log2_block_size), 0xff, 1 << dev->log2_block_size); return 0; } struct flash_dev *flash_probe(void) { struct stat st; struct flash_dev *dev; struct stdio_flash_priv *priv; if (!(dev = malloc(sizeof *dev))) return NULL; if (!(priv = malloc(sizeof *priv))) goto err_free_dev; if (!(priv->fp = fopen("flash.img", "r+b"))) goto err_free_priv; if (fstat(fileno(priv->fp), &st) < 0) goto err_close_fp; priv->size = st.st_size; if (!(priv->data = mmap(NULL, priv->size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(priv->fp), 0))) goto err_close_fp; dev->priv = priv; dev->ops = &stdio_flash_ops; dev->log2_page_size = ilog2(1); dev->log2_block_size = ilog2(4 * KIB); return dev; err_close_fp: fclose(priv->fp); err_free_priv: free(priv); err_free_dev: free(dev); return NULL; } void flash_release(struct flash_dev *dev) { struct stdio_flash_priv *priv; if (!dev) return; priv = dev->priv; munmap(priv->data, priv->size); fclose(priv->fp); free(dev->priv); free(dev); }