123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- #include <limits.h>
- #include <stdlib.h>
- #include <fs/fcb.h>
- #include "fcb_priv.h"
- #include "string.h"
- #include <errno.h>
- #include <device.h>
- #include <drivers/flash.h>
- uint8_t
- fcb_get_align(const struct fcb *fcb)
- {
- uint8_t align;
- if (fcb->fap == NULL) {
- return 0;
- }
- align = flash_area_align(fcb->fap);
- return align;
- }
- int fcb_flash_read(const struct fcb *fcb, const struct flash_sector *sector,
- off_t off, void *dst, size_t len)
- {
- int rc;
- if (off + len > sector->fs_size) {
- return -EINVAL;
- }
- if (fcb->fap == NULL) {
- return -EIO;
- }
- rc = flash_area_read(fcb->fap, sector->fs_off + off, dst, len);
- if (rc != 0) {
- return -EIO;
- }
- return 0;
- }
- int fcb_flash_write(const struct fcb *fcb, const struct flash_sector *sector,
- off_t off, const void *src, size_t len)
- {
- int rc;
- if (off + len > sector->fs_size) {
- return -EINVAL;
- }
- if (fcb->fap == NULL) {
- return -EIO;
- }
- rc = flash_area_write(fcb->fap, sector->fs_off + off, src, len);
- if (rc != 0) {
- return -EIO;
- }
- return 0;
- }
- int
- fcb_erase_sector(const struct fcb *fcb, const struct flash_sector *sector)
- {
- int rc;
- if (fcb->fap == NULL) {
- return -EIO;
- }
- rc = flash_area_erase(fcb->fap, sector->fs_off, sector->fs_size);
- if (rc != 0) {
- return -EIO;
- }
- return 0;
- }
- int
- fcb_init(int f_area_id, struct fcb *fcb)
- {
- struct flash_sector *sector;
- int rc;
- int i;
- uint8_t align;
- int oldest = -1, newest = -1;
- struct flash_sector *oldest_sector = NULL, *newest_sector = NULL;
- struct fcb_disk_area fda;
- const struct device *dev = NULL;
- const struct flash_parameters *fparam;
- if (!fcb->f_sectors || fcb->f_sector_cnt - fcb->f_scratch_cnt < 1) {
- return -EINVAL;
- }
- rc = flash_area_open(f_area_id, &fcb->fap);
- if (rc != 0) {
- return -EINVAL;
- }
- dev = device_get_binding(fcb->fap->fa_dev_name);
- fparam = flash_get_parameters(dev);
- fcb->f_erase_value = fparam->erase_value;
- align = fcb_get_align(fcb);
- if (align == 0U) {
- return -EINVAL;
- }
-
- for (i = 0; i < fcb->f_sector_cnt; i++) {
- sector = &fcb->f_sectors[i];
- rc = fcb_sector_hdr_read(fcb, sector, &fda);
- if (rc < 0) {
- return rc;
- }
- if (rc == 0) {
- continue;
- }
- if (oldest < 0) {
- oldest = newest = fda.fd_id;
- oldest_sector = newest_sector = sector;
- continue;
- }
- if (FCB_ID_GT(fda.fd_id, newest)) {
- newest = fda.fd_id;
- newest_sector = sector;
- } else if (FCB_ID_GT(oldest, fda.fd_id)) {
- oldest = fda.fd_id;
- oldest_sector = sector;
- }
- }
- if (oldest < 0) {
-
- oldest_sector = newest_sector = &fcb->f_sectors[0];
- rc = fcb_sector_hdr_init(fcb, oldest_sector, 0);
- if (rc) {
- return rc;
- }
- newest = oldest = 0;
- }
- fcb->f_align = align;
- fcb->f_oldest = oldest_sector;
- fcb->f_active.fe_sector = newest_sector;
- fcb->f_active.fe_elem_off = sizeof(struct fcb_disk_area);
- fcb->f_active_id = newest;
- while (1) {
- rc = fcb_getnext_in_sector(fcb, &fcb->f_active);
- if (rc == -ENOTSUP) {
- rc = 0;
- break;
- }
- if (rc != 0) {
- break;
- }
- }
- k_mutex_init(&fcb->f_mtx);
- return rc;
- }
- int
- fcb_free_sector_cnt(struct fcb *fcb)
- {
- int i;
- struct flash_sector *fa;
- fa = fcb->f_active.fe_sector;
- for (i = 0; i < fcb->f_sector_cnt; i++) {
- fa = fcb_getnext_sector(fcb, fa);
- if (fa == fcb->f_oldest) {
- break;
- }
- }
- return i;
- }
- int
- fcb_is_empty(struct fcb *fcb)
- {
- return (fcb->f_active.fe_sector == fcb->f_oldest &&
- fcb->f_active.fe_elem_off == sizeof(struct fcb_disk_area));
- }
- int
- fcb_put_len(const struct fcb *fcb, uint8_t *buf, uint16_t len)
- {
- if (len < 0x80) {
- buf[0] = len ^ ~fcb->f_erase_value;
- return 1;
- } else if (len < FCB_MAX_LEN) {
- buf[0] = (len | 0x80) ^ ~fcb->f_erase_value;
- buf[1] = (len >> 7) ^ ~fcb->f_erase_value;
- return 2;
- } else {
- return -EINVAL;
- }
- }
- int
- fcb_get_len(const struct fcb *fcb, uint8_t *buf, uint16_t *len)
- {
- int rc;
- if ((buf[0] ^ ~fcb->f_erase_value) & 0x80) {
- if ((buf[0] == fcb->f_erase_value) &&
- (buf[1] == fcb->f_erase_value)) {
- return -ENOTSUP;
- }
- *len = ((buf[0] ^ ~fcb->f_erase_value) & 0x7f) |
- ((uint8_t)(buf[1] ^ ~fcb->f_erase_value) << 7);
- rc = 2;
- } else {
- *len = (uint8_t)(buf[0] ^ ~fcb->f_erase_value);
- rc = 1;
- }
- return rc;
- }
- int
- fcb_sector_hdr_init(struct fcb *fcb, struct flash_sector *sector, uint16_t id)
- {
- struct fcb_disk_area fda;
- int rc;
- fda.fd_magic = fcb_flash_magic(fcb);
- fda.fd_ver = fcb->f_version;
- fda._pad = fcb->f_erase_value;
- fda.fd_id = id;
- rc = fcb_flash_write(fcb, sector, 0, &fda, sizeof(fda));
- if (rc != 0) {
- return -EIO;
- }
- return 0;
- }
- int fcb_sector_hdr_read(struct fcb *fcb, struct flash_sector *sector,
- struct fcb_disk_area *fdap)
- {
- struct fcb_disk_area fda;
- int rc;
- if (!fdap) {
- fdap = &fda;
- }
- rc = fcb_flash_read(fcb, sector, 0, fdap, sizeof(*fdap));
- if (rc) {
- return -EIO;
- }
- if (fdap->fd_magic == MK32(fcb->f_erase_value)) {
- return 0;
- }
- if (fdap->fd_magic != fcb_flash_magic(fcb)) {
- return -ENOMSG;
- }
- return 1;
- }
- int
- fcb_offset_last_n(struct fcb *fcb, uint8_t entries,
- struct fcb_entry *last_n_entry)
- {
- struct fcb_entry loc;
- int i;
- int rc;
-
- if (!entries) {
- entries = 1U;
- }
- i = 0;
- (void)memset(&loc, 0, sizeof(loc));
- while (!fcb_getnext(fcb, &loc)) {
- if (i == 0) {
-
- *last_n_entry = loc;
- }
-
- else if (i > (entries - 1)) {
- rc = fcb_getnext(fcb, last_n_entry);
- if (rc) {
-
- return -ENOENT;
- }
- }
- i++;
- }
- return (i == 0) ? -ENOENT : 0;
- }
- int
- fcb_clear(struct fcb *fcb)
- {
- int rc;
- rc = 0;
- while (!fcb_is_empty(fcb)) {
- rc = fcb_rotate(fcb);
- if (rc) {
- break;
- }
- }
- return rc;
- }
|