]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
bloblist: Reduce blob-header size
authorSimon Glass <sjg@chromium.org>
Wed, 27 Dec 2023 21:07:07 +0000 (13:07 -0800)
committerSimon Glass <sjg@chromium.org>
Sun, 31 Dec 2023 14:21:02 +0000 (07:21 -0700)
The v0.9 spec provides for an 8-byte header for each blob, with fewer
fields.
The blob data 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@chromium.org>
Co-developed-by: Raymond Mao <raymond.mao@linaro.org>
Signed-off-by: Raymond Mao <raymond.mao@linaro.org>
common/bloblist.c
include/bloblist.h
test/bloblist.c

index 73dbbc01c081cef4ad1289dc05e5f4fdeecd16ab..1c97d61e4aa8a4c6d66d967ea710bbd75a344960 100644 (file)
@@ -87,12 +87,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,
@@ -101,7 +103,13 @@ 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);
+       /*
+        * The data section of next TE should start from an address aligned
+        * to 1 << hdr->align_log2.
+        */
+       offset += rec_hdr_size(rec) + rec->size;
+       offset = round_up(offset + rec_hdr_size(rec), 1 << hdr->align_log2);
+       offset -= rec_hdr_size(rec);
 
        return offset;
 }
@@ -145,7 +153,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);
@@ -178,8 +186,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 */
@@ -283,8 +290,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);
index d2dcad69a1bff13d852bd17aa8201c823e7a18dd..7024d7bf9e5e88cc51e641e584ae907f8060d316 100644 (file)
  * 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          = 0x4a0fb10b,
 
+       BLOBLIST_BLOB_ALIGN_LOG2 = 3,
+       BLOBLIST_BLOB_ALIGN      = 1 << BLOBLIST_BLOB_ALIGN_LOG2,
+
        BLOBLIST_ALIGN_LOG2     = 3,
        BLOBLIST_ALIGN          = 1 << BLOBLIST_ALIGN_LOG2,
 };
@@ -199,17 +202,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),
 };
 
 /**
index 49ac4b92aee980ae3a2473b1fb332c2419e97d57..e6070041d36cdd7be8a2a85a38446ba09259e225 100644 (file)
@@ -272,8 +272,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);
 
@@ -331,12 +331,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]);
        }
 
@@ -351,7 +351,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, TEST_BLOBLIST_SIZE,
@@ -360,7 +360,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;
 }
@@ -448,7 +448,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;
@@ -583,7 +583,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));