summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYing-Chun Liu (PaulLiu) <paul.liu@linaro.org>2025-07-03 07:28:09 +0100
committerIlias Apalodimas <ilias.apalodimas@linaro.org>2025-07-03 12:25:56 +0300
commit3c08df58cc43c3ae8ec378ab0e32cfe548313c39 (patch)
treeb894f1004498d9913ce44e29e10b31656fc20057
parente7a85ec651ed5794eb9a837e1073f6b3146af501 (diff)
lib: efi_loader: efi_memory.c: add efi_realloc() for realloc memory
Add efi_realloc() for realloc memory that previously alloc by efi_alloc(). Note that if realloced memory is explicitly allocated as BootServicesData. Cc: Heinrich Schuchardt <xypron.glpk@gmx.de> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org> Cc: Peter Robinson <pbrobinson@gmail.com> Cc: Simon Glass <sjg@chromium.org> Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org> Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org> Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
-rw-r--r--include/efi_loader.h10
-rw-r--r--lib/efi_loader/efi_memory.c58
2 files changed, 68 insertions, 0 deletions
diff --git a/include/efi_loader.h b/include/efi_loader.h
index c02bc1b7ef4..b60ea58d71f 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -875,6 +875,16 @@ efi_status_t efi_next_variable_name(efi_uintn_t *size, u16 **buf,
#define efi_size_in_pages(size) (((size) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
/* Allocate boot service data pool memory */
void *efi_alloc(size_t len);
+/**
+ * efi_realloc() - reallocate boot services data pool memory
+ *
+ * Reallocate memory from pool for a new size and copy the data from old one.
+ *
+ * @ptr: pointer to the buffer
+ * @size: number of bytes to allocate
+ * Return: EFI status to indicate success or not
+ */
+efi_status_t efi_realloc(void **ptr, size_t len);
/* Allocate pages on the specified alignment */
void *efi_alloc_aligned_pages(u64 len, int memory_type, size_t align);
/* More specific EFI memory allocator, called by EFI payloads */
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 0828a47da61..6dfc698a247 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -669,6 +669,64 @@ void *efi_alloc(size_t size)
}
/**
+ * efi_realloc() - reallocate boot services data pool memory
+ *
+ * Reallocate memory from pool for a new size and copy the data from old one.
+ *
+ * @ptr: pointer to old buffer
+ * @size: number of bytes to allocate
+ * Return: EFI status to indicate success or not
+ */
+efi_status_t efi_realloc(void **ptr, size_t size)
+{
+ efi_status_t ret;
+ void *new_ptr;
+ struct efi_pool_allocation *alloc;
+ u64 num_pages = efi_size_in_pages(size +
+ sizeof(struct efi_pool_allocation));
+ size_t old_size;
+
+ if (!*ptr) {
+ *ptr = efi_alloc(size);
+ if (*ptr)
+ return EFI_SUCCESS;
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ret = efi_check_allocated((uintptr_t)*ptr, true);
+ if (ret != EFI_SUCCESS)
+ return ret;
+
+ alloc = container_of(*ptr, struct efi_pool_allocation, data);
+
+ /* Check that this memory was allocated by efi_allocate_pool() */
+ if (((uintptr_t)alloc & EFI_PAGE_MASK) ||
+ alloc->checksum != checksum(alloc)) {
+ printf("%s: illegal realloc 0x%p\n", __func__, *ptr);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ /* Don't realloc. The actual size in pages is the same. */
+ if (alloc->num_pages == num_pages)
+ return EFI_SUCCESS;
+
+ old_size = alloc->num_pages * EFI_PAGE_SIZE -
+ sizeof(struct efi_pool_allocation);
+
+ new_ptr = efi_alloc(size);
+
+ /* copy old data to new alloced buffer */
+ memcpy(new_ptr, *ptr, min(size, old_size));
+
+ /* free the old buffer */
+ efi_free_pool(*ptr);
+
+ *ptr = new_ptr;
+
+ return EFI_SUCCESS;
+}
+
+/**
* efi_free_pool() - free memory from pool
*
* @buffer: start of memory to be freed