[Skiboot] [PATCH] libffs: Add helper get ffs_handle to the "OTHER_SIDE"

Cyril Bur cyril.bur at au1.ibm.com
Mon Dec 21 15:20:31 AEDT 2015


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 at au1.ibm.com>
---
This will have to applied after my previous series
https://patchwork.ozlabs.org/patch/558688/
 libflash/libffs.c | 36 +++++++++++++++++++++++++++++++++++-
 libflash/libffs.h | 23 +++++++++++++++++++++--
 2 files changed, 56 insertions(+), 3 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)
 {
diff --git a/libflash/libffs.h b/libflash/libffs.h
index ab3f9b1..0d0d5f5 100644
--- a/libflash/libffs.h
+++ b/libflash/libffs.h
@@ -37,9 +37,28 @@ struct ffs_handle;
 
 /* Init */
 
-int ffs_init(uint32_t offset, uint32_t max_size,
-		struct blocklevel_device *bl, struct ffs_handle **ffs, int mark_ecc);
+int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl,
+		struct ffs_handle **ffs, bool mark_ecc);
 
+/*
+ * Initialise a new ffs_handle to the "OTHER SIDE".
+ * Reuses the underlying blocklevel_device.
+ */
+int ffs_next_side(struct ffs_handle *ffs, struct ffs_handle **new_ffs,
+		bool mark_ecc);
+
+/*
+ * 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 of the 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);
 
 void ffs_close(struct ffs_handle *ffs);
 
-- 
2.6.3



More information about the Skiboot mailing list