[PATCH 013/112] efi: payload: image: allocate image via loader if it exceeds malloc area

Ahmad Fatoum a.fatoum at pengutronix.de
Wed Jan 3 10:11:33 PST 2024


barebox allocates at maximum 256M for its own use when running as EFI
payload. With bigger kernel images and initrds, this may exceed the
space barebox has available, especially if decompression needs to happen
within barebox.

In that case, instead of failing with -ENOMEM, let's ask the EFI
firmware for a suitably sized buffer and read into that if the
allocation succeeds.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 efi/payload/image.c | 49 +++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/efi/payload/image.c b/efi/payload/image.c
index 8d29bf9bb434..b7f4b7560b4b 100644
--- a/efi/payload/image.c
+++ b/efi/payload/image.c
@@ -76,6 +76,51 @@ struct linux_kernel_header {
 	uint32_t handover_offset;	/** */
 } __attribute__ ((packed));
 
+static void *efi_read_file(const char *file, size_t *size)
+{
+	efi_physical_addr_t mem;
+	efi_status_t efiret;
+	struct stat s;
+	char *buf;
+	ssize_t ret;
+
+	buf = read_file(file, size);
+	if (buf || errno != ENOMEM)
+		return buf;
+
+	ret = stat(file, &s);
+	if (ret)
+		return NULL;
+
+	efiret = BS->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				    EFI_LOADER_CODE,
+				    DIV_ROUND_UP(s.st_size, EFI_PAGE_SIZE),
+				    &mem);
+	if (EFI_ERROR(efiret)) {
+		errno = efi_errno(efiret);
+		return NULL;
+	}
+
+	buf = (void *)mem;
+
+	ret = read_file_into_buf(file, buf, s.st_size);
+	if (ret < 0)
+		return NULL;
+
+	*size = ret;
+	return buf;
+}
+
+static void efi_free_file(void *_mem, size_t size)
+{
+	efi_physical_addr_t mem = (efi_physical_addr_t)_mem;
+
+	if (mem_malloc_start() <= mem && mem < mem_malloc_end())
+		free(_mem);
+	else
+		BS->free_pages(mem, DIV_ROUND_UP(size, EFI_PAGE_SIZE));
+}
+
 static int efi_load_image(const char *file, efi_loaded_image_t **loaded_image,
 		efi_handle_t *h)
 {
@@ -84,7 +129,7 @@ static int efi_load_image(const char *file, efi_loaded_image_t **loaded_image,
 	efi_handle_t handle;
 	efi_status_t efiret = EFI_SUCCESS;
 
-	exe = read_file(file, &size);
+	exe = efi_read_file(file, &size);
 	if (!exe)
 		return -errno;
 
@@ -106,7 +151,7 @@ static int efi_load_image(const char *file, efi_loaded_image_t **loaded_image,
 
 	*h = handle;
 out:
-	free(exe);
+	efi_free_file(exe, size);
 	return -efi_errno(efiret);
 }
 
-- 
2.39.2




More information about the barebox mailing list