aboutsummaryrefslogtreecommitdiff
path: root/libflash/libffs.c
diff options
context:
space:
mode:
authorCyril Bur <cyril.bur@au1.ibm.com>2015-12-21 15:20:31 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-01-08 11:36:20 +1100
commit40eed43c9c0bcbaf6ada461fe7e9edb89c2478f1 (patch)
treed6b000a2a5a63e3a97aa2f9967887f08e5925c30 /libflash/libffs.c
parent42b13e5fdef8c9eaa21282092b92d9fa7df3e8bf (diff)
downloadskiboot-40eed43c9c0bcbaf6ada461fe7e9edb89c2478f1.zip
skiboot-40eed43c9c0bcbaf6ada461fe7e9edb89c2478f1.tar.gz
skiboot-40eed43c9c0bcbaf6ada461fe7e9edb89c2478f1.tar.bz2
libffs: Add helper get ffs_handle to the "OTHER_SIDE"
Some FFS structures will have a partition called "OTHER_SIDE", this is a pointer to another ffs TOC on which another ffs_handle can be instantiated. Currently users of libffs would have to query for the presence of this partition and then initialise a new ffs_handle themselves. As accessing the "other" side appears to be becoming a common operation this convenience function should prove useful. Furthermore, it is possible for these multiTOC flash chips to be circular, that is the "OTHER_SIDE" partition of 'secondary' TOC points back to the initial TOC. The solution is to add a comparison function capable of detecting when repeated calls to ffs_next_side() go full circle. It should be noted here that this is all the comparator function is designed to detect, it will not be able to detect two identical TOCs opened with different blocklevel_devices as this would require the ability to compare blocklevel_devices. Signed-off-by: Cyril Bur <cyril.bur@au1.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'libflash/libffs.c')
-rw-r--r--libflash/libffs.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/libflash/libffs.c b/libflash/libffs.c
index f700da2..401b4db 100644
--- a/libflash/libffs.c
+++ b/libflash/libffs.c
@@ -72,7 +72,7 @@ static int ffs_check_convert_header(struct ffs_hdr *dst, struct ffs_hdr *src)
}
int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl,
- struct ffs_handle **ffs, int mark_ecc)
+ struct ffs_handle **ffs, bool mark_ecc)
{
struct ffs_hdr hdr;
struct ffs_handle *f;
@@ -271,6 +271,40 @@ int ffs_part_info(struct ffs_handle *ffs, uint32_t part_idx,
return 0;
}
+/*
+ * There are quite a few ways one might consider two ffs_handles to be the
+ * same. For the purposes of this function we are trying to detect a fairly
+ * specific scenario:
+ * Consecutive calls to ffs_next_side() may succeed but have gone circular.
+ * It is possible that the OTHER_SIDE partition in one TOC actually points
+ * back to the TOC to first ffs_handle.
+ * This function compares for this case, therefore the requirements are
+ * simple, the underlying blocklevel_devices must be the same along with
+ * the toc_offset and the max_size.
+ */
+int ffs_cmp(struct ffs_handle *one, struct ffs_handle *two)
+{
+ return (!one && !two) || (one && two && one->bl == two->bl
+ && one->toc_offset == two->toc_offset
+ && one->max_size == two->max_size);
+}
+
+int ffs_next_side(struct ffs_handle *ffs, struct ffs_handle **new_ffs,
+ bool mark_ecc)
+{
+ int rc;
+ uint32_t index, offset, max_size;
+ rc = ffs_lookup_part(ffs, "OTHER_SIDE", &index);
+ if (rc)
+ return rc;
+
+ rc = ffs_part_info(ffs, index, NULL, &offset, &max_size, NULL, NULL);
+ if (rc)
+ return rc;
+
+ return ffs_init(offset, max_size, ffs->bl, new_ffs, mark_ecc);
+}
+
int ffs_update_act_size(struct ffs_handle *ffs, uint32_t part_idx,
uint32_t act_size)
{