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);
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");
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",
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;
} else {
int ret;
- ret = bloblist_addrec(tag, size, &rec);
+ ret = bloblist_addrec(tag, size, align, &rec);
if (ret)
return ret;
}
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;
{
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;
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)
*
* @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
* @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
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',
};
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);
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());
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);
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 */
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));
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);