bloblist: Allow custom alignment for blobs
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>
This commit is contained in:
parent
751b7c7963
commit
4c1497e776
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user