aboutsummaryrefslogtreecommitdiff
path: root/libflash/libffs.c
diff options
context:
space:
mode:
authorCyril Bur <cyril.bur@au1.ibm.com>2018-03-15 16:58:24 +1100
committerStewart Smith <stewart@linux.ibm.com>2018-04-09 03:45:23 -0500
commit1622957255a66c026d9502219171b0f9e4996b4c (patch)
tree7972a3882ae1803b4405b90eb1ab1be32658663b /libflash/libffs.c
parent79316cb6aca6fc79585f4f47c18a37f2eb177780 (diff)
downloadskiboot-1622957255a66c026d9502219171b0f9e4996b4c.zip
skiboot-1622957255a66c026d9502219171b0f9e4996b4c.tar.gz
skiboot-1622957255a66c026d9502219171b0f9e4996b4c.tar.bz2
libflash/libffs: Allow caller to specifiy header partition
An FFS TOC is comprised of two parts. A small header which has a magic and very minimmal information about the TOC which will be common to all partitions, things like number of patritions, block sizes and the like. Following this small header are a series of entries. Importantly there is always an entry which encompases the TOC its self, this is usually called the 'part' partition. Currently libffs always assumes that the 'part' partition is at zero. While there is always a TOC and zero there doesn't actually have to be. PNORs may have multiple TOCs within them, therefore libffs needs to be flexible enough to allow callers to specify TOCs not at zero. The 'part' partition is otherwise a regular partition which may have flags associated with it. libffs should allow the user to set the flags for the 'part' partition. This patch achieves both by allowing the caller to specify the 'part' partition. The caller can not and libffs will provide a sensible default. Signed-off-by: Cyril Bur <cyril.bur@au1.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
Diffstat (limited to 'libflash/libffs.c')
-rw-r--r--libflash/libffs.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/libflash/libffs.c b/libflash/libffs.c
index b4a8116..ceaf0fd 100644
--- a/libflash/libffs.c
+++ b/libflash/libffs.c
@@ -684,8 +684,8 @@ int ffs_hdr_finalise(struct blocklevel_device *bl, struct ffs_hdr *hdr)
}
/* Don't really care if this fails */
- blocklevel_erase(bl, hdr->base, hdr->size);
- rc = blocklevel_write(bl, hdr->base, real_hdr,
+ blocklevel_erase(bl, hdr->part->base, hdr->size);
+ rc = blocklevel_write(bl, hdr->part->base, real_hdr,
ffs_hdr_raw_size(num_entries));
if (rc)
goto out;
@@ -770,7 +770,8 @@ int ffs_entry_set_act_size(struct ffs_entry *ent, uint32_t actual_size)
return 0;
}
-int ffs_hdr_new(uint32_t block_size, uint32_t block_count, struct ffs_hdr **r)
+int ffs_hdr_new(uint32_t block_size, uint32_t block_count,
+ struct ffs_entry **e, struct ffs_hdr **r)
{
struct ffs_hdr *ret;
struct ffs_entry *part_table;
@@ -786,12 +787,23 @@ int ffs_hdr_new(uint32_t block_size, uint32_t block_count, struct ffs_hdr **r)
ret->entries = calloc(HDR_ENTRIES_NUM, sizeof(struct ffs_entry *));
ret->entries_size = HDR_ENTRIES_NUM;
- /* Don't know how big it will be, ffs_hdr_finalise() will fix */
- rc = ffs_entry_new("part", 0, 0, &part_table);
- if (rc) {
- free(ret);
- return rc;
+ if (!e || !(*e)) {
+ /* Don't know how big it will be, ffs_hdr_finalise() will fix */
+ rc = ffs_entry_new("part", 0, 0, &part_table);
+ if (rc) {
+ free(ret);
+ return rc;
+ }
+ if (e)
+ *e = part_table;
+ } else {
+ part_table = *e;
}
+
+ /* If the user still holds a ref to e, then inc the refcount */
+ if (e)
+ part_table->ref++;
+
ret->part = part_table;
part_table->pid = FFS_PID_TOPLEVEL;