bloblist: Provide a way to remove a blob
Add a function to remove a blob of a particular type. Signed-off-by: Simon Glass <sjg@chromium.org> Co-developed-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -356,6 +356,38 @@ int bloblist_resize(uint tag, int new_size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bloblist_remove(uint tag)
|
||||||
|
{
|
||||||
|
struct bloblist_hdr *hdr = gd->bloblist;
|
||||||
|
struct bloblist_rec *rec;
|
||||||
|
ulong rec_start; /* offset where record starts */
|
||||||
|
ulong next_ofs; /* offset of the record after @rec */
|
||||||
|
ulong removed_size; /* total size to remove, including alignment */
|
||||||
|
|
||||||
|
rec = bloblist_findrec(tag);
|
||||||
|
if (!rec)
|
||||||
|
return log_msg_ret("find", -ENOENT);
|
||||||
|
|
||||||
|
/* Calculate where this record starts and where the next one begins */
|
||||||
|
rec_start = (void *)rec - (void *)hdr;
|
||||||
|
next_ofs = bloblist_blob_end_ofs(hdr, rec);
|
||||||
|
|
||||||
|
/* Calculate total size to remove (record + alignment) */
|
||||||
|
removed_size = next_ofs - rec_start;
|
||||||
|
|
||||||
|
/* Move all following blobs backward to fill the gap */
|
||||||
|
if (next_ofs < hdr->used_size) {
|
||||||
|
memmove((void *)hdr + rec_start,
|
||||||
|
(void *)hdr + next_ofs,
|
||||||
|
hdr->used_size - next_ofs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the used size */
|
||||||
|
hdr->used_size -= removed_size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static u32 bloblist_calc_chksum(struct bloblist_hdr *hdr)
|
static u32 bloblist_calc_chksum(struct bloblist_hdr *hdr)
|
||||||
{
|
{
|
||||||
u8 chksum;
|
u8 chksum;
|
||||||
|
|||||||
@@ -350,6 +350,18 @@ int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp);
|
|||||||
*/
|
*/
|
||||||
int bloblist_resize(uint tag, int new_size);
|
int bloblist_resize(uint tag, int new_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bloblist_remove() - remove a blob from the bloblist
|
||||||
|
*
|
||||||
|
* This removes the blob with the given tag from the bloblist. Any blobs after
|
||||||
|
* this one are relocated backward to fill the gap. The space is reclaimed and
|
||||||
|
* used_size is reduced accordingly.
|
||||||
|
*
|
||||||
|
* @tag: Tag to remove (enum bloblist_tag_t)
|
||||||
|
* Return: 0 if OK, -ENOENT if the tag is not found
|
||||||
|
*/
|
||||||
|
int bloblist_remove(uint tag);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bloblist_new() - Create a new, empty bloblist of a given size
|
* bloblist_new() - Create a new, empty bloblist of a given size
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -605,3 +605,67 @@ static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
BLOBLIST_TEST(bloblist_test_blob_maxsize, UFT_BLOBLIST);
|
BLOBLIST_TEST(bloblist_test_blob_maxsize, UFT_BLOBLIST);
|
||||||
|
|
||||||
|
/* Test removing a blob */
|
||||||
|
static int bloblist_test_remove(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
const uint small_size = 0x20;
|
||||||
|
struct bloblist_hdr *hdr;
|
||||||
|
void *blob1, *blob2, *blob3;
|
||||||
|
ulong used_before, used_after;
|
||||||
|
|
||||||
|
clear_bloblist();
|
||||||
|
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
|
||||||
|
hdr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
|
||||||
|
|
||||||
|
/* Create three blobs */
|
||||||
|
blob1 = bloblist_add(TEST_TAG, small_size, 0);
|
||||||
|
ut_assertnonnull(blob1);
|
||||||
|
strcpy(blob1, test1_str);
|
||||||
|
|
||||||
|
blob2 = bloblist_add(TEST_TAG2, small_size, 0);
|
||||||
|
ut_assertnonnull(blob2);
|
||||||
|
strcpy(blob2, test2_str);
|
||||||
|
|
||||||
|
blob3 = bloblist_add(TEST_TAG_MISSING, small_size, 0);
|
||||||
|
ut_assertnonnull(blob3);
|
||||||
|
|
||||||
|
used_before = hdr->used_size;
|
||||||
|
|
||||||
|
/* Remove the middle blob */
|
||||||
|
ut_assertok(bloblist_remove(TEST_TAG2));
|
||||||
|
|
||||||
|
/* Check that the blob is gone */
|
||||||
|
ut_assertnull(bloblist_find(TEST_TAG2, 0));
|
||||||
|
|
||||||
|
/* Check that the first blob is still there and intact */
|
||||||
|
ut_asserteq_ptr(blob1, bloblist_find(TEST_TAG, small_size));
|
||||||
|
ut_asserteq_str(test1_str, blob1);
|
||||||
|
|
||||||
|
/* Check that the third blob is still there */
|
||||||
|
ut_assertnonnull(bloblist_find(TEST_TAG_MISSING, small_size));
|
||||||
|
|
||||||
|
/* Check that used_size was reduced */
|
||||||
|
used_after = hdr->used_size;
|
||||||
|
ut_assert(used_after < used_before);
|
||||||
|
|
||||||
|
/* Try to remove a non-existent blob */
|
||||||
|
ut_asserteq(-ENOENT, bloblist_remove(TEST_TAG2));
|
||||||
|
|
||||||
|
/* Remove the first blob */
|
||||||
|
ut_assertok(bloblist_remove(TEST_TAG));
|
||||||
|
ut_assertnull(bloblist_find(TEST_TAG, 0));
|
||||||
|
|
||||||
|
/* The third blob should still be accessible */
|
||||||
|
ut_assertnonnull(bloblist_find(TEST_TAG_MISSING, small_size));
|
||||||
|
|
||||||
|
/* Remove the last blob */
|
||||||
|
ut_assertok(bloblist_remove(TEST_TAG_MISSING));
|
||||||
|
ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
|
||||||
|
|
||||||
|
/* Check that we're back to just the header */
|
||||||
|
ut_asserteq(sizeof(struct bloblist_hdr), hdr->used_size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
BLOBLIST_TEST(bloblist_test_remove, UFT_BLOBLIST);
|
||||||
|
|||||||
Reference in New Issue
Block a user