From patchwork Tue Mar 22 03:39:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyril Bur X-Patchwork-Id: 600383 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3qTdlV2rMbz9s3T for ; Tue, 22 Mar 2016 14:41:10 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3qTdlV2B7jzDqF6 for ; Tue, 22 Mar 2016 14:41:10 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from e23smtp03.au.ibm.com (e23smtp03.au.ibm.com [202.81.31.145]) (using TLSv1.2 with cipher CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3qTdlQ3Rn1zDq6X for ; Tue, 22 Mar 2016 14:41:06 +1100 (AEDT) Received: from localhost by e23smtp03.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 22 Mar 2016 13:41:03 +1000 Received: from d23dlp02.au.ibm.com (202.81.31.213) by e23smtp03.au.ibm.com (202.81.31.209) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 22 Mar 2016 13:41:02 +1000 X-IBM-Helo: d23dlp02.au.ibm.com X-IBM-MailFrom: cyril.bur@au1.ibm.com X-IBM-RcptTo: skiboot@lists.ozlabs.org Received: from d23relay09.au.ibm.com (d23relay09.au.ibm.com [9.185.63.181]) by d23dlp02.au.ibm.com (Postfix) with ESMTP id 07CE42BB0057 for ; Tue, 22 Mar 2016 14:41:02 +1100 (EST) Received: from d23av01.au.ibm.com (d23av01.au.ibm.com [9.190.234.96]) by d23relay09.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u2M3er9M8716434 for ; Tue, 22 Mar 2016 14:41:01 +1100 Received: from d23av01.au.ibm.com (localhost [127.0.0.1]) by d23av01.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u2M3eTmg019015 for ; Tue, 22 Mar 2016 14:40:29 +1100 Received: from ozlabs.au.ibm.com (ozlabs.au.ibm.com [9.192.253.14]) by d23av01.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u2M3eSvj017992 for ; Tue, 22 Mar 2016 14:40:29 +1100 Received: from camb691.ozlabs.ibm.com (haven.au.ibm.com [9.192.254.114]) (using TLSv1.2 with cipher AES128-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.au.ibm.com (Postfix) with ESMTPSA id 9F149A0119 for ; Tue, 22 Mar 2016 14:40:03 +1100 (AEDT) From: Cyril Bur To: skiboot@lists.ozlabs.org Date: Tue, 22 Mar 2016 14:39:43 +1100 Message-Id: <1458617983-19779-1-git-send-email-cyril.bur@au1.ibm.com> X-Mailer: git-send-email 2.7.3 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16032203-0009-0000-0000-0000068F043A Subject: [Skiboot] [RFC] libflash/libffs: Rework libffs X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This patch attempts a rework of libffs to prepare it for future changes. Firstly the types are split in two: 1. Packed, big endian structures used to map exactly how the data is on flash. 2. CPU endian, sane valued, not packed structures used to manipulate FFS data. Secondly: The packed struct can use BE types so that in future tools like sparse can be run over the code to check for endian conversion bugs. Thirdly: defines of sizeof(struct ...) were removed for clarity. Finally: For ease of manipulation, the in memory FFS structures contain a linked list of entries as this will make addition and removal operations much easier. This patch should be invisible to consumers of libffs. Signed-off-by: Cyril Bur --- libflash/ffs.h | 139 +++++++++++++++++++-------- libflash/libffs.c | 281 +++++++++++++++++++++++++++++------------------------- libflash/libffs.h | 11 +++ 3 files changed, 262 insertions(+), 169 deletions(-) diff --git a/libflash/ffs.h b/libflash/ffs.h index 5cb6778..3d1ac8f 100644 --- a/libflash/ffs.h +++ b/libflash/ffs.h @@ -28,8 +28,11 @@ #if defined(__KERNEL__) #include #else +#define CCAN_SHORT_TYPES_H +#include #include #endif +#include /* The version of this partition implementation */ #define FFS_VERSION_1 1 @@ -40,25 +43,13 @@ /* The maximum length of the partition name */ #define PART_NAME_MAX 15 -/* - * Sizes of the data structures - */ -#define FFS_HDR_SIZE sizeof(struct ffs_hdr) -#define FFS_ENTRY_SIZE sizeof(struct ffs_entry) - -/* - * Sizes of the data structures w/o checksum - */ -#define FFS_HDR_SIZE_CSUM (FFS_HDR_SIZE - sizeof(uint32_t)) -#define FFS_ENTRY_SIZE_CSUM (FFS_ENTRY_SIZE - sizeof(uint32_t)) - /* pid of logical partitions/containers */ #define FFS_PID_TOPLEVEL 0xFFFFFFFF /* * Type of image contained w/in partition */ -enum type { +enum ffs_type { FFS_TYPE_DATA = 1, FFS_TYPE_LOGICAL = 2, FFS_TYPE_PARTITION = 3, @@ -74,7 +65,9 @@ enum type { #define FFS_ENRY_INTEG_ECC 0x8000 /** - * struct ffs_entry_user - User data enties + * struct __ffs_entry_user - On flash user data entries + * + * Represents the on flash layout of FFS structures * * @chip: Chip Select (0,1) * @compressType: Compression Indication/alg (0=not compressed) @@ -84,18 +77,37 @@ enum type { * @freeMisc[2]: Unused Miscellaneious Info * @freeUser[14]: Unused User Data */ +struct __ffs_entry_user { + uint8_t chip; + uint8_t compresstype; + be16 datainteg; + uint8_t vercheck; + uint8_t miscflags; + uint8_t freemisc[2]; + be32 reserved[14]; +} __attribute__ ((packed)); + +/** + * struct ffs_entry_user - User data entries + * + * @chip: Chip Select (0,1) + * @compressType: Compression Indication/alg (0=not compressed) + * @dataInteg: Indicates Data Integrity mechanism + * @verCheck: Indicates Version check type + * @miscFlags: Misc Partition related Flags + */ struct ffs_entry_user { - uint8_t chip; - uint8_t compresstype; + uint8_t chip; + uint8_t compresstype; uint16_t datainteg; - uint8_t vercheck; - uint8_t miscflags; - uint8_t freemisc[2]; - uint32_t reserved[14]; + uint8_t vercheck; + uint8_t miscflags; }; /** - * struct ffs_entry - Partition entry + * struct __ffs_entry - On flash partition entry + * + * Represents the on flash layout of FFS structures * * @name: Opaque null terminated string * @base: Starting offset of partition in flash (in hdr.block_size) @@ -109,22 +121,50 @@ struct ffs_entry_user { * @user: User data (optional) * @checksum: Partition entry checksum (includes all above) */ +struct __ffs_entry { + char name[PART_NAME_MAX + 1]; + be32 base; + be32 size; + be32 pid; + be32 id; + be32 type; + be32 flags; + be32 actual; + be32 resvd[4]; + struct __ffs_entry_user user; + /* The checksum is actually endian agnostic */ + uint32_t checksum; +} __attribute__ ((packed)); + +/** + * struct ffs_entry - Partition entry + * + * @name: Opaque null terminated string + * @base: Starting offset of partition in flash (in bytes) + * @size: Partition size (in bytes) + * @actual: Actual partition size (in bytes) + * @pid: Parent partition entry (FFS_PID_TOPLEVEL for toplevel) + * @type: Describe type of partition + * @flags: Partition attributes (optional) + * @user: User data (optional) + */ struct ffs_entry { - char name[PART_NAME_MAX + 1]; + char name[PART_NAME_MAX + 1]; uint32_t base; uint32_t size; + uint32_t actual; uint32_t pid; - uint32_t id; - uint32_t type; + enum ffs_type type; uint32_t flags; - uint32_t actual; - uint32_t resvd[4]; struct ffs_entry_user user; - uint32_t checksum; -} __attribute__ ((packed)); + struct list_node list; +}; + /** - * struct ffs_hdr - FSP Flash Structure header + * struct __ffs_hdr - On flash FSP Flash Structure header + * + * Represents the on flash layout of FFS structures * * @magic: Eye catcher/corruption detector * @version: Version of the structure @@ -133,22 +173,39 @@ struct ffs_entry { * @entry_count: Number of struct ffs_entry elements in @entries array * @block_size: Size of block on device (in bytes) * @block_count: Number of blocks on device - * @resvd: Reserved words for future use + * @resvd[4]: Reserved words for future use * @checksum: Header checksum * @entries: Pointer to array of partition entries */ -struct ffs_hdr { - uint32_t magic; - uint32_t version; - uint32_t size; - uint32_t entry_size; - uint32_t entry_count; - uint32_t block_size; - uint32_t block_count; - uint32_t resvd[4]; - uint32_t checksum; - struct ffs_entry entries[]; +struct __ffs_hdr { + be32 magic; + be32 version; + be32 size; + be32 entry_size; + be32 entry_count; + be32 block_size; + be32 block_count; + be32 resvd[4]; + /* The checksum is actually endian agnostic */ + uint32_t checksum; + struct __ffs_entry entries[]; } __attribute__ ((packed)); +/** + * struct ffs_hdr - FSP Flash Structure header + * + * @version: Version of the structure + * @size: Size of partition table (in bytes) + * @block_size: Size of block on device (in bytes) + * @block_count: Number of blocks on device + * @entries: List of partition entries + */ +struct ffs_hdr { + uint32_t version; + uint32_t size; + uint32_t block_size; + uint32_t block_count; + struct list_head entries; +}; #endif /* __FFS_H__ */ diff --git a/libflash/libffs.c b/libflash/libffs.c index 4d57992..2c62cd0 100644 --- a/libflash/libffs.c +++ b/libflash/libffs.c @@ -25,22 +25,14 @@ #include #endif -#include - #include "libffs.h" -enum ffs_type { - ffs_type_flash, - ffs_type_image, -}; - struct ffs_handle { struct ffs_hdr hdr; /* Converted header */ - enum ffs_type type; uint32_t toc_offset; uint32_t max_size; - void *cache; - uint32_t cached_size; + /* The converted header knows how big this is */ + struct __ffs_hdr *cache; struct blocklevel_device *bl; }; @@ -53,32 +45,103 @@ static uint32_t ffs_checksum(void* data, size_t size) return csum; } -static int ffs_check_convert_header(struct ffs_hdr *dst, struct ffs_hdr *src) +/* Helper functions for typesafety and size safety */ +static uint32_t ffs_hdr_checksum(struct __ffs_hdr *hdr) +{ + return ffs_checksum(hdr, sizeof(struct __ffs_hdr)); +} + +static uint32_t ffs_entry_checksum(struct __ffs_entry *ent) { - dst->magic = be32_to_cpu(src->magic); - if (dst->magic != FFS_MAGIC) + return ffs_checksum(ent, sizeof(struct __ffs_entry)); +} + +static int ffs_check_convert_header(struct ffs_hdr *dst, struct __ffs_hdr *src) +{ + if (be32_to_cpu(src->magic) != FFS_MAGIC) return FFS_ERR_BAD_MAGIC; dst->version = be32_to_cpu(src->version); if (dst->version != FFS_VERSION_1) return FFS_ERR_BAD_VERSION; - if (ffs_checksum(src, FFS_HDR_SIZE) != 0) + if (ffs_hdr_checksum(src) != 0) return FFS_ERR_BAD_CKSUM; - dst->size = be32_to_cpu(src->size); - dst->entry_size = be32_to_cpu(src->entry_size); - dst->entry_count = be32_to_cpu(src->entry_count); + if (be32_to_cpu(src->entry_size) != sizeof(struct __ffs_entry)) + return FFS_ERR_BAD_SIZE; dst->block_size = be32_to_cpu(src->block_size); + dst->size = be32_to_cpu(src->size) * dst->block_size; dst->block_count = be32_to_cpu(src->block_count); return 0; } +static int ffs_entry_to_flash(struct ffs_hdr *hdr, + struct __ffs_entry *dst, struct ffs_entry *src) +{ + int index = 1; /* On flash indexes start at 1 */ + struct ffs_entry *ent; + list_for_each(&hdr->entries, ent, list) { + if (ent == src) + break; + index++; + } + + if (!ent) + return FFS_ERR_PART_NOT_FOUND; + + memcpy(dst->name, src->name, sizeof(dst->name)); + dst->name[PART_NAME_MAX] = '\0'; + dst->base = cpu_to_be32(src->base * hdr->block_size); + dst->size = cpu_to_be32(src->size * hdr->block_size); + dst->pid = cpu_to_be32(src->pid); + dst->id = cpu_to_be32(index); + dst->type = cpu_to_be32(src->type); /* Check that it is valid? */ + dst->flags = cpu_to_be32(src->flags); + dst->actual = cpu_to_be32(src->actual); + dst->user.datainteg = cpu_to_be16(src->user.datainteg); + dst->checksum = ffs_entry_checksum(dst); + + return 0; +} + +static int ffs_entry_to_cpu(struct ffs_hdr *hdr, + struct ffs_entry *dst, struct __ffs_entry *src) +{ + if (ffs_entry_checksum(src) != 0) + return FFS_ERR_BAD_CKSUM; + memcpy(dst->name, src->name, sizeof(dst->name)); + dst->name[PART_NAME_MAX] = '\0'; + dst->base = be32_to_cpu(src->base) * hdr->block_size; + dst->size = be32_to_cpu(src->size) * hdr->block_size; + dst->actual = be32_to_cpu(src->actual); + dst->pid = be32_to_cpu(src->pid); + dst->type = be32_to_cpu(src->type); /* Check that it is valid? */ + dst->flags = be32_to_cpu(src->flags); + dst->user.datainteg = be16_to_cpu(src->user.datainteg); + return 0; +} + +static struct ffs_entry *ffs_get_part(struct ffs_handle *ffs, uint32_t index) +{ + int i = 0; + struct ffs_entry *ent; + + list_for_each(&ffs->hdr.entries, ent, list) { + if (i == index) + break; + i++; + } + + return ent; +} + int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl, struct ffs_handle **ffs, bool mark_ecc) { - struct ffs_hdr hdr; - struct ffs_hdr blank_hdr; + struct __ffs_hdr blank_hdr; + struct __ffs_hdr raw_hdr; struct ffs_handle *f; uint32_t total_size; + struct ffs_entry *ent; int rc, i; if (!ffs || !bl) @@ -97,7 +160,7 @@ int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl, return FLASH_ERR_PARM_ERROR; /* Read flash header */ - rc = blocklevel_read(bl, offset, &hdr, sizeof(hdr)); + rc = blocklevel_read(bl, offset, &raw_hdr, sizeof(raw_hdr)); if (rc) { FL_ERR("FFS: Error %d reading flash header\n", rc); return rc; @@ -106,17 +169,17 @@ int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl, /* * Flash controllers can get deconfigured or otherwise upset, when this * happens they return all 0xFF bytes. - * An ffs_hdr consisting of all 0xFF cannot be valid and it would be + * An __ffs_hdr consisting of all 0xFF cannot be valid and it would be * nice to drop a hint to the user to help with debugging. This will * help quickly differentiate between flash corruption and standard * type 'reading from the wrong place' errors vs controller errors or * reading erased data. */ - memset(&blank_hdr, UINT_MAX, sizeof(struct ffs_hdr)); - if (memcmp(&blank_hdr, &hdr, sizeof(struct ffs_hdr)) == 0) { + memset(&blank_hdr, UINT_MAX, sizeof(struct __ffs_hdr)); + if (memcmp(&blank_hdr, &raw_hdr, sizeof(struct __ffs_hdr)) == 0) { FL_ERR("FFS: Reading the flash has returned all 0xFF.\n"); - FL_ERR("Are you reading erased flash?\n"); - FL_ERR("Is something else using the flash controller?\n"); + FL_ERR(" Are you reading erased flash?\n"); + FL_ERR(" Is something else using the flash controller?\n"); return FLASH_ERR_BAD_READ; } @@ -131,160 +194,125 @@ int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl, f->bl = bl; /* Convert and check flash header */ - rc = ffs_check_convert_header(&f->hdr, &hdr); + rc = ffs_check_convert_header(&f->hdr, &raw_hdr); if (rc) { FL_ERR("FFS: Error %d checking flash header\n", rc); goto out; } /* - * Decide how much of the image to grab to get the whole - * partition map. + * Grab the entire partition header */ - f->cached_size = f->hdr.block_size * f->hdr.size; - FL_DBG("FFS: Partition map size: 0x%x\n", f->cached_size); + FL_DBG("FFS: Partition map size: 0x%x\n", f->hdr.size); + if (offset + f->hdr.size > max_size) { + FL_ERR("FFS: Partition table is bigger than max_size\n"); + goto out; + } /* Allocate cache */ - f->cache = malloc(f->cached_size); + f->cache = malloc(f->hdr.size); if (!f->cache) { rc = FLASH_ERR_MALLOC_FAILED; goto out; } /* Read the cached map */ - rc = blocklevel_read(bl, offset, f->cache, f->cached_size); + rc = blocklevel_read(bl, offset, f->cache, f->hdr.size); if (rc) { FL_ERR("FFS: Error %d reading flash partition map\n", rc); goto out; } - if (mark_ecc) { - uint32_t start, total_size; - bool ecc; - for (i = 0; i < f->hdr.entry_count; i++) { - rc = ffs_part_info(f, i, NULL, &start, &total_size, - NULL, &ecc); + list_head_init(&f->hdr.entries); + for (i = 0; i < be32_to_cpu(raw_hdr.entry_count); i++) { + ent = calloc(1, sizeof(struct ffs_entry)); + if (!ent) { + rc = FLASH_ERR_MALLOC_FAILED; + goto out; + } + + list_add_tail(&f->hdr.entries, &ent->list); + rc = ffs_entry_to_cpu(&f->hdr, ent, &f->cache->entries[i]); + if (rc) + goto out; + + if (mark_ecc && has_ecc(ent)) { + rc = blocklevel_ecc_protect(bl, ent->base, ent->size); if (rc) { - FL_ERR("FFS: Failed to read ffs partition %d\n", - i); + FL_ERR("Failed to blocklevel_ecc_protect(0x%08x, 0x%08x)\n", + ent->base, ent->size); goto out; } - if (ecc) { - rc = blocklevel_ecc_protect(bl, start, total_size); - if (rc) { - FL_ERR("Failed to blocklevel_ecc_protect(0x%08x, 0x%08x)\n", - start, total_size); - goto out; - } - } /* ecc */ - } /* for */ + } } out: if (rc == 0) *ffs = f; else - free(f); + ffs_close(f); return rc; } void ffs_close(struct ffs_handle *ffs) { - if (ffs->cache) - free(ffs->cache); - free(ffs); -} + struct ffs_entry *ent, *next; -static struct ffs_entry *ffs_get_part(struct ffs_handle *ffs, uint32_t index, - uint32_t *out_offset) -{ - uint32_t esize = ffs->hdr.entry_size; - uint32_t offset = FFS_HDR_SIZE + index * esize; - - if (index > ffs->hdr.entry_count) - return NULL; - if (out_offset) - *out_offset = ffs->toc_offset + offset; - return (struct ffs_entry *)(ffs->cache + offset); -} + list_for_each_safe(&ffs->hdr.entries, ent, next, list) { + list_del(&ent->list); + free(ent); + } -static int ffs_check_convert_entry(struct ffs_entry *dst, struct ffs_entry *src) -{ - if (ffs_checksum(src, FFS_ENTRY_SIZE) != 0) - return FFS_ERR_BAD_CKSUM; - memcpy(dst->name, src->name, sizeof(dst->name)); - dst->base = be32_to_cpu(src->base); - dst->size = be32_to_cpu(src->size); - dst->pid = be32_to_cpu(src->pid); - dst->id = be32_to_cpu(src->id); - dst->type = be32_to_cpu(src->type); - dst->flags = be32_to_cpu(src->flags); - dst->actual = be32_to_cpu(src->actual); - dst->user.datainteg = be16_to_cpu(src->user.datainteg); + if (ffs->cache) + free(ffs->cache); - return 0; + free(ffs); } int ffs_lookup_part(struct ffs_handle *ffs, const char *name, uint32_t *part_idx) { - struct ffs_entry ent; - uint32_t i; - int rc; + int i = 0; + struct ffs_entry *ent; - /* Lookup the requested partition */ - for (i = 0; i < ffs->hdr.entry_count; i++) { - struct ffs_entry *src_ent = ffs_get_part(ffs, i, NULL); - rc = ffs_check_convert_entry(&ent, src_ent); - if (rc) { - FL_ERR("FFS: Bad entry %d in partition map\n", i); - continue; - } - if (!strncmp(name, ent.name, sizeof(ent.name))) + list_for_each(&ffs->hdr.entries, ent, list) { + if (!strncmp(name, ent->name, sizeof(ent->name))) break; + i++; } - if (i >= ffs->hdr.entry_count) - return FFS_ERR_PART_NOT_FOUND; + if (part_idx) *part_idx = i; - return 0; + return ent ? 0 : FFS_ERR_PART_NOT_FOUND; } int ffs_part_info(struct ffs_handle *ffs, uint32_t part_idx, char **name, uint32_t *start, uint32_t *total_size, uint32_t *act_size, bool *ecc) { - struct ffs_entry *raw_ent; - struct ffs_entry ent; + struct ffs_entry *ent; char *n; - int rc; - - if (part_idx >= ffs->hdr.entry_count) - return FFS_ERR_PART_NOT_FOUND; - raw_ent = ffs_get_part(ffs, part_idx, NULL); - if (!raw_ent) + ent = ffs_get_part(ffs, part_idx); + if (!ent) return FFS_ERR_PART_NOT_FOUND; - rc = ffs_check_convert_entry(&ent, raw_ent); - if (rc) { - FL_ERR("FFS: Bad entry %d in partition map\n", part_idx); - return rc; - } if (start) - *start = ent.base * ffs->hdr.block_size; + *start = ent->base; if (total_size) - *total_size = ent.size * ffs->hdr.block_size; + *total_size = ent->size; if (act_size) - *act_size = ent.actual; + *act_size = ent->actual; if (ecc) - *ecc = ((ent.user.datainteg & FFS_ENRY_INTEG_ECC) != 0); + *ecc = has_ecc(ent); if (name) { n = malloc(PART_NAME_MAX + 1); + if (!n) + return FLASH_ERR_MALLOC_FAILED; memset(n, 0, PART_NAME_MAX + 1); - strncpy(n, ent.name, PART_NAME_MAX); + strncpy(n, ent->name, PART_NAME_MAX); *name = n; } return 0; @@ -334,33 +362,30 @@ int ffs_update_act_size(struct ffs_handle *ffs, uint32_t part_idx, uint32_t act_size) { struct ffs_entry *ent; + struct __ffs_entry raw_ent; uint32_t offset; + int rc; - if (part_idx >= ffs->hdr.entry_count) { - FL_DBG("FFS: Entry out of bound\n"); - return FFS_ERR_PART_NOT_FOUND; - } - - ent = ffs_get_part(ffs, part_idx, &offset); + ent = ffs_get_part(ffs, part_idx); if (!ent) { FL_DBG("FFS: Entry not found\n"); return FFS_ERR_PART_NOT_FOUND; } + offset = ent->base; FL_DBG("FFS: part index %d at offset 0x%08x\n", part_idx, offset); - /* - * NOTE: We are accessing the unconverted ffs_entry from the PNOR here - * (since we are going to write it back) so we need to be endian safe. - */ - if (ent->actual == cpu_to_be32(act_size)) { + if (ent->actual == act_size) { FL_DBG("FFS: ent->actual alrady matches: 0x%08x==0x%08x\n", - cpu_to_be32(act_size), ent->actual); + act_size, ent->actual); return 0; } - ent->actual = cpu_to_be32(act_size); - ent->checksum = ffs_checksum(ent, FFS_ENTRY_SIZE_CSUM); + ent->actual = act_size; + + rc = ffs_entry_to_flash(&ffs->hdr, &raw_ent, ent); + if (rc) + return rc; - return blocklevel_write(ffs->bl, offset, ent, FFS_ENTRY_SIZE); + return blocklevel_write(ffs->bl, offset, &raw_ent, sizeof(struct __ffs_entry)); } diff --git a/libflash/libffs.h b/libflash/libffs.h index a9ff574..23ccb8f 100644 --- a/libflash/libffs.h +++ b/libflash/libffs.h @@ -22,6 +22,7 @@ /* FFS handle, opaque */ struct ffs_handle; +struct ffs_entry; /* Error codes: * @@ -34,6 +35,16 @@ struct ffs_handle; #define FFS_ERR_BAD_CKSUM 102 #define FFS_ERR_PART_NOT_FOUND 103 #define FFS_ERR_BAD_ECC 104 +#define FFS_ERR_BAD_SIZE 105 +#define FFS_ERR_BAD_PART_NAME 106 +#define FFS_ERR_BAD_PART_BASE 107 +#define FFS_ERR_BAD_PART_SIZE 108 +#define FFS_ERR_BAD_PART_PID 109 + +static inline bool has_ecc(struct ffs_entry *ent) +{ + return ((ent->user.datainteg & FFS_ENRY_INTEG_ECC) != 0); +} /* Init */