From: Simon Glass <s...@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 <s...@chromium.org>
Co-developed-by: Raymond Mao <raymond....@linaro.org>
Signed-off-by: Raymond Mao <raymond....@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

Reply via email to