[PATCH v2 4/6] bloblist: expose 'expand_by' as an output argument

Raymond Mao raymond.mao at linaro.org
Fri Jul 4 15:42:03 CEST 2025


Some advanced usecases of bloblist needs to know the actual bytes
expanded or shrunk after blob resizing.
For example, to support applying DT overlay from bloblist, firstly
the FDT blob needs to be resized for potential size increasing after
applying overlay. If the DT overlay blob is one of the following blobs
of the FDT, its address will be shifted after FDT blob resizing.
Thus, returning 'expand_by' helps the caller to get the shifted data
pointer when it comes to get the overlay for applying.

Signed-off-by: Raymond Mao <raymond.mao at linaro.org>
---
Changes in v2:
- None.

 common/bloblist.c      | 16 ++++++++--------
 include/bloblist.h     | 11 ++++++++++-
 test/common/bloblist.c | 17 +++++++++++------
 3 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/common/bloblist.c b/common/bloblist.c
index 550c0c78ffc..ae5273785eb 100644
--- a/common/bloblist.c
+++ b/common/bloblist.c
@@ -311,14 +311,14 @@ int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp)
 
 static int bloblist_resize_rec(struct bloblist_hdr *hdr,
 			       struct bloblist_rec *rec,
-			       int new_size)
+			       int new_size, int *expand_by)
 {
-	int expand_by;	/* Number of bytes to expand by (-ve to contract) */
 	int new_alloced;
 	ulong next_ofs;	/* Offset of the record after @rec */
 
-	expand_by = ALIGN(new_size - rec->size, BLOBLIST_BLOB_ALIGN);
-	new_alloced = ALIGN(hdr->used_size + expand_by, BLOBLIST_BLOB_ALIGN);
+	*expand_by = ALIGN(new_size - rec->size, BLOBLIST_BLOB_ALIGN);
+	new_alloced = ALIGN(hdr->used_size + *expand_by, BLOBLIST_BLOB_ALIGN);
+
 	if (new_size < 0) {
 		log_debug("Attempt to shrink blob size below 0 (%x)\n",
 			  new_size);
@@ -334,13 +334,13 @@ static int bloblist_resize_rec(struct bloblist_hdr *hdr,
 	/* Move the following blobs up or down, if this is not the last */
 	next_ofs = bloblist_blob_end_ofs(hdr, rec);
 	if (next_ofs != hdr->used_size) {
-		memmove((void *)hdr + next_ofs + expand_by,
+		memmove((void *)hdr + next_ofs + *expand_by,
 			(void *)hdr + next_ofs, hdr->used_size - next_ofs);
 	}
 	hdr->used_size = new_alloced;
 
 	/* Zero the new part of the blob */
-	if (expand_by > 0) {
+	if (*expand_by > 0) {
 		memset((void *)rec + rec_hdr_size(rec) + rec->size, '\0',
 		       new_size - rec->size);
 	}
@@ -351,7 +351,7 @@ static int bloblist_resize_rec(struct bloblist_hdr *hdr,
 	return 0;
 }
 
-int bloblist_resize(uint tag, int new_size)
+int bloblist_resize(uint tag, int new_size, int *expand_by)
 {
 	struct bloblist_hdr *hdr = gd->bloblist;
 	struct bloblist_rec *rec;
@@ -360,7 +360,7 @@ int bloblist_resize(uint tag, int new_size)
 	rec = bloblist_findrec(tag);
 	if (!rec)
 		return log_msg_ret("find", -ENOENT);
-	ret = bloblist_resize_rec(hdr, rec, new_size);
+	ret = bloblist_resize_rec(hdr, rec, new_size, expand_by);
 	if (ret)
 		return log_msg_ret("resize", ret);
 
diff --git a/include/bloblist.h b/include/bloblist.h
index c2d3065a43c..213285bbec6 100644
--- a/include/bloblist.h
+++ b/include/bloblist.h
@@ -73,6 +73,7 @@
 #define __BLOBLIST_H
 
 #include <mapmem.h>
+#include <errno.h>
 
 enum {
 	BLOBLIST_VERSION	= 1,
@@ -347,6 +348,7 @@ void *bloblist_ensure(uint tag, int size);
  */
 int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp);
 
+#if CONFIG_IS_ENABLED(BLOBLIST)
 /**
  * bloblist_resize() - resize a blob
  *
@@ -355,10 +357,17 @@ int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp);
  *
  * @tag:	Tag to add (enum bloblist_tag_t)
  * @new_size:	New size of the blob (>0 to expand, <0 to contract)
+ * @expand_by:	Number of bytes actually expanded by (-ve to contract)
  * Return: 0 if OK, -ENOSPC if the bloblist does not have enough space, -ENOENT
  * if the tag is not found
  */
-int bloblist_resize(uint tag, int new_size);
+int bloblist_resize(uint tag, int new_size, int *expand_by);
+#else
+static inline int bloblist_resize(uint tag, int new_size, int *expand_by)
+{
+	return -EPERM;
+}
+#endif
 
 /**
  * bloblist_new() - Create a new, empty bloblist of a given size
diff --git a/test/common/bloblist.c b/test/common/bloblist.c
index 797bde27025..c087d95c4b2 100644
--- a/test/common/bloblist.c
+++ b/test/common/bloblist.c
@@ -401,6 +401,7 @@ static int bloblist_test_grow(struct unit_test_state *uts)
 	void *blob1, *blob2, *blob1_new;
 	struct bloblist_hdr *hdr;
 	void *ptr;
+	int expand_by;
 
 	ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
 	hdr = ptr;
@@ -422,7 +423,7 @@ static int bloblist_test_grow(struct unit_test_state *uts)
 		    hdr->used_size);
 
 	/* Resize the first one */
-	ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
+	ut_assertok(bloblist_resize(TEST_TAG, small_size + 4, &expand_by));
 
 	/* The first one should not have moved, just got larger */
 	blob1_new = bloblist_find(TEST_TAG, small_size + 4);
@@ -455,6 +456,7 @@ static int bloblist_test_shrink(struct unit_test_state *uts)
 	struct bloblist_hdr *hdr;
 	int new_size;
 	void *ptr;
+	int expand_by;
 
 	ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
 
@@ -475,7 +477,7 @@ static int bloblist_test_shrink(struct unit_test_state *uts)
 
 	/* Resize the first one */
 	new_size = small_size - BLOBLIST_ALIGN - 4;
-	ut_assertok(bloblist_resize(TEST_TAG, new_size));
+	ut_assertok(bloblist_resize(TEST_TAG, new_size, &expand_by));
 
 	/* The first one should not have moved, just got smaller */
 	blob1_new = bloblist_find(TEST_TAG, new_size);
@@ -505,6 +507,7 @@ static int bloblist_test_resize_fail(struct unit_test_state *uts)
 	void *blob1, *blob2;
 	int new_size;
 	void *ptr;
+	int expand_by;
 
 	ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
 
@@ -522,11 +525,12 @@ static int bloblist_test_resize_fail(struct unit_test_state *uts)
 		    hdr->used_size);
 
 	/* Resize the first one, to check the boundary conditions */
-	ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
+	ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1, &expand_by));
 
 	new_size = small_size + (hdr->total_size - hdr->used_size);
-	ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
-	ut_assertok(bloblist_resize(TEST_TAG, new_size));
+	ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1,
+					     &expand_by));
+	ut_assertok(bloblist_resize(TEST_TAG, new_size, &expand_by));
 
 	return 0;
 }
@@ -540,6 +544,7 @@ static int bloblist_test_resize_last(struct unit_test_state *uts)
 	void *blob1, *blob2, *blob2_new;
 	int alloced_val;
 	void *ptr;
+	int expand_by;
 
 	ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
 	memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
@@ -561,7 +566,7 @@ static int bloblist_test_resize_last(struct unit_test_state *uts)
 	ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
 
 	/* Resize the second one, checking nothing changes */
-	ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
+	ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4, &expand_by));
 
 	blob2_new = bloblist_find(TEST_TAG2, small_size + 4);
 	ut_asserteq_ptr(blob2, blob2_new);
-- 
2.25.1



More information about the U-Boot mailing list