[PATCH v2 11/18] bloblist: Reduce blob-header size
Raymond Mao
raymond.mao at linaro.org
Mon Nov 27 20:50:22 CET 2023
From: Simon Glass <sjg at chromium.org>
The v0.9 spec provides for an 8-byte header for each blob, with fewer
fields.
The blob start address should be aligned to the alignment specified
by the bloblist header.
Update the implementation to match this.
Signed-off-by: Simon Glass <sjg at chromium.org>
Co-developed-by: Raymond Mao <raymond.mao at linaro.org>
Signed-off-by: Raymond Mao <raymond.mao at linaro.org>
---
Changes in v2
- Update the blob start address to align to the alignment required by
the bloblist header.
- Define the macros of bloblist header size and bloblist record header
size as the size of their structures.
common/bloblist.c | 17 +++++++++--------
include/bloblist.h | 33 ++++++++++++++++++++++-----------
test/bloblist.c | 16 ++++++++--------
3 files changed, 39 insertions(+), 27 deletions(-)
diff --git a/common/bloblist.c b/common/bloblist.c
index 59a092d4cd..55a7e1f591 100644
--- a/common/bloblist.c
+++ b/common/bloblist.c
@@ -85,12 +85,14 @@ static struct bloblist_rec *bloblist_first_blob(struct bloblist_hdr *hdr)
static inline uint rec_hdr_size(struct bloblist_rec *rec)
{
- return rec->hdr_size;
+ return (rec->tag_and_hdr_size & BLOBLISTR_HDR_SIZE_MASK) >>
+ BLOBLISTR_HDR_SIZE_SHIFT;
}
static inline uint rec_tag(struct bloblist_rec *rec)
{
- return rec->tag;
+ return (rec->tag_and_hdr_size & BLOBLISTR_TAG_MASK) >>
+ BLOBLISTR_TAG_SHIFT;
}
static ulong bloblist_blob_end_ofs(struct bloblist_hdr *hdr,
@@ -99,7 +101,7 @@ static ulong bloblist_blob_end_ofs(struct bloblist_hdr *hdr,
ulong offset;
offset = (void *)rec - (void *)hdr;
- offset += rec_hdr_size(rec) + ALIGN(rec->size, BLOBLIST_ALIGN);
+ offset += rec_hdr_size(rec) + ALIGN(rec->size, 1 << hdr->align_log2);
return offset;
}
@@ -143,7 +145,7 @@ static int bloblist_addrec(uint tag, int size, int align_log2,
int data_start, aligned_start, new_alloced;
if (!align_log2)
- align_log2 = BLOBLIST_ALIGN_LOG2;
+ align_log2 = BLOBLIST_BLOB_ALIGN_LOG2;
/* Figure out where the new data will start */
data_start = map_to_sysmem(hdr) + hdr->alloced + sizeof(*rec);
@@ -176,8 +178,7 @@ static int bloblist_addrec(uint tag, int size, int align_log2,
}
rec = (void *)hdr + hdr->alloced;
- rec->tag = tag;
- rec->hdr_size = sizeof(struct bloblist_rec);
+ rec->tag_and_hdr_size = tag | sizeof(*rec) << BLOBLISTR_HDR_SIZE_SHIFT;
rec->size = size;
/* Zero the record data */
@@ -281,8 +282,8 @@ static int bloblist_resize_rec(struct bloblist_hdr *hdr,
int new_alloced; /* New value for @hdr->alloced */
ulong next_ofs; /* Offset of the record after @rec */
- expand_by = ALIGN(new_size - rec->size, BLOBLIST_ALIGN);
- new_alloced = ALIGN(hdr->alloced + expand_by, BLOBLIST_ALIGN);
+ expand_by = ALIGN(new_size - rec->size, BLOBLIST_BLOB_ALIGN);
+ new_alloced = ALIGN(hdr->alloced + expand_by, BLOBLIST_BLOB_ALIGN);
if (new_size < 0) {
log_debug("Attempt to shrink blob size below 0 (%x)\n",
new_size);
diff --git a/include/bloblist.h b/include/bloblist.h
index ab7a7fc299..745bcdd227 100644
--- a/include/bloblist.h
+++ b/include/bloblist.h
@@ -24,11 +24,11 @@
* which would add to code size. For Thumb-2 the code size needed in SPL is
* approximately 940 bytes (e.g. for chromebook_bob).
*
- * 5. Bloblist uses 16-byte alignment internally and is designed to start on a
- * 16-byte boundary. Its headers are multiples of 16 bytes. This makes it easier
- * to deal with data structures which need this level of alignment, such as ACPI
- * tables. For use in SPL and TPL the alignment can be relaxed, since it can be
- * relocated to an aligned address in U-Boot proper.
+ * 5. Bloblist uses 8-byte alignment internally and is designed to start on a
+ * 8-byte boundary. Its headers are 8 bytes long. It is possible to achieve
+ * larger alignment (e.g. 16 bytes) by adding a dummy header, For use in SPL and
+ * TPL the alignment can be relaxed, since it can be relocated to an aligned
+ * address in U-Boot proper.
*
* 6. Bloblist is designed to be passed to Linux as reserved memory. While linux
* doesn't understand the bloblist header, it can be passed the indivdual blobs.
@@ -77,6 +77,9 @@ enum {
BLOBLIST_VERSION = 1,
BLOBLIST_MAGIC = 0x6ed0ff,
+ BLOBLIST_BLOB_ALIGN_LOG2 = 3,
+ BLOBLIST_BLOB_ALIGN = 1 << BLOBLIST_BLOB_ALIGN_LOG2,
+
BLOBLIST_ALIGN_LOG2 = 3,
BLOBLIST_ALIGN = 1 << BLOBLIST_ALIGN_LOG2,
};
@@ -195,17 +198,25 @@ struct bloblist_hdr {
*
* NOTE: Only exported for testing purposes. Do not use this struct.
*
- * @tag: Tag indicating what the record contains
- * @hdr_size: Size of this header, normally sizeof(struct bloblist_rec). The
- * record's data starts at this offset from the start of the record
+ * @tag_and_hdr_size: Tag indicating what the record contains (bottom 24 bits), and
+ * size of this header (top 8 bits), normally sizeof(struct bloblist_rec).
+ * The record's data starts at this offset from the start of the record
* @size: Size of record in bytes, excluding the header size. This does not
* need to be aligned (e.g. 3 is OK).
*/
struct bloblist_rec {
- u32 tag;
- u32 hdr_size;
+ u32 tag_and_hdr_size;
u32 size;
- u32 _spare;
+};
+
+enum {
+ BLOBLISTR_TAG_SHIFT = 0,
+ BLOBLISTR_TAG_MASK = 0xffffffU << BLOBLISTR_TAG_SHIFT,
+ BLOBLISTR_HDR_SIZE_SHIFT = 24,
+ BLOBLISTR_HDR_SIZE_MASK = 0xffU << BLOBLISTR_HDR_SIZE_SHIFT,
+
+ BLOBLIST_HDR_SIZE = sizeof(struct bloblist_hdr),
+ BLOBLIST_REC_HDR_SIZE = sizeof(struct bloblist_rec),
};
/**
diff --git a/test/bloblist.c b/test/bloblist.c
index 32256be772..7e65f30518 100644
--- a/test/bloblist.c
+++ b/test/bloblist.c
@@ -261,8 +261,8 @@ static int bloblist_test_cmd_info(struct unit_test_state *uts)
run_command("bloblist info", 0);
ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
ut_assert_nextline("size: 400 1 KiB");
- ut_assert_nextline("alloced: 70 112 Bytes");
- ut_assert_nextline("free: 390 912 Bytes");
+ ut_assert_nextline("alloced: 58 88 Bytes");
+ ut_assert_nextline("free: 3a8 936 Bytes");
ut_assert_console_end();
ut_unsilence_console(uts);
@@ -320,12 +320,12 @@ static int bloblist_test_align(struct unit_test_state *uts)
data = bloblist_add(i, size, 0);
ut_assertnonnull(data);
addr = map_to_sysmem(data);
- ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1));
+ ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN - 1));
/* Only the bytes in the blob data should be zeroed */
for (j = 0; j < size; j++)
ut_asserteq(0, data[j]);
- for (; j < BLOBLIST_ALIGN; j++)
+ for (; j < BLOBLIST_BLOB_ALIGN; j++)
ut_asserteq(ERASE_BYTE, data[j]);
}
@@ -340,7 +340,7 @@ static int bloblist_test_align(struct unit_test_state *uts)
}
/* Check alignment with an bloblist starting on a smaller alignment */
- hdr = map_sysmem(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE);
+ hdr = map_sysmem(TEST_ADDR + BLOBLIST_BLOB_ALIGN, TEST_BLOBLIST_SIZE);
memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
memset(hdr, '\0', sizeof(*hdr));
ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN,
@@ -349,7 +349,7 @@ static int bloblist_test_align(struct unit_test_state *uts)
data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1);
ut_assertnonnull(data);
addr = map_to_sysmem(data);
- ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1));
+ ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN * 2 - 1));
return 0;
}
@@ -437,7 +437,7 @@ static int bloblist_test_grow(struct unit_test_state *uts)
hdr = ptr;
ut_asserteq(sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2 +
- BLOBLIST_ALIGN,
+ BLOBLIST_BLOB_ALIGN,
hdr->alloced);
return 0;
@@ -572,7 +572,7 @@ static int bloblist_test_resize_last(struct unit_test_state *uts)
ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
/* Check that the new top of the allocated blobs has not been touched */
- alloced_val += BLOBLIST_ALIGN;
+ alloced_val += BLOBLIST_BLOB_ALIGN;
ut_asserteq(alloced_val, hdr->alloced);
ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced));
--
2.25.1
More information about the U-Boot
mailing list