diff options
Diffstat (limited to 'libflash')
-rw-r--r-- | libflash/libffs.c | 51 | ||||
-rw-r--r-- | libflash/libffs.h | 7 | ||||
-rw-r--r-- | libflash/libflash.c | 83 | ||||
-rw-r--r-- | libflash/libflash.h | 25 | ||||
-rw-r--r-- | libflash/test/test-flash.c | 20 |
5 files changed, 100 insertions, 86 deletions
diff --git a/libflash/libffs.c b/libflash/libffs.c index 55e6895..c03c56a 100644 --- a/libflash/libffs.c +++ b/libflash/libffs.c @@ -41,6 +41,7 @@ struct ffs_handle { uint32_t max_size; void *cache; uint32_t cached_size; + struct blocklevel_device *bl; }; static uint32_t ffs_checksum(void* data, size_t size) @@ -71,31 +72,31 @@ static int ffs_check_convert_header(struct ffs_hdr *dst, struct ffs_hdr *src) return 0; } -int ffs_open_flash(struct flash_chip *chip, uint32_t toc_offset, - uint32_t max_size, struct ffs_handle **ffs) +int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl, + struct ffs_handle **ffs) { struct ffs_hdr hdr; struct ffs_handle *f; - uint32_t fl_size, erase_size; + uint32_t total_size; int rc; - if (!ffs) + if (!ffs || !bl) return FLASH_ERR_PARM_ERROR; *ffs = NULL; - /* Grab some info about our flash chip */ - rc = flash_get_info(chip, NULL, &fl_size, &erase_size); + rc = blocklevel_get_info(bl, NULL, &total_size, NULL); if (rc) { FL_ERR("FFS: Error %d retrieving flash info\n", rc); return rc; } - if ((toc_offset + max_size) < toc_offset) + if ((offset + max_size) < offset) return FLASH_ERR_PARM_ERROR; - if ((toc_offset + max_size) > fl_size) + + if ((max_size > total_size)) return FLASH_ERR_PARM_ERROR; /* Read flash header */ - rc = flash_read(chip, toc_offset, &hdr, sizeof(hdr)); + rc = blocklevel_read(bl, offset, &hdr, sizeof(hdr)); if (rc) { FL_ERR("FFS: Error %d reading flash header\n", rc); return rc; @@ -106,17 +107,16 @@ int ffs_open_flash(struct flash_chip *chip, uint32_t toc_offset, if (!f) return FLASH_ERR_MALLOC_FAILED; memset(f, 0, sizeof(*f)); - f->type = ffs_type_flash; - f->toc_offset = toc_offset; - f->max_size = max_size ? max_size : (fl_size - toc_offset); - f->chip = chip; + + f->toc_offset = offset; + f->max_size = max_size; + f->bl = bl; /* Convert and check flash header */ rc = ffs_check_convert_header(&f->hdr, &hdr); if (rc) { FL_ERR("FFS: Error %d checking flash header\n", rc); - free(f); - return rc; + goto out; } /* @@ -126,26 +126,26 @@ int ffs_open_flash(struct flash_chip *chip, uint32_t toc_offset, f->cached_size = f->hdr.block_size * f->hdr.size; FL_DBG("FFS: Partition map size: 0x%x\n", f->cached_size); - /* Align to erase size */ - f->cached_size |= (erase_size - 1); - f->cached_size &= ~(erase_size - 1); - FL_DBG("FFS: Aligned to: 0x%x\n", f->cached_size); - /* Allocate cache */ f->cache = malloc(f->cached_size); if (!f->cache) { - free(f); - return FLASH_ERR_MALLOC_FAILED; + rc = FLASH_ERR_MALLOC_FAILED; + goto out; } /* Read the cached map */ - rc = flash_read(chip, toc_offset, f->cache, f->cached_size); + rc = blocklevel_read(bl, offset, f->cache, f->cached_size); if (rc) { FL_ERR("FFS: Error %d reading flash partition map\n", rc); - free(f); + goto out; } + +out: if (rc == 0) *ffs = f; + else + free(f); + return rc; } @@ -361,6 +361,7 @@ int ffs_update_act_size(struct ffs_handle *ffs, uint32_t part_idx, ent->checksum = ffs_checksum(ent, FFS_ENTRY_SIZE_CSUM); if (!ffs->chip) return 0; - return flash_smart_write(ffs->chip, offset, ent, FFS_ENTRY_SIZE); + + return blocklevel_write(ffs->bl, offset, ent, FFS_ENTRY_SIZE); } diff --git a/libflash/libffs.h b/libflash/libffs.h index faaa4bc..a0040e9 100644 --- a/libflash/libffs.h +++ b/libflash/libffs.h @@ -18,6 +18,7 @@ #include <libflash/libflash.h> #include <libflash/ffs.h> +#include <libflash/blocklevel.h> /* FFS handle, opaque */ struct ffs_handle; @@ -34,8 +35,10 @@ struct ffs_handle; #define FFS_ERR_PART_NOT_FOUND 103 #define FFS_ERR_BAD_ECC 104 -int ffs_open_flash(struct flash_chip *chip, uint32_t toc_offset, - uint32_t max_size, struct ffs_handle **ffs); +/* Init */ + +int ffs_init(uint32_t offset, uint32_t max_size, + struct blocklevel_device *bl, struct ffs_handle **ffs); /* ffs_open_image is Linux only as it uses lseek, which skiboot does not * implement */ diff --git a/libflash/libflash.c b/libflash/libflash.c index e43be4f..2af0c79 100644 --- a/libflash/libflash.c +++ b/libflash/libflash.c @@ -20,6 +20,7 @@ #include "libflash.h" #include "libflash-priv.h" #include "ecc.h" +#include "blocklevel.h" #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -45,6 +46,7 @@ struct flash_chip { bool mode_4b; /* Flash currently in 4b mode */ struct flash_req *cur_req; /* Current request */ void *smart_buf; /* Buffer for smart writes */ + struct blocklevel_device bl; }; #ifndef __SKIBOOT__ @@ -112,8 +114,9 @@ int fl_wren(struct spi_flash_ctrl *ct) return FLASH_ERR_WREN_TIMEOUT; } -int flash_read(struct flash_chip *c, uint32_t pos, void *buf, uint32_t len) +static int flash_read(struct blocklevel_device *bl, uint32_t pos, void *buf, uint32_t len) { + struct flash_chip *c = container_of(bl, struct flash_chip, bl); struct spi_flash_ctrl *ct = c->ctrl; /* XXX Add sanity/bound checking */ @@ -138,7 +141,7 @@ int flash_read(struct flash_chip *c, uint32_t pos, void *buf, uint32_t len) * This provides a wrapper around flash_read on ECCed data * len is length of data without ECC attached */ -int flash_read_corrected(struct flash_chip *c, uint32_t pos, void *buf, +int flash_read_corrected(struct blocklevel_device *bl, uint32_t pos, void *buf, uint32_t len, bool ecc) { struct ecc64 *bufecc; @@ -147,7 +150,7 @@ int flash_read_corrected(struct flash_chip *c, uint32_t pos, void *buf, uint8_t ret; if (!ecc) - return flash_read(c, pos, buf, len); + return flash_read(bl, pos, buf, len); /* Copy the buffer in chunks */ bufecc = malloc(ECC_BUFFER_SIZE(COPY_BUFFER_LENGTH)); @@ -159,7 +162,7 @@ int flash_read_corrected(struct flash_chip *c, uint32_t pos, void *buf, copylen = MIN(len, COPY_BUFFER_LENGTH); /* Read ECCed data from flash */ - rc = flash_read(c, pos, bufecc, ECC_BUFFER_SIZE(copylen)); + rc = flash_read(bl, pos, bufecc, ECC_BUFFER_SIZE(copylen)); if (rc) goto err; @@ -215,8 +218,9 @@ static void fl_get_best_erase(struct flash_chip *c, uint32_t dst, uint32_t size, *cmd = CMD_BE; } -int flash_erase(struct flash_chip *c, uint32_t dst, uint32_t size) +static int flash_erase(struct blocklevel_device *bl, uint32_t dst, uint32_t size) { + struct flash_chip *c = container_of(bl, struct flash_chip, bl); struct spi_flash_ctrl *ct = c->ctrl; uint32_t chunk; uint8_t cmd; @@ -262,8 +266,9 @@ int flash_erase(struct flash_chip *c, uint32_t dst, uint32_t size) return 0; } -int flash_erase_chip(struct flash_chip *c) +int flash_erase_chip(struct blocklevel_device *bl) { + struct flash_chip *c = container_of(bl, struct flash_chip, bl); struct spi_flash_ctrl *ct = c->ctrl; int rc; @@ -311,9 +316,10 @@ static int fl_wpage(struct flash_chip *c, uint32_t dst, const void *src, return fl_sync_wait_idle(ct); } -int flash_write(struct flash_chip *c, uint32_t dst, const void *src, +static int flash_write(struct blocklevel_device *bl, uint32_t dst, const void *src, uint32_t size, bool verify) { + struct flash_chip *c = container_of(bl, struct flash_chip, bl); struct spi_flash_ctrl *ct = c->ctrl; uint32_t todo = size; uint32_t d = dst; @@ -374,7 +380,7 @@ int flash_write(struct flash_chip *c, uint32_t dst, const void *src, chunk = sizeof(vbuf); if (chunk > size) chunk = size; - rc = flash_read(c, dst, vbuf, chunk); + rc = flash_read(bl, dst, vbuf, chunk); if (rc) return rc; if (memcmp(vbuf, src, chunk)) { FL_ERR("LIBFLASH: Miscompare at 0x%08x\n", dst); @@ -387,7 +393,7 @@ int flash_write(struct flash_chip *c, uint32_t dst, const void *src, return 0; } -int flash_write_corrected(struct flash_chip *c, uint32_t pos, const void *buf, +int flash_write_corrected(struct blocklevel_device *bl, uint32_t pos, const void *buf, uint32_t len, bool verify, bool ecc) { struct ecc64 *bufecc; @@ -396,7 +402,7 @@ int flash_write_corrected(struct flash_chip *c, uint32_t pos, const void *buf, uint8_t ret; if (!ecc) - return flash_write(c, pos, buf, len, verify); + return flash_write(bl, pos, buf, len, verify); /* Copy the buffer in chunks */ bufecc = malloc(ECC_BUFFER_SIZE(COPY_BUFFER_LENGTH)); @@ -415,7 +421,7 @@ int flash_write_corrected(struct flash_chip *c, uint32_t pos, const void *buf, } /* Write ECCed data to the flash */ - rc = flash_write(c, pos, bufecc, copylen, verify); + rc = flash_write(bl, pos, bufecc, copylen, verify); if (rc) goto err; @@ -463,12 +469,12 @@ static enum sm_comp_res flash_smart_comp(struct flash_chip *c, return is_same ? sm_no_change : sm_need_write; } -int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src, - uint32_t size) +static int flash_smart_write(struct blocklevel_device *bl, uint32_t dst, const void *src, uint32_t size) { + struct flash_chip *c = container_of(bl, struct flash_chip, bl); uint32_t er_size = c->min_erase_mask + 1; uint32_t end = dst + size; - int rc; + int rc; /* Some sanity checking */ if (end <= dst || !size || end > c->tsize) { @@ -489,7 +495,7 @@ int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src, off = dst & c->min_erase_mask; FL_DBG("LIBFLASH: reading page 0x%08x..0x%08x...", page, page + er_size); - rc = flash_read(c, page, c->smart_buf, er_size); + rc = flash_read(bl, page, c->smart_buf, er_size); if (rc) { FL_DBG(" error %d!\n", rc); return rc; @@ -510,7 +516,7 @@ int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src, case sm_need_write: /* Just needs writing over */ FL_DBG(" need write !\n"); - rc = flash_write(c, dst, src, chunk, true); + rc = flash_write(bl, dst, src, chunk, true); if (rc) { FL_DBG("LIBFLASH: Write error %d !\n", rc); return rc; @@ -518,14 +524,14 @@ int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src, break; case sm_need_erase: FL_DBG(" need erase !\n"); - rc = flash_erase(c, page, er_size); + rc = flash_erase(bl, page, er_size); if (rc) { FL_DBG("LIBFLASH: erase error %d !\n", rc); return rc; } /* Then update the portion of the buffer and write the block */ memcpy(c->smart_buf + off, src, chunk); - rc = flash_write(c, page, c->smart_buf, er_size, true); + rc = flash_write(bl, page, c->smart_buf, er_size, true); if (rc) { FL_DBG("LIBFLASH: write error %d !\n", rc); return rc; @@ -539,14 +545,14 @@ int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src, return 0; } -int flash_smart_write_corrected(struct flash_chip *c, uint32_t dst, const void *src, +int flash_smart_write_corrected(struct blocklevel_device *bl, uint32_t dst, const void *src, uint32_t size, bool ecc) { struct ecc64 *buf; int rc; if (!ecc) - return flash_smart_write(c, dst, src, size); + return flash_smart_write(bl, dst, src, size); buf = malloc(ECC_BUFFER_SIZE(size)); if (!buf) @@ -558,7 +564,7 @@ int flash_smart_write_corrected(struct flash_chip *c, uint32_t dst, const void * goto out; } - rc = flash_smart_write(c, dst, buf, ECC_BUFFER_SIZE(size)); + rc = flash_smart_write(bl, dst, buf, ECC_BUFFER_SIZE(size)); out: free(buf); @@ -684,8 +690,9 @@ static int flash_set_4b(struct flash_chip *c, bool enable) return ct->cmd_wr(ct, enable ? CMD_EN4B : CMD_EX4B, false, 0, NULL, 0); } -int flash_force_4b_mode(struct flash_chip *c, bool enable_4b) +int flash_force_4b_mode(struct blocklevel_device *bl, bool enable_4b) { + struct flash_chip *c = container_of(bl, struct flash_chip, bl); struct spi_flash_ctrl *ct = c->ctrl; int rc; @@ -776,24 +783,29 @@ static int flash_configure(struct flash_chip *c) return 0; } -int flash_get_info(struct flash_chip *chip, const char **name, +static int flash_get_info(struct blocklevel_device *bl, const char **name, uint32_t *total_size, uint32_t *erase_granule) { + struct flash_chip *c = container_of(bl, struct flash_chip, bl); if (name) - *name = chip->info.name; + *name = c->info.name; if (total_size) - *total_size = chip->tsize; + *total_size = c->tsize; if (erase_granule) - *erase_granule = chip->min_erase_mask + 1; + *erase_granule = c->min_erase_mask + 1; return 0; } -int flash_init(struct spi_flash_ctrl *ctrl, struct flash_chip **flash) +int flash_init(struct spi_flash_ctrl *ctrl, struct blocklevel_device **bl) { struct flash_chip *c; int rc; - *flash = NULL; + if (!bl) + return FLASH_ERR_PARM_ERROR; + + *bl = NULL; + c = malloc(sizeof(struct flash_chip)); if (!c) return FLASH_ERR_MALLOC_FAILED; @@ -814,18 +826,25 @@ int flash_init(struct spi_flash_ctrl *ctrl, struct flash_chip **flash) rc = flash_configure(c); if (rc) FL_ERR("LIBFLASH: Flash configuration failed\n"); - bail: +bail: if (rc) { free(c); return rc; } - *flash = c; + + c->bl.read = &flash_read; + c->bl.write = &flash_smart_write; + c->bl.erase = &flash_erase; + c->bl.get_info = &flash_get_info; + + *bl = &(c->bl); return 0; } -void flash_exit(struct flash_chip *chip) +void flash_exit(struct blocklevel_device *bl) { /* XXX Make sure we are idle etc... */ - free(chip); + if (bl) + free(container_of(bl, struct flash_chip, bl)); } diff --git a/libflash/libflash.h b/libflash/libflash.h index 7ed65d0..30f984d 100644 --- a/libflash/libflash.h +++ b/libflash/libflash.h @@ -18,6 +18,7 @@ #include <stdint.h> #include <stdbool.h> +#include <libflash/blocklevel.h> #ifdef __SKIBOOT__ #include <skiboot.h> @@ -59,18 +60,13 @@ extern bool libflash_debug; struct flash_chip; struct spi_flash_ctrl; -int flash_init(struct spi_flash_ctrl *ctrl, struct flash_chip **flash); -void flash_exit(struct flash_chip *chip); - -int flash_get_info(struct flash_chip *chip, const char **name, - uint32_t *total_size, uint32_t *erase_granule); +int flash_init(struct spi_flash_ctrl *ctrl, struct blocklevel_device **bl); +void flash_exit(struct blocklevel_device *bl); /* libflash sets the 4b mode automatically based on the flash * size and controller capabilities but it can be overriden */ -int flash_force_4b_mode(struct flash_chip *chip, bool enable_4b); - -int flash_read(struct flash_chip *c, uint32_t pos, void *buf, uint32_t len); +int flash_force_4b_mode(struct blocklevel_device *bl, bool enable_4b); /* * This provides a wapper around flash_read() on ECCed data. All params are @@ -80,11 +76,8 @@ int flash_read(struct flash_chip *c, uint32_t pos, void *buf, uint32_t len); * len is length of data without ecc attached therefore this will read beyond * pos + len. */ -int flash_read_corrected(struct flash_chip *c, uint32_t pos, void *buf, +int flash_read_corrected(struct blocklevel_device *bl, uint32_t pos, void *buf, uint32_t len, bool ecc); -int flash_erase(struct flash_chip *c, uint32_t dst, uint32_t size); -int flash_write(struct flash_chip *c, uint32_t dst, const void *src, - uint32_t size, bool verify); /* * This provides a wrapper around flash_write() on ECCed data. All params are @@ -94,10 +87,8 @@ int flash_write(struct flash_chip *c, uint32_t dst, const void *src, * size is length of data without ECC attached therefore this will write beyond * dst + size. */ -int flash_write_corrected(struct flash_chip *c, uint32_t dst, const void *src, +int flash_write_corrected(struct blocklevel_device *bl, uint32_t dst, const void *src, uint32_t size, bool verify, bool ecc); -int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src, - uint32_t size); /* * This provides a wrapper around flash_smart_write() on ECCed data. All @@ -107,12 +98,12 @@ int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src, * size is length of data without ECC attached therefore this will write beyond * dst + size. */ -int flash_smart_write_corrected(struct flash_chip *c, uint32_t dst, const void *src, +int flash_smart_write_corrected(struct blocklevel_device *bl, uint32_t dst, const void *src, uint32_t size, bool ecc); /* chip erase may not be supported by all chips/controllers, get ready * for FLASH_ERR_CHIP_ER_NOT_SUPPORTED */ -int flash_erase_chip(struct flash_chip *c); +int flash_erase_chip(struct blocklevel_device *bl); #endif /* __LIBFLASH_H */ diff --git a/libflash/test/test-flash.c b/libflash/test/test-flash.c index 4479b5a..cf2b3a5 100644 --- a/libflash/test/test-flash.c +++ b/libflash/test/test-flash.c @@ -366,7 +366,7 @@ struct spi_flash_ctrl sim_ctrl = { int main(void) { - struct flash_chip *fl; + struct blocklevel_device *bl; uint32_t total_size, erase_granule; const char *name; uint16_t *test; @@ -378,12 +378,12 @@ int main(void) memset(sim_image, 0xff, sim_image_sz); test = malloc(0x10000 * 2); - rc = flash_init(&sim_ctrl, &fl); + rc = flash_init(&sim_ctrl, &bl); if (rc) { ERR("flash_init failed with err %d\n", rc); exit(1); } - rc = flash_get_info(fl, &name, &total_size, &erase_granule); + rc = flash_get_info(bl, &name, &total_size, &erase_granule); if (rc) { ERR("flash_get_info failed with err %d\n", rc); exit(1); @@ -395,13 +395,13 @@ int main(void) /* Write 64k of stuff at 0 and at 128k */ printf("Writing test patterns...\n"); - flash_smart_write(fl, 0, test, 0x10000); - flash_smart_write(fl, 0x20000, test, 0x10000); + flash_smart_write(bl, 0, test, 0x10000); + flash_smart_write(bl, 0x20000, test, 0x10000); /* Write "Hello world" straddling the 64k boundary */ #define HW "Hello World" printf("Writing test string...\n"); - flash_smart_write(fl, 0xfffc, HW, sizeof(HW)); + flash_smart_write(bl, 0xfffc, HW, sizeof(HW)); /* Check result */ if (memcmp(sim_image + 0xfffc, HW, sizeof(HW))) { @@ -416,7 +416,7 @@ int main(void) printf("Test pattern pass\n"); printf("Test ECC interfaces\n"); - flash_smart_write_corrected(fl, 0, test, 0x10000, 1); + flash_smart_write_corrected(bl, 0, test, 0x10000, 1); ecc_test = (struct ecc64 *)sim_image; test64 = (uint64_t *)test; for (i = 0; i < 0x10000 / sizeof(*ecc_test); i++) { @@ -433,7 +433,7 @@ int main(void) printf("Test ECC interface pass\n"); printf("Test ECC erase\n"); - if (flash_erase(fl, 0, 0x10000) != 0) { + if (flash_erase(bl, 0, 0x10000) != 0) { ERR("flash_erase didn't return 0\n"); exit(1); } @@ -444,7 +444,7 @@ int main(void) ERR("Data not properly cleared at %d\n", i); exit(1); } - rc = flash_write(fl, i * sizeof(*ecc_test) + 8, &zero, 1, 0); + rc = flash_write(bl, i * sizeof(*ecc_test) + 8, &zero, 1, 0); if (rc || ecc_test[i].ecc != 0) { ERR("Cleared data not correctly ECCed: 0x%02x (0x%016lx) expecting 0 at %d\n", ecc_test[i].ecc, ecc_test[i].data, i); exit(1); @@ -452,7 +452,7 @@ int main(void) } printf("Test ECC erase pass\n"); - flash_exit(fl); + flash_exit(bl); return 0; } |