]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
lib: efi_loader: efi_memory.c: add efi_realloc() for realloc memory
authorYing-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Thu, 3 Jul 2025 06:28:09 +0000 (07:28 +0100)
committerIlias Apalodimas <ilias.apalodimas@linaro.org>
Thu, 3 Jul 2025 09:25:56 +0000 (12:25 +0300)
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>
include/efi_loader.h
lib/efi_loader/efi_memory.c

index c02bc1b7ef4971a6e945a788585d57a7df60bf2f..b60ea58d71fb9e65e4441742f7801d05b8f6b1f6 100644 (file)
@@ -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 */
index 0828a47da61c6f84ba29051e1c3349e51b803157..6dfc698a2479bfc7ed470f9f9a91ffe488523da5 100644 (file)
@@ -668,6 +668,64 @@ void *efi_alloc(size_t size)
        return buf;
 }
 
+/**
+ * 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
  *