]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
bloblist: Allow custom alignment for blobs
authorSimon Glass <sjg@chromium.org>
Sun, 20 Sep 2020 00:49:29 +0000 (18:49 -0600)
committerSimon Glass <sjg@chromium.org>
Tue, 6 Oct 2020 15:07:54 +0000 (09:07 -0600)
Some blobs need a larger alignment than the default. For example, ACPI
tables often start at a 4KB boundary. Add support for this.

Update the size of the test blob to allow these larger records.

Signed-off-by: Simon Glass <sjg@chromium.org>
arch/x86/cpu/intel_common/acpi.c
arch/x86/cpu/intel_common/intel_opregion.c
common/bloblist.c
include/bloblist.h
test/bloblist.c

index a4d5fbd38a7fe68b344a4ebcb254df12f02236db..4496bbfd999c2d506651b2d94ab769fd97f462a5 100644 (file)
@@ -198,7 +198,7 @@ int southbridge_inject_dsdt(const struct udevice *dev, struct acpi_ctx *ctx)
        struct acpi_global_nvs *gnvs;
        int ret;
 
-       ret = bloblist_ensure_size(BLOBLISTT_ACPI_GNVS, sizeof(*gnvs),
+       ret = bloblist_ensure_size(BLOBLISTT_ACPI_GNVS, sizeof(*gnvs), 0,
                                   (void **)&gnvs);
        if (ret)
                return log_msg_ret("bloblist", ret);
index 4e6c64d9aaaa067df384fee49043f0d3f43a04d6..c95ae04992d2d21c3f381abacd4c579cd30f421d 100644 (file)
@@ -108,7 +108,7 @@ int intel_gma_init_igd_opregion(struct udevice *dev,
                struct optionrom_vbt *ext_vbt;
 
                ret = bloblist_ensure_size(BLOBLISTT_INTEL_VBT,
-                                          vbt->hdr_vbt_size,
+                                          vbt->hdr_vbt_size, 0,
                                           (void **)&ext_vbt);
                if (ret) {
                        log_err("GMA: Unable to add Ext VBT to bloblist\n");
index 173f28d8ec9ec9339bc7e537ab3b4ed2ff1f538e..33b58623807380123682eb7de6f509c97fb5ac47 100644 (file)
@@ -83,18 +83,25 @@ static struct bloblist_rec *bloblist_findrec(uint tag)
        return NULL;
 }
 
-static int bloblist_addrec(uint tag, int size, struct bloblist_rec **recp)
+static int bloblist_addrec(uint tag, int size, int align,
+                          struct bloblist_rec **recp)
 {
        struct bloblist_hdr *hdr = gd->bloblist;
        struct bloblist_rec *rec;
        int data_start, new_alloced;
 
+       if (!align)
+               align = BLOBLIST_ALIGN;
+
        /* Figure out where the new data will start */
-       data_start = hdr->alloced + sizeof(*rec);
-       data_start = ALIGN(data_start, BLOBLIST_ALIGN);
+       data_start = map_to_sysmem(hdr) + hdr->alloced + sizeof(*rec);
+
+       /* Align the address and then calculate the offset from ->alloced */
+       data_start = ALIGN(data_start, align) - map_to_sysmem(hdr);
 
        /* Calculate the new allocated total */
-       new_alloced = data_start + ALIGN(size, BLOBLIST_ALIGN);
+       new_alloced = data_start + ALIGN(size, align);
+
        if (new_alloced >= hdr->size) {
                log(LOGC_BLOBLIST, LOGL_ERR,
                    "Failed to allocate %x bytes size=%x, need size=%x\n",
@@ -117,7 +124,8 @@ static int bloblist_addrec(uint tag, int size, struct bloblist_rec **recp)
        return 0;
 }
 
-static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size)
+static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size,
+                             int align)
 {
        struct bloblist_rec *rec;
 
@@ -130,7 +138,7 @@ static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size)
        } else {
                int ret;
 
-               ret = bloblist_addrec(tag, size, &rec);
+               ret = bloblist_addrec(tag, size, align, &rec);
                if (ret)
                        return ret;
        }
@@ -152,22 +160,22 @@ void *bloblist_find(uint tag, int size)
        return (void *)rec + rec->hdr_size;
 }
 
-void *bloblist_add(uint tag, int size)
+void *bloblist_add(uint tag, int size, int align)
 {
        struct bloblist_rec *rec;
 
-       if (bloblist_addrec(tag, size, &rec))
+       if (bloblist_addrec(tag, size, align, &rec))
                return NULL;
 
        return (void *)rec + rec->hdr_size;
 }
 
-int bloblist_ensure_size(uint tag, int size, void **blobp)
+int bloblist_ensure_size(uint tag, int size, int align, void **blobp)
 {
        struct bloblist_rec *rec;
        int ret;
 
-       ret = bloblist_ensurerec(tag, &rec, size);
+       ret = bloblist_ensurerec(tag, &rec, size, align);
        if (ret)
                return ret;
        *blobp = (void *)rec + rec->hdr_size;
@@ -179,7 +187,7 @@ void *bloblist_ensure(uint tag, int size)
 {
        struct bloblist_rec *rec;
 
-       if (bloblist_ensurerec(tag, &rec, size))
+       if (bloblist_ensurerec(tag, &rec, size, 0))
                return NULL;
 
        return (void *)rec + rec->hdr_size;
@@ -190,7 +198,7 @@ int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp)
        struct bloblist_rec *rec;
        int ret;
 
-       ret = bloblist_ensurerec(tag, &rec, *sizep);
+       ret = bloblist_ensurerec(tag, &rec, *sizep, 0);
        if (ret == -ESPIPE)
                *sizep = rec->size;
        else if (ret)
index 6c37cd2a6390f454a6d50a6f6fb25d28dce92828..965d8e9a29b2b3ed32a5044d26679a6a5b30b992 100644 (file)
@@ -132,10 +132,11 @@ void *bloblist_find(uint tag, int size);
  *
  * @tag:       Tag to add (enum bloblist_tag_t)
  * @size:      Size of the blob
+ * @align:     Alignment of the blob (in bytes), 0 for default
  * @return pointer to the newly added block, or NULL if there is not enough
  *     space for the blob
  */
-void *bloblist_add(uint tag, int size);
+void *bloblist_add(uint tag, int size, int align);
 
 /**
  * bloblist_ensure_size() - Find or add a blob
@@ -145,10 +146,11 @@ void *bloblist_add(uint tag, int size);
  * @tag:       Tag to add (enum bloblist_tag_t)
  * @size:      Size of the blob
  * @blobp:     Returns a pointer to blob on success
+ * @align:     Alignment of the blob (in bytes), 0 for default
  * @return 0 if OK, -ENOSPC if it is missing and could not be added due to lack
  *     of space, or -ESPIPE it exists but has the wrong size
  */
-int bloblist_ensure_size(uint tag, int size, void **blobp);
+int bloblist_ensure_size(uint tag, int size, int align, void **blobp);
 
 /**
  * bloblist_ensure() - Find or add a blob
index 68535237641a5affdd589c228aeacd006cf5acae..0bb9e2d81e7b4d509ff7df0e162f5303bf957a9c 100644 (file)
@@ -25,10 +25,10 @@ enum {
 
        TEST_SIZE               = 10,
        TEST_SIZE2              = 20,
-       TEST_SIZE_LARGE         = 0xe0,
+       TEST_SIZE_LARGE         = 0x3e0,
 
        TEST_ADDR               = CONFIG_BLOBLIST_ADDR,
-       TEST_BLOBLIST_SIZE      = 0x100,
+       TEST_BLOBLIST_SIZE      = 0x400,
 
        ERASE_BYTE              = '\xff',
 };
@@ -100,7 +100,7 @@ static int bloblist_test_blob(struct unit_test_state *uts)
        ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
 
        /* Add a record and check that we can find it */
-       data = bloblist_add(TEST_TAG, TEST_SIZE);
+       data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
        rec = (void *)(hdr + 1);
        ut_asserteq_addr(rec + 1, data);
        data = bloblist_find(TEST_TAG, TEST_SIZE);
@@ -206,10 +206,10 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
        hdr->chksum--;
 
        /* Make sure the checksum changes when we add blobs */
-       data = bloblist_add(TEST_TAG, TEST_SIZE);
+       data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
        ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
 
-       data2 = bloblist_add(TEST_TAG2, TEST_SIZE2);
+       data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
        ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
        ut_assertok(bloblist_finish());
 
@@ -255,9 +255,9 @@ static int bloblist_test_cmd_info(struct unit_test_state *uts)
        console_record_reset();
        run_command("bloblist info", 0);
        ut_assert_nextline("base:     %lx", (ulong)map_to_sysmem(hdr));
-       ut_assert_nextline("size:     100    256 Bytes");
+       ut_assert_nextline("size:     400    1 KiB");
        ut_assert_nextline("alloced:  70     112 Bytes");
-       ut_assert_nextline("free:     90     144 Bytes");
+       ut_assert_nextline("free:     390    912 Bytes");
        ut_assert_console_end();
        gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
 
@@ -298,6 +298,8 @@ BLOBLIST_TEST(bloblist_test_cmd_list, 0);
 static int bloblist_test_align(struct unit_test_state *uts)
 {
        struct bloblist_hdr *hdr;
+       ulong addr;
+       char *data;
        int i;
 
        /* At the start there should be no records */
@@ -305,14 +307,14 @@ static int bloblist_test_align(struct unit_test_state *uts)
        ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
        ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
 
-       /* Check the alignment */
+       /* Check the default alignment */
        for (i = 0; i < 3; i++) {
                int size = i * 3;
                ulong addr;
                char *data;
                int j;
 
-               data = bloblist_add(i, size);
+               data = bloblist_add(i, size, 0);
                ut_assertnonnull(data);
                addr = map_to_sysmem(data);
                ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1));
@@ -324,6 +326,28 @@ static int bloblist_test_align(struct unit_test_state *uts)
                        ut_asserteq(ERASE_BYTE, data[j]);
        }
 
+       /* Check larger alignment */
+       for (i = 0; i < 3; i++) {
+               int align = 32 << i;
+
+               data = bloblist_add(3 + i, i * 4, align);
+               ut_assertnonnull(data);
+               addr = map_to_sysmem(data);
+               ut_asserteq(0, addr & (align - 1));
+       }
+
+       /* Check alignment with an bloblist starting on a smaller alignment */
+       hdr = map_sysmem(TEST_ADDR + BLOBLIST_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,
+                                0));
+
+       data = bloblist_add(1, 5, BLOBLIST_ALIGN * 2);
+       ut_assertnonnull(data);
+       addr = map_to_sysmem(data);
+       ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1));
+
        return 0;
 }
 BLOBLIST_TEST(bloblist_test_align, 0);