#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 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_erase(struct flash_dev *dev, uint32_t addr, size_t len); static struct flash_ops stdio_flash_ops = { .read = stdio_flash_read, .write = stdio_flash_write, .erase = stdio_flash_erase, }; 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_erase(struct flash_dev *dev, uint32_t addr, size_t len) { struct stdio_flash_priv *priv = dev->priv; if (!IS_ROUND(addr, 4 * KIB) || !IS_ROUND(len, 4 * KIB)) return -1; memset(priv->data + addr, 0xFF, len); 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; 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); }