* [PATCH 01/15] efi: payload: split image handling from legacy handover boot support
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
@ 2025-09-20 3:03 ` chalianis1
2025-09-20 3:03 ` [PATCH 02/15] efi: payload: add support for efi stub boot chalianis1
` (14 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: chalianis1 @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis, Ahmad Fatoum
From: Ahmad Fatoum <a.fatoum@barebox.org>
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
efi/Kconfig | 4 +
efi/payload/Kconfig | 4 +
efi/payload/Makefile | 2 +
efi/payload/handover.c | 195 ++++++++++++++++++++++++++++++++++++++
efi/payload/image.c | 228 ++-------------------------------------------
efi/payload/image.h | 14 +++
| 63 +++++++++++++
7 files changed, 291 insertions(+), 219 deletions(-)
diff --git a/efi/Kconfig b/efi/Kconfig
index 84f670fd23d33ab3b5699ecedefea157aa36ffb6..91dca949b5a3cf96dd7c014bed4823da8ccf2eed 100644
--- a/efi/Kconfig
+++ b/efi/Kconfig
@@ -18,6 +18,10 @@ config EFI_PAYLOAD
select PARTITION_DISK
select HW_HAS_PCI
+if EFI_PAYLOAD
+source "efi/payload/Kconfig"
+endif
+
config EFI
bool
diff --git a/efi/payload/Kconfig b/efi/payload/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..310f79c3d89f6ab3abc930cc659b8c21441ae742
--- /dev/null
+++ b/efi/payload/Kconfig
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config EFI_HANDOVER_PROTOCOL
+ def_bool y
diff --git a/efi/payload/Makefile b/efi/payload/Makefile
index a4a0332a82882244308866031c557fd3130ff4a0..d8b577bf3e2396f7e756023024d6466a6b4922b9 100644
--- a/efi/payload/Makefile
+++ b/efi/payload/Makefile
@@ -2,6 +2,8 @@
obj-y += init.o
obj-y += image.o
+obj-$(CONFIG_EFI_HANDOVER_PROTOCOL) += handover.o
+obj-y += efi-initrd.o
obj-$(CONFIG_OFTREE) += fdt.o
bbenv-y += env-efi
obj-$(CONFIG_CMD_IOMEM) += iomem.o
diff --git a/efi/payload/handover.c b/efi/payload/handover.c
new file mode 100644
index 0000000000000000000000000000000000000000..7419d86cc99716b2b514a1a392cc617059f0fa4d
--- /dev/null
+++ b/efi/payload/handover.c
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * handover.c - legacy x86 EFI handover protocol
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ */
+
+#include <clock.h>
+#include <common.h>
+#include <linux/sizes.h>
+#include <linux/ktime.h>
+#include <memory.h>
+#include <command.h>
+#include <magicvar.h>
+#include <init.h>
+#include <driver.h>
+#include <io.h>
+#include <efi.h>
+#include <malloc.h>
+#include <string.h>
+#include <linux/err.h>
+#include <boot.h>
+#include <bootm.h>
+#include <fs.h>
+#include <libfile.h>
+#include <binfmt.h>
+#include <wchar.h>
+#include <efi/efi-payload.h>
+#include <efi/efi-device.h>
+
+#include "image.h"
+#include "setup_header.h"
+
+static int efi_do_execute_image(enum filetype filetype, const char *file)
+{
+ efi_handle_t handle;
+ struct efi_loaded_image *loaded_image;
+ int ret;
+
+ ret = efi_load_image(file, &loaded_image, &handle);
+ if (ret)
+ return ret;
+
+ return efi_execute_image(handle, loaded_image, filetype);
+}
+
+typedef void(*handover_fn)(void *image, struct efi_system_table *table,
+ struct x86_setup_header *header);
+
+static inline void linux_efi_handover(efi_handle_t handle,
+ struct x86_setup_header *header)
+{
+ handover_fn handover;
+ uintptr_t addr;
+
+ addr = header->code32_start + header->handover_offset;
+ if (IS_ENABLED(CONFIG_X86_64))
+ addr += 512;
+
+ handover = efi_phys_to_virt(addr);
+ handover(handle, efi_sys_table, header);
+}
+
+static int do_bootm_efi(struct image_data *data)
+{
+ void *tmp;
+ void *initrd = NULL;
+ size_t size;
+ efi_handle_t handle;
+ int ret;
+ const char *options;
+ struct efi_loaded_image *loaded_image;
+ struct x86_setup_header *image_header, *boot_header;
+
+ ret = efi_load_image(data->os_file, &loaded_image, &handle);
+ if (ret)
+ return ret;
+
+ image_header = (struct x86_setup_header *)loaded_image->image_base;
+
+ if (!is_x86_setup_header(image_header) ||
+ image_header->version < 0x20b ||
+ !image_header->relocatable_kernel) {
+ pr_err("Not a valid kernel image!\n");
+ BS->unload_image(handle);
+ return -EINVAL;
+ }
+
+ boot_header = xmalloc(0x4000);
+ memset(boot_header, 0, 0x4000);
+ memcpy(boot_header, image_header, sizeof(*image_header));
+
+ /* Refer to Linux kernel commit a27e292b8a54
+ * ("Documentation/x86/boot: Reserve type_of_loader=13 for barebox")
+ */
+ boot_header->type_of_loader = 0x13;
+
+ if (data->initrd_file) {
+ tmp = read_file(data->initrd_file, &size);
+ initrd = xmemalign(PAGE_SIZE, PAGE_ALIGN(size));
+ memcpy(initrd, tmp, size);
+ memset(initrd + size, 0, PAGE_ALIGN(size) - size);
+ free(tmp);
+ boot_header->ramdisk_image = efi_virt_to_phys(initrd);
+ boot_header->ramdisk_size = PAGE_ALIGN(size);
+ }
+
+ options = linux_bootargs_get();
+ if (options) {
+ boot_header->cmd_line_ptr = efi_virt_to_phys(options);
+ boot_header->cmdline_size = strlen(options);
+ }
+
+ boot_header->code32_start = efi_virt_to_phys(loaded_image->image_base +
+ (image_header->setup_sects+1) * 512);
+
+ if (bootm_verbose(data)) {
+ printf("\nStarting kernel at 0x%p", loaded_image->image_base);
+ if (data->initrd_file)
+ printf(", initrd at 0x%08x",
+ boot_header->ramdisk_image);
+ printf("...\n");
+ }
+
+ if (data->dryrun) {
+ BS->unload_image(handle);
+ free(boot_header);
+ free(initrd);
+ return 0;
+ }
+
+ efi_set_variable_usec("LoaderTimeExecUSec", &efi_systemd_vendor_guid,
+ ktime_to_us(ktime_get()));
+
+ shutdown_barebox();
+ linux_efi_handover(handle, boot_header);
+
+ return 0;
+}
+
+static struct image_handler efi_handle_tr = {
+ .name = "EFI Application",
+ .bootm = do_bootm_efi,
+ .filetype = filetype_exe,
+};
+
+static int efi_execute(struct binfmt_hook *b, char *file, int argc, char **argv)
+{
+ return efi_do_execute_image(b->type, file);
+}
+
+static struct binfmt_hook binfmt_efi_hook = {
+ .type = filetype_exe,
+ .hook = efi_execute,
+};
+
+static int do_bootm_mbr(struct image_data *data)
+{
+ /* On x86, Linux kernel images have a MBR magic at the end of
+ * the first 512 byte sector and a PE magic if they're EFI-stubbed.
+ * The PE magic has precedence over the MBR, so if we arrive in
+ * this boot handler, the kernel has no EFI stub.
+ *
+ * Print a descriptive error message instead of "no image handler
+ * found for image type MBR sector".
+ */
+ pr_err("Can't boot MBR sector: Is CONFIG_EFI_STUB disabled in your Linux kernel config?\n");
+ return -ENOSYS;
+}
+
+static struct image_handler non_efi_handle_linux_x86 = {
+ .name = "non-EFI x86 Linux Image",
+ .bootm = do_bootm_mbr,
+ .filetype = filetype_mbr,
+};
+
+static struct binfmt_hook binfmt_arm64_efi_hook = {
+ .type = filetype_arm64_efi_linux_image,
+ .hook = efi_execute,
+};
+
+static int efi_register_image_handler(void)
+{
+ register_image_handler(&efi_handle_tr);
+ binfmt_register(&binfmt_efi_hook);
+
+ if (IS_ENABLED(CONFIG_X86))
+ register_image_handler(&non_efi_handle_linux_x86);
+
+ if (IS_ENABLED(CONFIG_ARM64))
+ binfmt_register(&binfmt_arm64_efi_hook);
+
+ return 0;
+}
+late_efi_initcall(efi_register_image_handler);
diff --git a/efi/payload/image.c b/efi/payload/image.c
index 33c5e18dac272d6f2e0810a675dc44a149854595..5b0a0ac199c0999bf970bd45d4dfca394b347aa0 100644
--- a/efi/payload/image.c
+++ b/efi/payload/image.c
@@ -8,10 +8,7 @@
#include <clock.h>
#include <common.h>
#include <linux/sizes.h>
-#include <linux/ktime.h>
#include <memory.h>
-#include <command.h>
-#include <magicvar.h>
#include <init.h>
#include <driver.h>
#include <io.h>
@@ -19,63 +16,15 @@
#include <malloc.h>
#include <string.h>
#include <linux/err.h>
-#include <boot.h>
-#include <bootm.h>
+#include <bootargs.h>
#include <fs.h>
#include <libfile.h>
-#include <binfmt.h>
#include <wchar.h>
#include <efi/efi-payload.h>
#include <efi/efi-device.h>
-struct linux_kernel_header {
- /* first sector of the image */
- uint8_t code1[0x0020];
- uint16_t cl_magic; /**< Magic number 0xA33F */
- uint16_t cl_offset; /**< The offset of command line */
- uint8_t code2[0x01F1 - 0x0020 - 2 - 2];
- uint8_t setup_sects; /**< The size of the setup in sectors */
- uint16_t root_flags; /**< If the root is mounted readonly */
- uint16_t syssize; /**< obsolete */
- uint16_t swap_dev; /**< obsolete */
- uint16_t ram_size; /**< obsolete */
- uint16_t vid_mode; /**< Video mode control */
- uint16_t root_dev; /**< Default root device number */
- uint16_t boot_flag; /**< 0xAA55 magic number */
-
- /* second sector of the image */
- uint16_t jump; /**< Jump instruction (this is code!) */
- uint32_t header; /**< Magic signature "HdrS" */
- uint16_t version; /**< Boot protocol version supported */
- uint32_t realmode_swtch; /**< Boot loader hook */
- uint16_t start_sys; /**< The load-low segment (obsolete) */
- uint16_t kernel_version; /**< Points to kernel version string */
- uint8_t type_of_loader; /**< Boot loader identifier */
- uint8_t loadflags; /**< Boot protocol option flags */
- uint16_t setup_move_size; /**< Move to high memory size */
- uint32_t code32_start; /**< Boot loader hook */
- uint32_t ramdisk_image; /**< initrd load address */
- uint32_t ramdisk_size; /**< initrd size */
- uint32_t bootsect_kludge; /**< obsolete */
- uint16_t heap_end_ptr; /**< Free memory after setup end */
- uint8_t ext_loader_ver; /**< boot loader's extension of the version number */
- uint8_t ext_loader_type; /**< boot loader's extension of its type */
- uint32_t cmd_line_ptr; /**< Points to the kernel command line */
- uint32_t initrd_addr_max; /**< Highest address for initrd */
- uint32_t kernel_alignment; /**< Alignment unit required by the kernel */
- uint8_t relocatable_kernel; /** */
- uint8_t min_alignment; /** */
- uint16_t xloadflags; /** */
- uint32_t cmdline_size; /** */
- uint32_t hardware_subarch; /** */
- uint64_t hardware_subarch_data; /** */
- uint32_t payload_offset; /** */
- uint32_t payload_length; /** */
- uint64_t setup_data; /** */
- uint64_t pref_address; /** */
- uint32_t init_size; /** */
- uint32_t handover_offset; /** */
-} __attribute__ ((packed));
+#include "image.h"
+#include "setup_header.h"
static void *efi_read_file(const char *file, size_t *size)
{
@@ -122,8 +71,8 @@ static void efi_free_file(void *_mem, size_t size)
BS->free_pages(mem, DIV_ROUND_UP(size, EFI_PAGE_SIZE));
}
-static int efi_load_image(const char *file, struct efi_loaded_image **loaded_image,
- efi_handle_t *h)
+int efi_load_image(const char *file, struct efi_loaded_image **loaded_image,
+ efi_handle_t *h)
{
void *exe;
size_t size;
@@ -158,10 +107,7 @@ static int efi_load_image(const char *file, struct efi_loaded_image **loaded_ima
static bool is_linux_image(enum filetype filetype, const void *base)
{
- const struct linux_kernel_header *hdr = base;
-
- if (IS_ENABLED(CONFIG_X86) &&
- hdr->boot_flag == 0xAA55 && hdr->header == 0x53726448)
+ if (IS_ENABLED(CONFIG_X86) && is_x86_setup_header(base))
return true;
if (IS_ENABLED(CONFIG_ARM64) &&
@@ -171,18 +117,13 @@ static bool is_linux_image(enum filetype filetype, const void *base)
return false;
}
-static int efi_execute_image(enum filetype filetype, const char *file)
+int efi_execute_image(efi_handle_t handle,
+ struct efi_loaded_image *loaded_image,
+ enum filetype filetype)
{
- efi_handle_t handle;
- struct efi_loaded_image *loaded_image;
efi_status_t efiret;
const char *options;
bool is_driver;
- int ret;
-
- ret = efi_load_image(file, &loaded_image, &handle);
- if (ret)
- return ret;
is_driver = (loaded_image->image_code_type == EFI_BOOT_SERVICES_CODE) ||
(loaded_image->image_code_type == EFI_RUNTIME_SERVICES_CODE);
@@ -215,154 +156,3 @@ static int efi_execute_image(enum filetype filetype, const char *file)
return -efi_errno(efiret);
}
-
-typedef void(*handover_fn)(void *image, struct efi_system_table *table,
- struct linux_kernel_header *header);
-
-static inline void linux_efi_handover(efi_handle_t handle,
- struct linux_kernel_header *header)
-{
- handover_fn handover;
- uintptr_t addr;
-
- addr = header->code32_start + header->handover_offset;
- if (IS_ENABLED(CONFIG_X86_64))
- addr += 512;
-
- handover = efi_phys_to_virt(addr);
- handover(handle, efi_sys_table, header);
-}
-
-static int do_bootm_efi(struct image_data *data)
-{
- void *tmp;
- void *initrd = NULL;
- size_t size;
- efi_handle_t handle;
- int ret;
- const char *options;
- struct efi_loaded_image *loaded_image;
- struct linux_kernel_header *image_header, *boot_header;
-
- ret = efi_load_image(data->os_file, &loaded_image, &handle);
- if (ret)
- return ret;
-
- image_header = (struct linux_kernel_header *)loaded_image->image_base;
-
- if (image_header->boot_flag != 0xAA55 ||
- image_header->header != 0x53726448 ||
- image_header->version < 0x20b ||
- !image_header->relocatable_kernel) {
- pr_err("Not a valid kernel image!\n");
- BS->unload_image(handle);
- return -EINVAL;
- }
-
- boot_header = xmalloc(0x4000);
- memset(boot_header, 0, 0x4000);
- memcpy(boot_header, image_header, sizeof(*image_header));
-
- /* Refer to Linux kernel commit a27e292b8a54
- * ("Documentation/x86/boot: Reserve type_of_loader=13 for barebox")
- */
- boot_header->type_of_loader = 0x13;
-
- if (data->initrd_file) {
- tmp = read_file(data->initrd_file, &size);
- initrd = xmemalign(PAGE_SIZE, PAGE_ALIGN(size));
- memcpy(initrd, tmp, size);
- memset(initrd + size, 0, PAGE_ALIGN(size) - size);
- free(tmp);
- boot_header->ramdisk_image = efi_virt_to_phys(initrd);
- boot_header->ramdisk_size = PAGE_ALIGN(size);
- }
-
- options = linux_bootargs_get();
- if (options) {
- boot_header->cmd_line_ptr = efi_virt_to_phys(options);
- boot_header->cmdline_size = strlen(options);
- }
-
- boot_header->code32_start = efi_virt_to_phys(loaded_image->image_base +
- (image_header->setup_sects+1) * 512);
-
- if (bootm_verbose(data)) {
- printf("\nStarting kernel at 0x%p", loaded_image->image_base);
- if (data->initrd_file)
- printf(", initrd at 0x%08x",
- boot_header->ramdisk_image);
- printf("...\n");
- }
-
- if (data->dryrun) {
- BS->unload_image(handle);
- free(boot_header);
- free(initrd);
- return 0;
- }
-
- efi_set_variable_usec("LoaderTimeExecUSec", &efi_systemd_vendor_guid,
- ktime_to_us(ktime_get()));
-
- shutdown_barebox();
- linux_efi_handover(handle, boot_header);
-
- return 0;
-}
-
-static struct image_handler efi_handle_tr = {
- .name = "EFI Application",
- .bootm = do_bootm_efi,
- .filetype = filetype_exe,
-};
-
-static int efi_execute(struct binfmt_hook *b, char *file, int argc, char **argv)
-{
- return efi_execute_image(b->type, file);
-}
-
-static struct binfmt_hook binfmt_efi_hook = {
- .type = filetype_exe,
- .hook = efi_execute,
-};
-
-static int do_bootm_mbr(struct image_data *data)
-{
- /* On x86, Linux kernel images have a MBR magic at the end of
- * the first 512 byte sector and a PE magic if they're EFI-stubbed.
- * The PE magic has precedence over the MBR, so if we arrive in
- * this boot handler, the kernel has no EFI stub.
- *
- * Print a descriptive error message instead of "no image handler
- * found for image type MBR sector".
- */
- pr_err("Can't boot MBR sector: Is CONFIG_EFI_STUB disabled in your Linux kernel config?\n");
- return -ENOSYS;
-}
-
-static struct image_handler non_efi_handle_linux_x86 = {
- .name = "non-EFI x86 Linux Image",
- .bootm = do_bootm_mbr,
- .filetype = filetype_mbr,
-};
-
-static struct binfmt_hook binfmt_arm64_efi_hook = {
- .type = filetype_arm64_efi_linux_image,
- .hook = efi_execute,
-};
-
-static int efi_register_image_handler(void)
-{
- register_image_handler(&efi_handle_tr);
- binfmt_register(&binfmt_efi_hook);
-
- if (IS_ENABLED(CONFIG_X86))
- register_image_handler(&non_efi_handle_linux_x86);
-
- if (IS_ENABLED(CONFIG_ARM64))
- binfmt_register(&binfmt_arm64_efi_hook);
-
- return 0;
-}
-late_efi_initcall(efi_register_image_handler);
diff --git a/efi/payload/image.h b/efi/payload/image.h
new file mode 100644
index 0000000000000000000000000000000000000000..673b21db839afd6dec8735e67e16aafa9f53fdd2
--- /dev/null
+++ b/efi/payload/image.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __EFI_PAYLOAD_IMAGE_H__
+#define __EFI_PAYLOAD_IMAGE_H__
+
+#include <efi/types.h>
+
+int efi_load_image(const char *file, struct efi_loaded_image **loaded_image,
+ efi_handle_t *h);
+
+int efi_execute_image(efi_handle_t handle,
+ struct efi_loaded_image *loaded_image,
+ enum filetype filetype);
+
+#endif
--git a/efi/payload/setup_header.h b/efi/payload/setup_header.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f094b8444154a06ca2606d8e7a8d958a1c0bf93
--- /dev/null
+++ b/efi/payload/setup_header.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __EFI_PAYLOAD_SETUP_HEADER_H__
+#define __EFI_PAYLOAD_SETUP_HEADER_H__
+
+#include <linux/types.h>
+
+struct x86_setup_header {
+ /* first sector of the image */
+ uint8_t code1[0x0020];
+ uint16_t cl_magic; /**< Magic number 0xA33F */
+ uint16_t cl_offset; /**< The offset of command line */
+ uint8_t code2[0x01F1 - 0x0020 - 2 - 2];
+ uint8_t setup_sects; /**< The size of the setup in sectors */
+ uint16_t root_flags; /**< If the root is mounted readonly */
+ uint16_t syssize; /**< obsolete */
+ uint16_t swap_dev; /**< obsolete */
+ uint16_t ram_size; /**< obsolete */
+ uint16_t vid_mode; /**< Video mode control */
+ uint16_t root_dev; /**< Default root device number */
+ uint16_t boot_flag; /**< 0xAA55 magic number */
+
+ /* second sector of the image */
+ uint16_t jump; /**< Jump instruction (this is code!) */
+ uint32_t header; /**< Magic signature "HdrS" */
+ uint16_t version; /**< Boot protocol version supported */
+ uint32_t realmode_swtch; /**< Boot loader hook */
+ uint16_t start_sys; /**< The load-low segment (obsolete) */
+ uint16_t kernel_version; /**< Points to kernel version string */
+ uint8_t type_of_loader; /**< Boot loader identifier */
+ uint8_t loadflags; /**< Boot protocol option flags */
+ uint16_t setup_move_size; /**< Move to high memory size */
+ uint32_t code32_start; /**< Boot loader hook */
+ uint32_t ramdisk_image; /**< initrd load address */
+ uint32_t ramdisk_size; /**< initrd size */
+ uint32_t bootsect_kludge; /**< obsolete */
+ uint16_t heap_end_ptr; /**< Free memory after setup end */
+ uint8_t ext_loader_ver; /**< boot loader's extension of the version number */
+ uint8_t ext_loader_type; /**< boot loader's extension of its type */
+ uint32_t cmd_line_ptr; /**< Points to the kernel command line */
+ uint32_t initrd_addr_max; /**< Highest address for initrd */
+ uint32_t kernel_alignment; /**< Alignment unit required by the kernel */
+ uint8_t relocatable_kernel; /** */
+ uint8_t min_alignment; /** */
+ uint16_t xloadflags; /** */
+ uint32_t cmdline_size; /** */
+ uint32_t hardware_subarch; /** */
+ uint64_t hardware_subarch_data; /** */
+ uint32_t payload_offset; /** */
+ uint32_t payload_length; /** */
+ uint64_t setup_data; /** */
+ uint64_t pref_address; /** */
+ uint32_t init_size; /** */
+ uint32_t handover_offset; /** */
+} __attribute__ ((packed));
+
+static inline bool is_x86_setup_header(const void *base)
+{
+ const struct x86_setup_header *hdr = base;
+
+ return hdr->boot_flag == 0xAA55 && hdr->header == 0x53726448;
+}
+
+#endif
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 02/15] efi: payload: add support for efi stub boot
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
2025-09-20 3:03 ` [PATCH 01/15] efi: payload: split image handling from legacy handover boot support chalianis1
@ 2025-09-20 3:03 ` chalianis1
2025-09-20 3:03 ` [PATCH 03/15] efi: payload: add support for fit image chalianis1
` (13 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: chalianis1 @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis, Ahmad Fatoum
From: Ahmad Fatoum <a.fatoum@barebox.org>
This patch has more stock, between implementing EFI STUB boot, refactor to
reuse the code and finaly support the fit image format.
This code is tested on many qemu EFI compilations comming from ovmf ubuntu
package, tianocore efi for qemu, local edk2 build, and also tested on RPi3b
64 bit EFI from tianocore and a local build of edk2, more mchines will be
tested soon. the test was for a full boot chain on RPi3b booting a fit image
containing a kernel, an fdt, and a ramdisk with ostree initrd to mount an
ostree root filesystem. for contribution in short term,
1. it would be nice to test with more hardware,
2. linux global checkup of efivars, efi capsule update, efi runtime services
3. The state.dtb to support barebox state to manage multiple system boot
and a recovery.
the case would be sys1 = new ostree commit, sys2 = old commit (rollback)
and a recovery boot system on readonly disk.
4. secure boot, PoC to check if there is a way to load TF-A from EFI
and then load the efi payload from it and launch optee??
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
efi/Kconfig | 17 ++
efi/payload/Kconfig | 5 +-
efi/payload/Makefile | 1 +
efi/payload/bootm.c | 508 +++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 530 insertions(+), 1 deletion(-)
diff --git a/efi/Kconfig b/efi/Kconfig
index 91dca949b5a3cf96dd7c014bed4823da8ccf2eed..5f4c6713d539abc88e3244f7ff3933274a8c4ebb 100644
--- a/efi/Kconfig
+++ b/efi/Kconfig
@@ -54,4 +54,21 @@ config EFI_PAYLOAD_DEFAULT_PATH
endif
+config EFI_FDT_FORCE
+ bool "Force EFI provided FDT"
+ default n
+ help
+ with this options we keep the fdt passed by EFI in the
+ system configuration table, EFI has to suppot FDT otherwise
+ an empty fdt will be generated when linux boots by efi.
+
+config EFI_INITRD_INSTALL
+ bool "Install the initramfs by barebox"
+ default n
+ help
+ with this option barebox will install the initrd to the
+ system configuration table, same as what kernel do after
+ calling read file2 boot services, in this case the initrd
+ will be read directly by the kernel as an initramfs.
+
endmenu
diff --git a/efi/payload/Kconfig b/efi/payload/Kconfig
index 310f79c3d89f6ab3abc930cc659b8c21441ae742..8f76b00744e7453ddde4ac19c1ce9a4db377e0b2 100644
--- a/efi/payload/Kconfig
+++ b/efi/payload/Kconfig
@@ -1,4 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config EFI_HANDOVER_PROTOCOL
- def_bool y
+ def_bool X86
+
+config EFI_PAYLOAD_BOOTM
+ def_bool !EFI_HANDOVER_PROTOCOL
diff --git a/efi/payload/Makefile b/efi/payload/Makefile
index d8b577bf3e2396f7e756023024d6466a6b4922b9..083728c53cb454db7dec7321592a9a7b6a2f77db 100644
--- a/efi/payload/Makefile
+++ b/efi/payload/Makefile
@@ -3,6 +3,7 @@
obj-y += init.o
obj-y += image.o
obj-$(CONFIG_EFI_HANDOVER_PROTOCOL) += handover.o
+obj-$(CONFIG_EFI_PAYLOAD_BOOTM) += bootm.o
obj-y += efi-initrd.o
obj-$(CONFIG_OFTREE) += fdt.o
bbenv-y += env-efi
diff --git a/efi/payload/bootm.c b/efi/payload/bootm.c
new file mode 100644
index 0000000000000000000000000000000000000000..6d6ecbf2e49ab7a47cfb9843418abf306b5c51db
--- /dev/null
+++ b/efi/payload/bootm.c
@@ -0,0 +1,508 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * image.c - barebox EFI payload support
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ */
+
+#include <clock.h>
+#include <common.h>
+#include <linux/sizes.h>
+#include <linux/ktime.h>
+#include <memory.h>
+#include <command.h>
+#include <magicvar.h>
+#include <init.h>
+#include <driver.h>
+#include <io.h>
+#include <efi.h>
+#include <malloc.h>
+#include <string.h>
+#include <linux/err.h>
+#include <boot.h>
+#include <bootm.h>
+#include <fs.h>
+#include <libfile.h>
+#include <binfmt.h>
+#include <wchar.h>
+#include <efi/efi-payload.h>
+#include <efi/efi-device.h>
+
+#include "image.h"
+#include "setup_header.h"
+
+struct efi_mem_resource {
+ efi_physical_addr_t base;
+ size_t size;
+} __attribute__ ((packed));
+
+struct efi_image_data {
+ struct image_data *data;
+
+ efi_handle_t handle;
+ struct efi_loaded_image *loaded_image;
+
+ struct efi_mem_resource image_res;
+ struct efi_mem_resource oftree_res;
+ struct efi_mem_resource *initrd_res;
+};
+
+
+static void *efi_allocate_pages(efi_physical_addr_t *mem,
+ size_t size,
+ enum efi_allocate_type allocate_type,
+ enum efi_memory_type mem_type)
+{
+ efi_status_t efiret;
+
+ efiret = BS->allocate_pages(allocate_type, mem_type,
+ DIV_ROUND_UP(size, EFI_PAGE_SIZE), mem);
+ if (EFI_ERROR(efiret)) {
+ errno = efi_errno(efiret);
+ return NULL;
+ }
+
+ return efi_phys_to_virt(*mem);
+}
+
+static void efi_free_pages(void *_mem, size_t size)
+{
+ efi_physical_addr_t mem = efi_virt_to_phys(_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_file_image(const char *file,
+ struct efi_loaded_image **loaded_image,
+ efi_handle_t *h)
+{
+ efi_physical_addr_t mem;
+ void *exe;
+ char *buf;
+ size_t size;
+ efi_handle_t handle;
+ efi_status_t efiret = EFI_SUCCESS;
+ int ret;
+
+ buf = read_file(file, &size);
+ if (!buf)
+ return -ENOMEM;
+
+ exe = efi_allocate_pages(&mem, size, EFI_ALLOCATE_ANY_PAGES,
+ EFI_LOADER_CODE);
+ if (!exe) {
+ pr_err("Failed to allocate pages for image\n");
+ ret = -ENOMEM;
+ goto free_buf;
+ }
+
+ memcpy(exe, buf, size);
+
+ efiret = BS->load_image(false, efi_parent_image, efi_device_path, exe,
+ size, &handle);
+ if (EFI_ERROR(efiret)) {
+ ret = -efi_errno(efiret);
+ pr_err("failed to LoadImage: %s\n", efi_strerror(efiret));
+ goto free_mem;
+ }
+
+ efiret = BS->open_protocol(handle, &efi_loaded_image_protocol_guid,
+ (void **)loaded_image, efi_parent_image,
+ NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(efiret)) {
+ ret = -efi_errno(efiret);
+ pr_err("failed to OpenProtocol: %s\n", efi_strerror(efiret));
+ BS->unload_image(handle);
+ goto free_mem;
+ }
+
+ *h = handle;
+ free(buf);
+
+ return 0;
+
+free_mem:
+ efi_free_pages(exe, size);
+free_buf:
+ free(buf);
+
+ return ret;
+}
+
+typedef void(*handover_fn)(void *image, struct efi_system_table *table,
+ struct x86_setup_header *header);
+
+static inline void linux_efi_handover(efi_handle_t handle,
+ struct x86_setup_header *header)
+{
+ handover_fn handover;
+ uintptr_t addr;
+
+ addr = header->code32_start + header->handover_offset;
+ if (IS_ENABLED(CONFIG_X86_64))
+ addr += 512;
+
+ handover = efi_phys_to_virt(addr);
+ handover(handle, efi_sys_table, header);
+}
+
+static int do_bootm_efi(struct image_data *data)
+{
+ void *tmp;
+ void *initrd = NULL;
+ size_t size;
+ efi_handle_t handle;
+ int ret;
+ const char *options;
+ struct efi_loaded_image *loaded_image;
+ struct x86_setup_header *image_header, *boot_header;
+
+ ret = efi_load_file_image(data->os_file, &loaded_image, &handle);
+ if (ret)
+ return ret;
+
+ image_header = (struct x86_setup_header *)loaded_image->image_base;
+
+ if (image_header->boot_flag != 0xAA55 ||
+ image_header->header != 0x53726448 ||
+ image_header->version < 0x20b ||
+ !image_header->relocatable_kernel) {
+ pr_err("Not a valid kernel image!\n");
+ BS->unload_image(handle);
+ return -EINVAL;
+ }
+
+ boot_header = xmalloc(0x4000);
+ memset(boot_header, 0, 0x4000);
+ memcpy(boot_header, image_header, sizeof(*image_header));
+
+ /* Refer to Linux kernel commit a27e292b8a54
+ * ("Documentation/x86/boot: Reserve type_of_loader=13 for barebox")
+ */
+ boot_header->type_of_loader = 0x13;
+
+ if (data->initrd_file) {
+ tmp = read_file(data->initrd_file, &size);
+ initrd = xmemalign(PAGE_SIZE, PAGE_ALIGN(size));
+ memcpy(initrd, tmp, size);
+ memset(initrd + size, 0, PAGE_ALIGN(size) - size);
+ free(tmp);
+ boot_header->ramdisk_image = efi_virt_to_phys(initrd);
+ boot_header->ramdisk_size = PAGE_ALIGN(size);
+ }
+
+ options = linux_bootargs_get();
+ if (options) {
+ boot_header->cmd_line_ptr = efi_virt_to_phys(options);
+ boot_header->cmdline_size = strlen(options);
+ }
+
+ boot_header->code32_start = efi_virt_to_phys(loaded_image->image_base +
+ (image_header->setup_sects+1) * 512);
+
+ if (bootm_verbose(data)) {
+ printf("\nStarting kernel at 0x%p", loaded_image->image_base);
+ if (data->initrd_file)
+ printf(", initrd at 0x%08x",
+ boot_header->ramdisk_image);
+ printf("...\n");
+ }
+
+ if (data->dryrun) {
+ BS->unload_image(handle);
+ free(boot_header);
+ free(initrd);
+ return 0;
+ }
+
+ efi_set_variable_usec("LoaderTimeExecUSec", &efi_systemd_vendor_guid,
+ ktime_to_us(ktime_get()));
+
+ shutdown_barebox();
+ linux_efi_handover(handle, boot_header);
+
+ return 0;
+}
+
+static int efi_load_os(struct efi_image_data *e)
+{
+ return efi_load_file_image(e->data->os_file,
+ &e->loaded_image, &e->handle);
+}
+
+static void efi_unload_os(struct efi_image_data *e)
+{
+ BS->close_protocol(e->handle, &efi_loaded_image_protocol_guid,
+ efi_parent_image, NULL);
+
+ BS->unload_image(e->handle);
+ efi_free_pages(efi_phys_to_virt(e->image_res.base),
+ e->image_res.size);
+}
+
+static int efi_load_ramdisk(struct efi_image_data *e)
+{
+ void *vmem, *tmp = NULL;
+ efi_physical_addr_t mem;
+ efi_status_t efiret = EFI_SUCCESS;
+ const void *initrd;
+ unsigned long initrd_size;
+ int ret;
+
+ if (!e->data->initrd_file)
+ return 0;
+
+ pr_info("Loading ramdisk from '%s'\n", e->data->initrd_file);
+ tmp = read_file(e->data->initrd_file, &initrd_size);
+ if (!tmp || initrd_size <= 0) {
+ pr_err("Failed to read initrd from file: %s\n",
+ e->data->initrd_file);
+ return -EINVAL;
+ }
+ initrd = tmp;
+
+ efiret = BS->allocate_pool(EFI_LOADER_DATA,
+ sizeof(struct efi_mem_resource),
+ (void **)&e->initrd_res);
+ if (EFI_ERROR(efiret) || !e->initrd_res) {
+ ret = -efi_errno(efiret);
+ pr_err("Failed to allocate initrd %s/n", efi_strerror(efiret));
+ goto free_mem;
+ }
+
+ vmem = efi_allocate_pages(&mem, initrd_size,
+ EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA);
+ if (!vmem) {
+ pr_err("Failed to allocate pages for initrd data\n");
+ ret = -ENOMEM;
+ goto free_pool;
+ }
+
+ memcpy(vmem, (void *)initrd, initrd_size);
+ e->initrd_res->base = (uint64_t)mem;
+ e->initrd_res->size = (uint64_t)initrd_size;
+
+ if (IS_ENABLED(CONFIG_EFI_INITRD_INSTALL)) {
+ efiret = BS->install_configuration_table(
+ &efi_linux_initrd_media_guid,
+ (void *)e->initrd_res);
+ if (EFI_ERROR(efiret)) {
+ ret = -efi_errno(efiret);
+ pr_err("Failed to install INITRD %s/n",
+ efi_strerror(efiret));
+ goto free_pages;
+ }
+ } else {
+ ret = efi_initrd_register(vmem, initrd_size);
+ if (ret) {
+ pr_err("Failed to register INITRD %s/n",
+ strerror(efiret));
+ goto free_pages;
+ }
+ }
+
+ free(tmp);
+
+ return 0;
+
+free_pages:
+ efi_free_pages(vmem, initrd_size);
+free_pool:
+ BS->free_pool(e->initrd_res);
+free_mem:
+ free(tmp);
+
+ return ret;
+}
+
+static void efi_unload_ramdisk(struct efi_image_data *e)
+{
+
+ if (IS_ENABLED(CONFIG_EFI_INITRD_INSTALL))
+ BS->install_configuration_table(
+ &efi_linux_initrd_media_guid, NULL);
+ else
+ efi_initrd_unregister();
+
+ efi_free_pages(efi_phys_to_virt(e->initrd_res->base),
+ e->initrd_res->size);
+
+ BS->free_pool(e->initrd_res);
+ e->initrd_res = NULL;
+}
+
+static int efi_load_fdt(struct efi_image_data *e)
+{
+ efi_status_t efiret = EFI_SUCCESS;
+ efi_physical_addr_t mem;
+ void *vmem, *tmp = NULL;
+ const void *of_tree;
+ unsigned long of_size;
+ int ret;
+
+ if (IS_ENABLED(CONFIG_EFI_FDT_FORCE))
+ return 0;
+
+ if (!e->data->oftree_file)
+ return 0;
+
+ pr_info("Loading devicetree from '%s'\n", e->data->oftree_file);
+ tmp = read_file(e->data->oftree_file, &of_size);
+ if (!tmp || of_size <= 0) {
+ pr_err("Failed to read initrd from file: %s\n",
+ e->data->initrd_file);
+ return -EINVAL;
+ }
+ of_tree = tmp;
+
+ vmem = efi_allocate_pages(&mem, SZ_128K,
+ EFI_ALLOCATE_ANY_PAGES,
+ EFI_ACPI_RECLAIM_MEMORY);
+ if (!vmem) {
+ pr_err("Failed to allocate pages for FDT\n");
+ ret = -ENOMEM;
+ goto free_file;
+ }
+
+ memcpy(vmem, of_tree, of_size);
+
+ efiret = BS->install_configuration_table(&efi_fdt_guid,
+ (void *)mem);
+ if (EFI_ERROR(efiret)) {
+ pr_err("Failed to install FDT %s/n", efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto free_mem;
+ }
+
+ e->oftree_res.base = mem;
+ e->oftree_res.size = SZ_128K;
+
+ free(tmp);
+
+ return 0;
+
+free_mem:
+ efi_free_pages(vmem, SZ_128K);
+free_file:
+ free(tmp);
+
+ return ret;
+}
+
+static void efi_unload_fdt(struct efi_image_data *e)
+{
+ BS->install_configuration_table(&efi_fdt_guid, NULL);
+
+ efi_free_pages(efi_phys_to_virt(e->oftree_res.base),
+ e->oftree_res.size);
+}
+
+static int do_bootm_efi_stub(struct image_data *data)
+{
+ struct efi_image_data e = { .data = data };
+ enum filetype type;
+ int ret = 0;
+
+ ret = efi_load_os(&e);
+ if (ret)
+ return ret;
+
+ ret = efi_load_fdt(&e);
+ if (ret)
+ goto unload_os;
+
+ ret = efi_load_ramdisk(&e);
+ if (ret)
+ goto unload_oftree;
+
+ type = file_detect_type(e.loaded_image->image_base, PAGE_SIZE);
+ ret = efi_execute_image(e.handle, e.loaded_image, type);
+ if (ret)
+ goto unload_ramdisk;
+
+ return 0;
+
+unload_ramdisk:
+ if (e.initrd_res)
+ efi_unload_ramdisk(&e);
+unload_oftree:
+ efi_unload_fdt(&e);
+unload_os:
+ efi_unload_os(&e);
+ return ret;
+}
+
+static struct image_handler efi_handle_tr = {
+ .name = "EFI Application",
+ .bootm = do_bootm_efi,
+ .filetype = filetype_exe,
+};
+
+static struct image_handler efi_arm64_handle_tr = {
+ .name = "EFI ARM64 Linux kernel",
+ .bootm = do_bootm_efi_stub,
+ .filetype = filetype_arm64_efi_linux_image,
+};
+
+static int efi_execute(struct binfmt_hook *b, char *file, int argc, char **argv)
+{
+ int ret;
+ efi_handle_t handle;
+ struct efi_loaded_image *loaded_image;
+
+ ret = efi_load_file_image(file, &loaded_image, &handle);
+ if (ret)
+ return ret;
+
+ return efi_execute_image(handle, loaded_image, b->type);
+}
+
+static struct binfmt_hook binfmt_efi_hook = {
+ .type = filetype_exe,
+ .hook = efi_execute,
+};
+
+static int do_bootm_mbr(struct image_data *data)
+{
+ /* On x86, Linux kernel images have a MBR magic at the end of
+ * the first 512 byte sector and a PE magic if they're EFI-stubbed.
+ * The PE magic has precedence over the MBR, so if we arrive in
+ * this boot handler, the kernel has no EFI stub.
+ *
+ * Print a descriptive error message instead of "no image handler
+ * found for image type MBR sector".
+ */
+ pr_err("Can't boot MBR sector: Is CONFIG_EFI_STUB disabled in your Linux kernel config?\n");
+ return -ENOSYS;
+}
+
+static struct image_handler non_efi_handle_linux_x86 = {
+ .name = "non-EFI x86 Linux Image",
+ .bootm = do_bootm_mbr,
+ .filetype = filetype_mbr,
+};
+
+static struct binfmt_hook binfmt_arm64_efi_hook = {
+ .type = filetype_arm64_efi_linux_image,
+ .hook = efi_execute,
+};
+
+static int efi_register_image_handler(void)
+{
+ register_image_handler(&efi_handle_tr);
+ binfmt_register(&binfmt_efi_hook);
+
+ if (IS_ENABLED(CONFIG_X86))
+ register_image_handler(&non_efi_handle_linux_x86);
+
+ if (IS_ENABLED(CONFIG_ARM64)) {
+ register_image_handler(&efi_arm64_handle_tr);
+ binfmt_register(&binfmt_arm64_efi_hook);
+ }
+
+ return 0;
+}
+late_efi_initcall(efi_register_image_handler);
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 03/15] efi: payload: add support for fit image
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
2025-09-20 3:03 ` [PATCH 01/15] efi: payload: split image handling from legacy handover boot support chalianis1
2025-09-20 3:03 ` [PATCH 02/15] efi: payload: add support for efi stub boot chalianis1
@ 2025-09-20 3:03 ` chalianis1
2025-09-20 3:03 ` [PATCH 04/15] efi: payload: make selectable without COMPILE_TEST chalianis1
` (12 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: chalianis1 @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis, Ahmad Fatoum
From: Ahmad Fatoum <a.fatoum@barebox.org>
This patch has more stock, between implementing EFI STUB boot, refactor to
reuse the code and finaly support the fit image format.
This code is tested on many qemu EFI compilations comming from ovmf ubuntu
package, tianocore efi for qemu, local edk2 build, and also tested on RPi3b
64 bit EFI from tianocore and a local build of edk2, more mchines will be
tested soon. the test was for a full boot chain on RPi3b booting a fit image
containing a kernel, an fdt, and a ramdisk with ostree initrd to mount an
ostree root filesystem. for contribution in short term,
1. it would be nice to test with more hardware,
2. linux global checkup of efivars, efi capsule update, efi runtime services
3. The state.dtb to support barebox state to manage multiple system boot
and a recovery.
the case would be sys1 = new ostree commit, sys2 = old commit (rollback)
and a recovery boot system on readonly disk.
4. secure boot, PoC to check if there is a way to load TF-A from EFI
and then load the efi payload from it and launch optee??
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
efi/payload/bootm.c | 148 ++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 126 insertions(+), 22 deletions(-)
diff --git a/efi/payload/bootm.c b/efi/payload/bootm.c
index 6d6ecbf2e49ab7a47cfb9843418abf306b5c51db..ce225ab949c92cb0c52c1334c2395e30b309b781 100644
--- a/efi/payload/bootm.c
+++ b/efi/payload/bootm.c
@@ -25,6 +25,7 @@
#include <libfile.h>
#include <binfmt.h>
#include <wchar.h>
+#include <image-fit.h>
#include <efi/efi-payload.h>
#include <efi/efi-device.h>
@@ -227,10 +228,93 @@ static int do_bootm_efi(struct image_data *data)
return 0;
}
+static bool ramdisk_is_fit(struct image_data *data)
+{
+ struct stat st;
+
+ if (bootm_signed_images_are_forced())
+ return true;
+
+ if (data->initrd_file) {
+ if (!stat(data->initrd_file, &st) && st.st_size > 0)
+ return false;
+ }
+
+ return data->os_fit ? fit_has_image(data->os_fit,
+ data->fit_config, "ramdisk") > 0 : false;
+}
+
+static bool fdt_is_fit(struct image_data *data)
+{
+ struct stat st;
+
+ if (bootm_signed_images_are_forced())
+ return true;
+
+ if (data->oftree_file) {
+ if (!stat(data->oftree_file, &st) && st.st_size > 0)
+ return false;
+ }
+
+ return data->os_fit ? fit_has_image(data->os_fit,
+ data->fit_config, "fdt") > 0 : false;
+}
+
static int efi_load_os(struct efi_image_data *e)
{
- return efi_load_file_image(e->data->os_file,
- &e->loaded_image, &e->handle);
+ efi_status_t efiret = EFI_SUCCESS;
+ efi_physical_addr_t mem;
+ size_t image_size = 0;
+ void *image = NULL;
+ void *vmem = NULL;
+ int ret = 0;
+
+ if (!e->data->os_fit)
+ return efi_load_file_image(e->data->os_file,
+ &e->loaded_image, &e->handle);
+
+ image = (void *)e->data->fit_kernel;
+ image_size = e->data->fit_kernel_size;
+
+ if (image_size <= 0 || !image)
+ return -EINVAL;
+
+ vmem = efi_allocate_pages(&mem, image_size, EFI_ALLOCATE_ANY_PAGES,
+ EFI_LOADER_CODE);
+ if (!vmem) {
+ pr_err("Failed to allocate pages for image\n");
+ return -ENOMEM;
+ }
+
+ memcpy(vmem, image, image_size);
+
+ efiret = BS->load_image(false, efi_parent_image, efi_device_path, image,
+ image_size, &e->handle);
+ if (EFI_ERROR(efiret)) {
+ ret = -efi_errno(efiret);
+ pr_err("failed to LoadImage: %s\n", efi_strerror(efiret));
+ goto out_mem;
+ };
+
+ efiret = BS->open_protocol(e->handle, &efi_loaded_image_protocol_guid,
+ (void **)&e->loaded_image, efi_parent_image,
+ NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(efiret)) {
+ ret = -efi_errno(efiret);
+ pr_err("failed to OpenProtocol: %s\n", efi_strerror(efiret));
+ goto out_unload;
+ }
+
+ e->image_res.base = mem;
+ e->image_res.size = image_size;
+
+ return 0;
+
+out_mem:
+ efi_free_pages(vmem, image_size);
+out_unload:
+ BS->unload_image(e->handle);
+ return ret;
}
static void efi_unload_os(struct efi_image_data *e)
@@ -252,17 +336,27 @@ static int efi_load_ramdisk(struct efi_image_data *e)
unsigned long initrd_size;
int ret;
- if (!e->data->initrd_file)
- return 0;
-
- pr_info("Loading ramdisk from '%s'\n", e->data->initrd_file);
- tmp = read_file(e->data->initrd_file, &initrd_size);
- if (!tmp || initrd_size <= 0) {
- pr_err("Failed to read initrd from file: %s\n",
- e->data->initrd_file);
- return -EINVAL;
+ if (ramdisk_is_fit(e->data)) {
+ ret = fit_open_image(e->data->os_fit, e->data->fit_config,
+ "ramdisk", &initrd, &initrd_size);
+ if (ret) {
+ pr_err("Cannot open ramdisk image in FIT image: %pe\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+ } else {
+ if (!e->data->initrd_file)
+ return 0;
+
+ pr_info("Loading ramdisk from '%s'\n", e->data->initrd_file);
+ tmp = read_file(e->data->initrd_file, &initrd_size);
+ if (!tmp || initrd_size <= 0) {
+ pr_err("Failed to read initrd from file: %s\n",
+ e->data->initrd_file);
+ return -EINVAL;
+ }
+ initrd = tmp;
}
- initrd = tmp;
efiret = BS->allocate_pool(EFI_LOADER_DATA,
sizeof(struct efi_mem_resource),
@@ -346,17 +440,27 @@ static int efi_load_fdt(struct efi_image_data *e)
if (IS_ENABLED(CONFIG_EFI_FDT_FORCE))
return 0;
- if (!e->data->oftree_file)
- return 0;
-
- pr_info("Loading devicetree from '%s'\n", e->data->oftree_file);
- tmp = read_file(e->data->oftree_file, &of_size);
- if (!tmp || of_size <= 0) {
- pr_err("Failed to read initrd from file: %s\n",
- e->data->initrd_file);
- return -EINVAL;
+ if (fdt_is_fit(e->data)) {
+ ret = fit_open_image(e->data->os_fit, e->data->fit_config,
+ "fdt", &of_tree, &of_size);
+ if (ret) {
+ pr_err("Cannot open FDT image in FIT image: %pe\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+ } else {
+ if (!e->data->oftree_file)
+ return 0;
+
+ pr_info("Loading devicetree from '%s'\n", e->data->oftree_file);
+ tmp = read_file(e->data->oftree_file, &of_size);
+ if (!tmp || of_size <= 0) {
+ pr_err("Failed to read initrd from file: %s\n",
+ e->data->initrd_file);
+ return -EINVAL;
+ }
+ of_tree = tmp;
}
- of_tree = tmp;
vmem = efi_allocate_pages(&mem, SZ_128K,
EFI_ALLOCATE_ANY_PAGES,
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 04/15] efi: payload: make selectable without COMPILE_TEST
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (2 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 03/15] efi: payload: add support for fit image chalianis1
@ 2025-09-20 3:03 ` chalianis1
2025-09-20 3:03 ` [PATCH 05/15] arm: efi: add a generic defconfig for v8 efi payload, Chali Anis
` (11 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: chalianis1 @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis, Ahmad Fatoum
From: Ahmad Fatoum <a.fatoum@barebox.org>
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
efi/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/efi/Kconfig b/efi/Kconfig
index 5f4c6713d539abc88e3244f7ff3933274a8c4ebb..5ae7ec92e5f8d12f72842c5c97bc9ed924b6dff9 100644
--- a/efi/Kconfig
+++ b/efi/Kconfig
@@ -6,7 +6,7 @@ config HAVE_EFI_PAYLOAD
bool
config EFI_PAYLOAD
- bool "Build as EFI payload" if COMPILE_TEST
+ bool "Build as EFI payload"
depends on HAVE_EFI_PAYLOAD
select PBL_FULLY_PIC if ARM64
select EFI
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 05/15] arm: efi: add a generic defconfig for v8 efi payload,
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (3 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 04/15] efi: payload: make selectable without COMPILE_TEST chalianis1
@ 2025-09-20 3:03 ` Chali Anis
2025-09-20 3:03 ` [PATCH 06/15] efi: payload: initrd: implement efi initrd media protocol Chali Anis
` (10 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chali Anis @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
arch/arm/configs/efi_v8_defconfig | 266 ++++++++++++++++++++++++++++++++++++++
1 file changed, 266 insertions(+)
diff --git a/arch/arm/configs/efi_v8_defconfig b/arch/arm/configs/efi_v8_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..607ab44e473f6ad910c1944f2828b6255e5ade10
--- /dev/null
+++ b/arch/arm/configs/efi_v8_defconfig
@@ -0,0 +1,266 @@
+CONFIG_64BIT=y
+CONFIG_CPU_V8=y
+CONFIG_MMU=y
+CONFIG_MALLOC_SIZE=0x0
+CONFIG_NAME="efi_v8_defconfig"
+CONFIG_EFI_PAYLOAD=y
+CONFIG_FS_EFI=y
+CONFIG_FS_EFIVARFS=y
+CONFIG_DRIVER_SERIAL_EFI_STDIO=y
+CONFIG_EFI_BLK=y
+CONFIG_EFI_BLK_SEPARATE_USBDISK=y
+CONFIG_WATCHDOG_EFI=y
+CONFIG_HW_RANDOM_EFI=y
+CONFIG_I2C_EFI=y
+CONFIG_VIDEO=y
+CONFIG_DRIVER_VIDEO_EFI_GOP=y
+CONFIG_CLOCKSOURCE_EFI=y
+CONFIG_SERIAL_EFI_STDIO=y
+CONFIG_CMD_EFI_HANDLE_DUMP=y
+CONFIG_BOOTM_FITIMAGE=y
+CONFIG_PROMPT_HUSH_PS2="y"
+CONFIG_CMDLINE_EDITING=y
+CONFIG_BOOTM_SHOW_TYPE=y
+CONFIG_BOOTM_VERBOSE=y
+CONFIG_CONSOLE_ACTIVATE_ALL=y
+CONFIG_CONSOLE_ALLOW_COLOR=y
+CONFIG_PBL_CONSOLE=y
+CONFIG_PROMPT="barebox> "
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_PARTITION_DISK_EFI=y
+CONFIG_MENU=y
+CONFIG_BOOTM_INITRD=y
+CONFIG_BOOTM_OFTREE=y
+CONFIG_BLSPEC=y
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_ARM_PSCI_CLIENT=y
+CONFIG_KALLSYMS=y
+CONFIG_BOOTM_AIMAGE=y
+CONFIG_BLSPEC=y
+CONFIG_CONSOLE_ACTIVATE_ALL_FALLBACK=y
+CONFIG_CONSOLE_RATP=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_STATE=y
+CONFIG_BOOTCHOOSER=y
+CONFIG_RESET_SOURCE=y
+CONFIG_MACHINE_ID=y
+CONFIG_FASTBOOT_SPARSE=y
+CONFIG_CMD_DMESG=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_IMD=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_ARM_MMUINFO=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_BFETCH=y
+CONFIG_CMD_MMC_EXTCSD=y
+CONFIG_CMD_POLLER=y
+CONFIG_CMD_SLICE=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_BOOTCHOOSER=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_FINDMNT=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_DEFAULTENV=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_SHA1SUM=y
+CONFIG_CMD_SHA224SUM=y
+CONFIG_CMD_SHA256SUM=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_LET=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_READF=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_LOGIN=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_MENUTREE=y
+CONFIG_CMD_PASSWD=y
+CONFIG_CMD_SPLASH=y
+CONFIG_CMD_FBTEST=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_CLK=y
+CONFIG_CMD_DETECT=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_POWEROFF=y
+CONFIG_CMD_SMC=y
+CONFIG_CMD_LED_TRIGGER=y
+CONFIG_CMD_USBGADGET=y
+CONFIG_CMD_WD=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_FIRMWARELOAD=y
+CONFIG_CMD_OF_DIFF=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OF_DISPLAY_TIMINGS=y
+CONFIG_CMD_OF_FIXUP_STATUS=y
+CONFIG_CMD_OF_OVERLAY=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_TIME=y
+CONFIG_NET=y
+CONFIG_NET_NETCONSOLE=y
+CONFIG_NET_SNTP=y
+CONFIG_NET_FASTBOOT=y
+CONFIG_NET_9P=y
+CONFIG_NET_9P_VIRTIO=y
+CONFIG_DEEP_PROBE_DEFAULT=y
+CONFIG_OF_BAREBOX_DRIVERS=y
+CONFIG_OF_BAREBOX_ENV_IN_FS=y
+CONFIG_OF_OVERLAY_LIVE=y
+CONFIG_SERIAL_DEV_BUS=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_DRIVER_SERIAL_CADENCE=y
+CONFIG_DRIVER_SERIAL_LPUART32=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_DRIVER_NET_TI_K3_AM65_CPSW_NUSS=y
+CONFIG_DRIVER_NET_DESIGNWARE_IMX8=y
+CONFIG_DRIVER_NET_DESIGNWARE_ROCKCHIP=y
+CONFIG_DRIVER_NET_FEC_IMX=y
+CONFIG_DRIVER_NET_FSL_ENETC=y
+CONFIG_DRIVER_NET_FSL_FMAN=y
+CONFIG_DRIVER_NET_MACB=y
+CONFIG_DRIVER_NET_VIRTIO=y
+CONFIG_DP83867_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_NET_DSA_MV88E6XXX=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_MDIO_GPIO=y
+CONFIG_MDIO_BUS_MUX_GPIO=y
+CONFIG_NET_USB=y
+CONFIG_NET_USB_ASIX=y
+CONFIG_USB_NET_AX88179_178A=y
+CONFIG_NET_USB_SMSC95XX=y
+CONFIG_NET_USB_RTL8152=y
+CONFIG_DRIVER_SPI_FSL_QUADSPI=y
+CONFIG_DRIVER_SPI_IMX=y
+CONFIG_SPI_NXP_FLEXSPI=y
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_IMX=y
+CONFIG_I2C_OMAP=y
+CONFIG_I2C_RK3X=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_M25P80=y
+CONFIG_DRIVER_CFI=y
+CONFIG_CFI_BUFFER_WRITE=y
+CONFIG_VIRTIO_BLK=y
+CONFIG_USB_HOST=y
+CONFIG_USB_IMX_CHIPIDEA=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_DUAL_ROLE=y
+CONFIG_USB_EHCI=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_ONBOARD_DEV=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_SERIAL=y
+CONFIG_USB_GADGET_FASTBOOT=y
+CONFIG_USB_GADGET_MASS_STORAGE=y
+CONFIG_VIDEO=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_DRIVER_VIDEO_BOCHS_PCI=y
+CONFIG_SOUND=y
+CONFIG_MCI=y
+CONFIG_MCI_MMC_BOOT_PARTITIONS=y
+CONFIG_MCI_DW=y
+CONFIG_MCI_SUNXI_SMHC=y
+CONFIG_MCI_ROCKCHIP_DWCMSHC=y
+CONFIG_MCI_IMX_ESDHC=y
+CONFIG_MCI_ARASAN=y
+CONFIG_MCI_AM654=y
+CONFIG_COMMON_CLK=y
+CONFIG_COMMON_CLK_SCMI=y
+CONFIG_MFD_ACT8846=y
+CONFIG_RAVE_SP_CORE=y
+CONFIG_MFD_PCA9450=y
+CONFIG_MFD_RK808=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_GPIO_OF=y
+CONFIG_LED_TRIGGERS=y
+CONFIG_LED_PCA955X=y
+CONFIG_EEPROM_AT25=y
+CONFIG_EEPROM_AT24=y
+CONFIG_VIRTIO_INPUT=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_POLLER=y
+CONFIG_WATCHDOG_DW=y
+CONFIG_WATCHDOG_IMX=y
+CONFIG_WATCHDOG_IMXULP=y
+CONFIG_RAVE_SP_WATCHDOG=y
+CONFIG_K3_RTI_WDT=y
+CONFIG_HWRNG=y
+CONFIG_HW_RANDOM_VIRTIO=y
+CONFIG_DMADEVICES=y
+CONFIG_TI_K3_UDMA=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_ZYNQ=y
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_NVMEM_RMEM=y
+CONFIG_IMX_OCOTP_ELE=y
+CONFIG_RAVE_SP_EEPROM=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED=y
+CONFIG_REGULATOR_ARM_SCMI=y
+CONFIG_REGULATOR_RK808=y
+CONFIG_RESET_IMX7=y
+CONFIG_PCI_ECAM_GENERIC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_FIRMWARE_ZYNQMP_FPGA=y
+CONFIG_ARM_SCMI_PROTOCOL=y
+CONFIG_GENERIC_PHY=y
+CONFIG_USB_NOP_XCEIV=y
+CONFIG_PHY_ROCKCHIP_INNO_USB2=y
+CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=y
+CONFIG_ROCKCHIP_IODOMAIN=y
+CONFIG_TI_SCI_PM_DOMAINS=y
+CONFIG_NVMEM_REBOOT_MODE=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_PCI=y
+CONFIG_MAILBOX=y
+CONFIG_FS_CRAMFS=y
+CONFIG_FS_EXT4=y
+CONFIG_FS_TFTP=y
+CONFIG_FS_NFS=y
+CONFIG_9P_FS=y
+CONFIG_9P_FS_WRITE=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_BPKFS=y
+CONFIG_FS_UIMAGEFS=y
+CONFIG_FS_PSTORE=y
+CONFIG_FS_PSTORE_CONSOLE=y
+CONFIG_FS_RATP=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DIGEST_SHA1_ARM64_CE=y
+CONFIG_DIGEST_SHA256_ARM64_CE=y
+# CONFIG_MISSING_FIRMWARE_ERROR is not set
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 06/15] efi: payload: initrd: implement efi initrd media protocol.
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (4 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 05/15] arm: efi: add a generic defconfig for v8 efi payload, Chali Anis
@ 2025-09-20 3:03 ` Chali Anis
2025-09-20 3:03 ` [PATCH 07/15] common: filetype: add x86 linux filetype Chali Anis
` (9 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chali Anis @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis
Add the ability to install an initrd media protocol from an initrd file
or a fitImage, support both the initrd media protocol or installing the
initramfs directly to efi like what linux do.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
efi/guid.c | 7 +++
efi/payload/efi-initrd.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++
include/efi.h | 4 ++
include/efi/efi-payload.h | 3 ++
4 files changed, 137 insertions(+)
diff --git a/efi/guid.c b/efi/guid.c
index ef230a2b240321634544cb63f8bf93d28bb5f100..7b572acb768b5cc999dbf3eff390f48d8c226444 100644
--- a/efi/guid.c
+++ b/efi/guid.c
@@ -44,6 +44,7 @@ const efi_guid_t efi_load_file_protocol_guid = EFI_LOAD_FILE_PROTOCOL_GUID;
const efi_guid_t efi_load_file2_protocol_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;
const efi_guid_t efi_device_path_utilities_protocol_guid =
EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID;
+const efi_guid_t efi_linux_initrd_media_guid = EFI_LINUX_INITRD_MEDIA_GUID;
#define EFI_GUID_STRING(guid, short, long) do { \
if (!efi_guidcmp(guid, *g)) \
@@ -128,5 +129,11 @@ const char *efi_guid_string(efi_guid_t *g)
EFI_GUID_STRING(EFI_ISCSIDXE_INF_GUID, "IScsiDxe.inf", "EFI IScsiDxe.inf File GUID");
EFI_GUID_STRING(EFI_VLANCONFIGDXE_INF_GUID, "VlanConfigDxe.inf", "EFI VlanConfigDxe.inf File GUID");
+ /* FDT */
+ EFI_GUID_STRING(EFI_DEVICE_TREE_GUID, "DeviceTree", "EFI Device Tree GUID");
+
+ /* Ramdisk */
+ EFI_GUID_STRING(EFI_LINUX_INITRD_MEDIA_GUID, "Initrd Media", "EFI Linux Initrd Media GUID");
+
return "unknown";
}
diff --git a/efi/payload/efi-initrd.c b/efi/payload/efi-initrd.c
new file mode 100644
index 0000000000000000000000000000000000000000..633fbc29c137bfc05a1da9fda05b332e5449e9f6
--- /dev/null
+++ b/efi/payload/efi-initrd.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * efi-initrd.c - barebox EFI payload support
+ *
+ * Copyright (c) 2025 Anis Chali <chalianis1@gmail.com>
+ */
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <linux/hw_random.h>
+#include <efi.h>
+#include <efi/efi-device.h>
+#include <efi/device-path.h>
+#include <efi/efi-payload.h>
+
+static efi_status_t EFIAPI efi_initrd_load_file2(
+ struct efi_load_file_protocol *this, struct efi_device_path *file_path,
+ bool boot_policy, unsigned long *buffer_size, void *buffer);
+
+static const struct {
+ struct efi_device_path_vendor vendor;
+ struct efi_device_path end;
+} __packed initrd_dev_path = { { {
+ DEVICE_PATH_TYPE_MEDIA_DEVICE,
+ DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
+ sizeof(initrd_dev_path.vendor),
+ },
+ EFI_LINUX_INITRD_MEDIA_GUID },
+ { DEVICE_PATH_TYPE_END, DEVICE_PATH_SUB_TYPE_END,
+ DEVICE_PATH_END_LENGTH } };
+
+static struct efi_device_path_memory *initrd_dev;
+static efi_handle_t lf2_handle;
+static struct efi_load_file_protocol efi_lf2_p = {
+ .load_file = efi_initrd_load_file2
+};
+
+static efi_status_t EFIAPI efi_initrd_load_file2(
+ struct efi_load_file_protocol *this, struct efi_device_path *file_path,
+ bool boot_policy, unsigned long *buffer_size, void *buffer)
+{
+ size_t initrd_size;
+
+ if (!this || this != &efi_lf2_p || !buffer_size)
+ return EFI_INVALID_PARAMETER;
+
+ if (file_path->type != initrd_dev_path.end.type ||
+ file_path->sub_type != initrd_dev_path.end.sub_type)
+ return EFI_INVALID_PARAMETER;
+
+ if (boot_policy)
+ return EFI_UNSUPPORTED;
+
+ initrd_size = initrd_dev->ending_address - initrd_dev->starting_address;
+ if (!buffer || *buffer_size < initrd_size) {
+ *buffer_size = initrd_size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ else {
+ memcpy(buffer, (void *)(uintptr_t)initrd_dev->starting_address,
+ initrd_size);
+ *buffer_size = initrd_size;
+ }
+
+ return EFI_SUCCESS;
+}
+
+int efi_initrd_register(void *initrd, size_t initrd_sz)
+{
+ efi_physical_addr_t mem;
+ efi_status_t efiret;
+ size_t sz;
+ int ret;
+
+ sz = sizeof(struct efi_device_path_memory) +
+ sizeof(struct efi_device_path);
+ efiret = BS->allocate_pool(EFI_BOOT_SERVICES_DATA, sz, (void **)&mem);
+ if (EFI_ERROR(efiret)) {
+ pr_err("Failed to allocate memory for INITRD %s\n",
+ efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ return ret;
+ }
+
+ initrd_dev = efi_phys_to_virt(mem);
+ initrd_dev->header.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
+ initrd_dev->header.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY;
+ initrd_dev->header.length = sizeof(struct efi_device_path_memory);
+ initrd_dev->memory_type = EFI_LOADER_DATA;
+ initrd_dev->starting_address = efi_virt_to_phys(initrd);
+ initrd_dev->ending_address = efi_virt_to_phys(initrd) + initrd_sz;
+
+ memcpy(&initrd_dev[1], &initrd_dev_path.end, DEVICE_PATH_END_LENGTH);
+
+ efiret = BS->install_multiple_protocol_interfaces(
+ &lf2_handle, &efi_load_file2_protocol_guid, &efi_lf2_p,
+ &efi_device_path_protocol_guid, &initrd_dev_path, NULL);
+ if (EFI_ERROR(efiret)) {
+ pr_err("Failed to install protocols for INITRD %s\n",
+ efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ return 0;
+out:
+ BS->free_pool(efi_phys_to_virt(mem));
+ return ret;
+}
+
+void efi_initrd_unregister(void)
+{
+ if (!initrd_dev)
+ return;
+
+ BS->uninstall_multiple_protocol_interfaces(
+ lf2_handle, &efi_device_path_protocol_guid, &initrd_dev_path,
+ &efi_load_file2_protocol_guid, &efi_lf2_p, NULL);
+
+ BS->free_pool(initrd_dev);
+ initrd_dev = NULL;
+}
diff --git a/include/efi.h b/include/efi.h
index 40b69fdb01889e074c8014a69db706159329d883..bd339ea097c311cbe607d2084f23967c62ab63aa 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -558,6 +558,9 @@ extern struct efi_runtime_services *RT;
#define EFI_DRIVER_BINDING_PROTOCOL_GUID \
EFI_GUID(0x18a031ab, 0xb443, 0x4d1a, 0xa5, 0xc0, 0x0c, 0x09, 0x26, 0x1e, 0x9f, 0x71)
+#define EFI_LINUX_INITRD_MEDIA_GUID \
+ EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68)
+
struct efi_driver_binding_protocol {
efi_status_t (EFIAPI * supported)(
struct efi_driver_binding_protocol *this,
@@ -603,6 +606,7 @@ extern const efi_guid_t efi_guid_event_group_reset_system;
extern const efi_guid_t efi_load_file_protocol_guid;
extern const efi_guid_t efi_load_file2_protocol_guid;
extern const efi_guid_t efi_device_path_utilities_protocol_guid;
+extern const efi_guid_t efi_linux_initrd_media_guid;
struct efi_config_table {
efi_guid_t guid;
diff --git a/include/efi/efi-payload.h b/include/efi/efi-payload.h
index fe45864dd8a7fb6a4e73b640add56016d005262b..d8e66a187a870fcae9288d9c65984896e5196c31 100644
--- a/include/efi/efi-payload.h
+++ b/include/efi/efi-payload.h
@@ -34,4 +34,7 @@ int efi_set_variable_usec(char *name, efi_guid_t *vendor, uint64_t usec);
void *efi_earlymem_alloc(const struct efi_system_table *sys_table,
size_t *memsize, enum efi_memory_type mem_type);
+int efi_initrd_register(void *initrd, size_t initrd_size);
+void efi_initrd_unregister(void);
+
#endif
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 07/15] common: filetype: add x86 linux filetype.
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (5 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 06/15] efi: payload: initrd: implement efi initrd media protocol Chali Anis
@ 2025-09-20 3:03 ` Chali Anis
2025-09-20 3:03 ` [PATCH 08/15] efi: payload: early-mem: helps to correctly boot x86 linux Chali Anis
` (8 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chali Anis @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis
add x86 linux filetype to be used to boot with efi stub
bootm image handler.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
common/filetype.c | 4 ++++
include/filetype.h | 6 ++++++
2 files changed, 10 insertions(+)
diff --git a/common/filetype.c b/common/filetype.c
index eb397a175cb63df06e4426d2b99e4fde360c5b11..8735d3b16723b88c470750a1ca9ca10a6bcbba14 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -87,6 +87,8 @@ static const struct filetype_str filetype_str[] = {
[filetype_zstd_compressed] = { "ZSTD compressed", "zstd" },
[filetype_rockchip_rkss_image] = { "Rockchip signed boot image",
"rk-image" },
+ [filetype_x86_efi_linux_image] = { "X86 Linux/EFI image",
+ "x86-efi-linux" },
};
static const char *file_type_to_nr_string(enum filetype f)
@@ -435,6 +437,8 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
return is_dos_exe(buf8) ? filetype_riscv_efi_linux_image : filetype_riscv_linux_image;
if (is_riscv_linux_bootimage(buf) && !memcmp(&buf[12], "barebox", 8))
return filetype_riscv_barebox_image;
+ if (bufsize > 0x206 && is_x86_linux_bootimage(buf))
+ return filetype_x86_efi_linux_image;
if (le32_to_cpu(buf[5]) == 0x504d5453)
return filetype_mxs_bootstream;
diff --git a/include/filetype.h b/include/filetype.h
index 6f4a103df3040ef259660d06ca878f72e2245c12..7ca9fe2158cbd20cda3ed587293a91addf2bd79c 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -67,6 +67,7 @@ enum filetype {
filetype_nxp_fspi_image,
filetype_zstd_compressed,
filetype_rockchip_rkss_image,
+ filetype_x86_efi_linux_image,
filetype_max,
};
@@ -150,4 +151,9 @@ static inline bool is_riscv_linux_bootimage(const void *header)
return le32_to_cpup(header + 56) == 0x05435352;
}
+static inline bool is_x86_linux_bootimage(const void *header)
+{
+ return le32_to_cpup(header + 0x202) == 0x53726448;
+}
+
#endif /* __FILE_TYPE_H */
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 08/15] efi: payload: early-mem: helps to correctly boot x86 linux.
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (6 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 07/15] common: filetype: add x86 linux filetype Chali Anis
@ 2025-09-20 3:03 ` Chali Anis
2025-09-20 3:03 ` [PATCH 09/15] efi: payload: bootm: add x86 efi stub boot support Chali Anis
` (7 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chali Anis @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis
remove the allocate EFI_ALLOCATE_MAX_ADDRESSES and use a different
memsize for x86 since the initrd could be bigger that those used in
arm. it might be refactored in the future with a more generic allocation
strategy (i.e barebox malloc memory vs an allocator for the boot loader data)
something like sdram_request_region or just allocate small memory for the
barebox allocator and implement a way to allocate memory for kernel/initrd
directly from efi.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
efi/payload/early-mem.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/efi/payload/early-mem.c b/efi/payload/early-mem.c
index 0f79a8c306942f21169a947cb957e0318a54294e..150a2a595afcdb69026f98c53f9a3bf3425da999 100644
--- a/efi/payload/early-mem.c
+++ b/efi/payload/early-mem.c
@@ -9,18 +9,17 @@ void *efi_earlymem_alloc(const struct efi_system_table *sys_table,
size_t *memsize, enum efi_memory_type mem_type)
{
struct efi_boot_services *bs = sys_table->boottime;
- enum efi_allocate_type alloc_type = EFI_ALLOCATE_ANY_PAGES;
efi_physical_addr_t mem;
efi_status_t efiret;
+ size_t m_sz;
- if (IS_ENABLED(CONFIG_X86)) {
- /* Try to stay clear of memory mapped devices */
- alloc_type = EFI_ALLOCATE_MAX_ADDRESS;
- mem = SZ_1G - 1;
- }
+ if (IS_ENABLED(CONFIG_X86))
+ m_sz = SZ_512M;
+ else
+ m_sz = SZ_256M;
- for (*memsize = SZ_256M; *memsize >= SZ_8M; *memsize /= 2) {
- efiret = bs->allocate_pages(alloc_type, mem_type,
+ for (*memsize = m_sz; *memsize >= SZ_8M; *memsize /= 2) {
+ efiret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES, mem_type,
*memsize / EFI_PAGE_SIZE, &mem);
if (!EFI_ERROR(efiret) || efiret != EFI_OUT_OF_RESOURCES)
break;
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 09/15] efi: payload: bootm: add x86 efi stub boot support.
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (7 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 08/15] efi: payload: early-mem: helps to correctly boot x86 linux Chali Anis
@ 2025-09-20 3:03 ` Chali Anis
2025-09-20 3:03 ` [PATCH 10/15] efi: payload: x86: enable the possibility to efi stub bootm for x86 Chali Anis
` (6 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chali Anis @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis
implement the efi stub boot on x86, this code is tested on qemu,
and dell latitude 7490. the EFI_ALLOCATE_MAX_PAGES cause an xfuncs
issue on real hardware so I transformed it to allocate any pages.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
efi/payload/bootm.c | 139 ++++++++++++++--------------------------------------
1 file changed, 38 insertions(+), 101 deletions(-)
diff --git a/efi/payload/bootm.c b/efi/payload/bootm.c
index ce225ab949c92cb0c52c1334c2395e30b309b781..401aefe28188bb4335f73a8e259a16c605096626 100644
--- a/efi/payload/bootm.c
+++ b/efi/payload/bootm.c
@@ -133,101 +133,6 @@ static int efi_load_file_image(const char *file,
return ret;
}
-typedef void(*handover_fn)(void *image, struct efi_system_table *table,
- struct x86_setup_header *header);
-
-static inline void linux_efi_handover(efi_handle_t handle,
- struct x86_setup_header *header)
-{
- handover_fn handover;
- uintptr_t addr;
-
- addr = header->code32_start + header->handover_offset;
- if (IS_ENABLED(CONFIG_X86_64))
- addr += 512;
-
- handover = efi_phys_to_virt(addr);
- handover(handle, efi_sys_table, header);
-}
-
-static int do_bootm_efi(struct image_data *data)
-{
- void *tmp;
- void *initrd = NULL;
- size_t size;
- efi_handle_t handle;
- int ret;
- const char *options;
- struct efi_loaded_image *loaded_image;
- struct x86_setup_header *image_header, *boot_header;
-
- ret = efi_load_file_image(data->os_file, &loaded_image, &handle);
- if (ret)
- return ret;
-
- image_header = (struct x86_setup_header *)loaded_image->image_base;
-
- if (image_header->boot_flag != 0xAA55 ||
- image_header->header != 0x53726448 ||
- image_header->version < 0x20b ||
- !image_header->relocatable_kernel) {
- pr_err("Not a valid kernel image!\n");
- BS->unload_image(handle);
- return -EINVAL;
- }
-
- boot_header = xmalloc(0x4000);
- memset(boot_header, 0, 0x4000);
- memcpy(boot_header, image_header, sizeof(*image_header));
-
- /* Refer to Linux kernel commit a27e292b8a54
- * ("Documentation/x86/boot: Reserve type_of_loader=13 for barebox")
- */
- boot_header->type_of_loader = 0x13;
-
- if (data->initrd_file) {
- tmp = read_file(data->initrd_file, &size);
- initrd = xmemalign(PAGE_SIZE, PAGE_ALIGN(size));
- memcpy(initrd, tmp, size);
- memset(initrd + size, 0, PAGE_ALIGN(size) - size);
- free(tmp);
- boot_header->ramdisk_image = efi_virt_to_phys(initrd);
- boot_header->ramdisk_size = PAGE_ALIGN(size);
- }
-
- options = linux_bootargs_get();
- if (options) {
- boot_header->cmd_line_ptr = efi_virt_to_phys(options);
- boot_header->cmdline_size = strlen(options);
- }
-
- boot_header->code32_start = efi_virt_to_phys(loaded_image->image_base +
- (image_header->setup_sects+1) * 512);
-
- if (bootm_verbose(data)) {
- printf("\nStarting kernel at 0x%p", loaded_image->image_base);
- if (data->initrd_file)
- printf(", initrd at 0x%08x",
- boot_header->ramdisk_image);
- printf("...\n");
- }
-
- if (data->dryrun) {
- BS->unload_image(handle);
- free(boot_header);
- free(initrd);
- return 0;
- }
-
- efi_set_variable_usec("LoaderTimeExecUSec", &efi_systemd_vendor_guid,
- ktime_to_us(ktime_get()));
-
- shutdown_barebox();
- linux_efi_handover(handle, boot_header);
-
- return 0;
-}
-
static bool ramdisk_is_fit(struct image_data *data)
{
struct stat st;
@@ -368,9 +273,9 @@ static int efi_load_ramdisk(struct efi_image_data *e)
}
vmem = efi_allocate_pages(&mem, initrd_size,
- EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA);
+ EFI_ALLOCATE_ANY_PAGES, EFI_LOADER_DATA);
if (!vmem) {
- pr_err("Failed to allocate pages for initrd data\n");
+ pr_err("Failed to allocate pages for initrd data: %s\n", strerror(errno));
ret = -ENOMEM;
goto free_pool;
}
@@ -498,6 +403,9 @@ static int efi_load_fdt(struct efi_image_data *e)
static void efi_unload_fdt(struct efi_image_data *e)
{
+ if (IS_ENABLED(CONFIG_EFI_FDT_FORCE))
+ return;
+
BS->install_configuration_table(&efi_fdt_guid, NULL);
efi_free_pages(efi_phys_to_virt(e->oftree_res.base),
@@ -539,12 +447,33 @@ static int do_bootm_efi_stub(struct image_data *data)
return ret;
}
-static struct image_handler efi_handle_tr = {
+static int efi_app_execute(struct image_data *data)
+{
+ int ret;
+ struct efi_image_data e = { .data = data };
+ enum filetype type;
+
+ ret = efi_load_file_image(data->os_file, &e.loaded_image, &e.handle);
+ if (ret)
+ return ret;
+
+ type = file_detect_type(e.loaded_image->image_base, PAGE_SIZE);
+
+ return efi_execute_image(e.handle, e.loaded_image, type);
+}
+
+static struct image_handler efi_app_handle_tr = {
.name = "EFI Application",
- .bootm = do_bootm_efi,
+ .bootm = efi_app_execute,
.filetype = filetype_exe,
};
+static struct image_handler efi_x86_linux_handle_tr = {
+ .name = "EFI X86 Linux kernel",
+ .bootm = do_bootm_efi_stub,
+ .filetype = filetype_x86_efi_linux_image,
+};
+
static struct image_handler efi_arm64_handle_tr = {
.name = "EFI ARM64 Linux kernel",
.bootm = do_bootm_efi_stub,
@@ -594,13 +523,21 @@ static struct binfmt_hook binfmt_arm64_efi_hook = {
.hook = efi_execute,
};
+static struct binfmt_hook binfmt_x86_efi_hook = {
+ .type = filetype_x86_efi_linux_image,
+ .hook = efi_execute,
+};
+
static int efi_register_image_handler(void)
{
- register_image_handler(&efi_handle_tr);
+ register_image_handler(&efi_app_handle_tr);
binfmt_register(&binfmt_efi_hook);
- if (IS_ENABLED(CONFIG_X86))
+ if (IS_ENABLED(CONFIG_X86)) {
register_image_handler(&non_efi_handle_linux_x86);
+ register_image_handler(&efi_x86_linux_handle_tr);
+ binfmt_register(&binfmt_x86_efi_hook);
+ }
if (IS_ENABLED(CONFIG_ARM64)) {
register_image_handler(&efi_arm64_handle_tr);
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 10/15] efi: payload: x86: enable the possibility to efi stub bootm for x86.
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (8 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 09/15] efi: payload: bootm: add x86 efi stub boot support Chali Anis
@ 2025-09-20 3:03 ` Chali Anis
2025-09-20 3:03 ` [PATCH 11/15] malloc: tlsf: efi: add a fallback for allocate more memory when we are in efi Chali Anis
` (5 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chali Anis @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis
this permits to select one of efi stub bootm or efi handover protocol
tested on dell latitude and qemu.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
efi/payload/Kconfig | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/efi/payload/Kconfig b/efi/payload/Kconfig
index 8f76b00744e7453ddde4ac19c1ce9a4db377e0b2..47238208c527e8a6ab0e7f18a86dfb9a8ab79716 100644
--- a/efi/payload/Kconfig
+++ b/efi/payload/Kconfig
@@ -1,7 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
config EFI_HANDOVER_PROTOCOL
+ bool "EFI Handover protocol"
def_bool X86
config EFI_PAYLOAD_BOOTM
- def_bool !EFI_HANDOVER_PROTOCOL
+ bool "EFI bootm protocol"
+ depends on !EFI_HANDOVER_PROTOCOL
+ select BOOTM_FITIMAGE
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 11/15] malloc: tlsf: efi: add a fallback for allocate more memory when we are in efi.
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (9 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 10/15] efi: payload: x86: enable the possibility to efi stub bootm for x86 Chali Anis
@ 2025-09-20 3:03 ` Chali Anis
2025-09-20 3:03 ` [PATCH 12/15] configs: efi: arm64: x86: enable the use of efi malloc fallback Chali Anis
` (4 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chali Anis @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis
this will fix the OOM issues for when barebox is running on top of efi.
the OOM were unpredictble since we can't determine the size required in
advance for initrd or kernel. with this patch we don't need anymore to
increase memory in efi early mem, we allocate only what barebox needs
to relocate itself and have what it needs to manage peripherls, at any
OOM we fallback to efi to give us more memory. So we get a more
deterministic behaviour and more generic efi payload and finally
a huge speedup for the boot time. and the most important a clean code.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
common/Kconfig | 9 ++++++
common/Makefile | 1 +
common/efi_malloc.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++
common/tlsf_malloc.c | 22 +++++++++++++--
include/malloc.h | 19 +++++++++++++
5 files changed, 129 insertions(+), 2 deletions(-)
diff --git a/common/Kconfig b/common/Kconfig
index eb2fb1da1e0919b6e7d5e868c48ad2e195cd8aa8..5e2251ff7821f14556b19816a51eb8d7e9133a6f 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -317,6 +317,15 @@ config EXPERIMENTAL
bool
prompt "Prompt for experimental code"
+config MALLOC_EFI
+ bool "efi malloc fallback"
+ depends on EFI_PAYLOAD
+ help
+ select this option to use efi malloc fallback, it will permit,
+ when we use barebox as an efi payload to automaticlly allocate
+ more memory from efi as needed, permits to be more resilient with
+ OOM and support what ever we have to boot or execute as efi app.
+
choice
prompt "malloc implementation"
default MALLOC_TLSF
diff --git a/common/Makefile b/common/Makefile
index d501a6a2755a113fac3ac632806d4a92b741d6e2..aa693b4c31b66aecb76192579466972fb8c351b3 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_MALLOC_TLSF) += tlsf_malloc.o tlsf.o calloc.o
KASAN_SANITIZE_tlsf.o := n
obj-$(CONFIG_MALLOC_DUMMY) += dummy_malloc.o calloc.o
+obj-$(CONFIG_MALLOC_EFI) += efi_malloc.o
obj-y += malloc.o
obj-$(CONFIG_MEMINFO) += meminfo.o
obj-$(CONFIG_MENU) += menu.o
diff --git a/common/efi_malloc.c b/common/efi_malloc.c
new file mode 100644
index 0000000000000000000000000000000000000000..fcd97794f2d6e08d41acd9f2a4d4fc0252b6caf2
--- /dev/null
+++ b/common/efi_malloc.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 Sascha Hauer <s.hauer@pengutronix.de>
+ */
+#include <linux/sizes.h>
+#include <common.h>
+#include <malloc.h>
+#include <efi.h>
+#include <efi/efi-util.h>
+#include <string.h>
+#include <errno.h>
+
+struct alloc_header {
+ size_t size; /* requested size */
+};
+
+void *efi_malloc(size_t size)
+{
+ efi_status_t efiret;
+ efi_physical_addr_t mem;
+ struct alloc_header *hdr;
+ size_t pages;
+
+ if (!size)
+ return ZERO_SIZE_PTR;
+
+ pages = DIV_ROUND_UP(size, EFI_PAGE_SIZE);
+ efiret = BS->allocate_pages(EFI_ALLOCATE_ANY_PAGES, EFI_LOADER_DATA,
+ pages, &mem);
+ if (EFI_ERROR(efiret)) {
+ errno = efi_errno(efiret);
+ return NULL;
+ }
+
+ hdr = (struct alloc_header *)efi_phys_to_virt(mem);
+ hdr->size = size;
+ return (void *)(hdr + 1);
+}
+
+void efi_free(void *ptr)
+{
+ efi_physical_addr_t phys;
+ struct alloc_header *hdr;
+
+ if (!ptr)
+ return;
+
+ hdr = (struct alloc_header *)ptr - 1;
+ phys = efi_virt_to_phys(hdr);
+ BS->free_pages(phys, DIV_ROUND_UP(hdr->size, EFI_PAGE_SIZE));
+}
+
+void *efi_realloc(void *ptr, size_t size)
+{
+ struct alloc_header *hdr;
+ void *n_mem;
+ size_t old_sz;
+
+ if (!ptr)
+ return efi_malloc(size);
+
+ if (!size) {
+ efi_free(ptr);
+ return NULL;
+ }
+
+ hdr = (struct alloc_header *)ptr - 1;
+ old_sz = hdr->size;
+
+ n_mem = efi_malloc(size);
+ if (!n_mem) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ memcpy(n_mem, ptr, (old_sz < size) ? old_sz : size);
+ efi_free(ptr);
+
+ return n_mem;
+}
diff --git a/common/tlsf_malloc.c b/common/tlsf_malloc.c
index 6e9d48af26bbf05573fda04f616412c895342593..25ae40e455528a318fc150dba4ea7bc2ce27f3e3 100644
--- a/common/tlsf_malloc.c
+++ b/common/tlsf_malloc.c
@@ -6,6 +6,8 @@
*/
#include <malloc.h>
+#include <efi.h>
+#include <memory.h>
#include <string.h>
#include <stdio.h>
@@ -29,8 +31,12 @@ void *malloc(size_t bytes)
void *mem;
mem = tlsf_malloc(tlsf_mem_pool, bytes);
- if (!mem)
+ if (!mem) {
+ if (IS_ENABLED(CONFIG_MALLOC_EFI))
+ return efi_malloc(bytes);
+
errno = ENOMEM;
+ }
return mem;
}
@@ -38,6 +44,14 @@ EXPORT_SYMBOL(malloc);
void free(void *mem)
{
+ if (IS_ENABLED(CONFIG_MALLOC_EFI)) {
+ if (efi_virt_to_phys(mem) < mem_malloc_start() &&
+ efi_virt_to_phys(mem) > mem_malloc_end()) {
+ efi_free(mem);
+ return;
+ }
+ }
+
tlsf_free(tlsf_mem_pool, mem);
}
EXPORT_SYMBOL(free);
@@ -51,8 +65,12 @@ EXPORT_SYMBOL(malloc_usable_size);
void *realloc(void *oldmem, size_t bytes)
{
void *mem = tlsf_realloc(tlsf_mem_pool, oldmem, bytes);
- if (!mem)
+ if (!mem) {
+ if (IS_ENABLED(CONFIG_MALLOC_EFI))
+ return efi_realloc(oldmem, bytes);
+
errno = ENOMEM;
+ }
return mem;
}
diff --git a/include/malloc.h b/include/malloc.h
index 35551250324ee1d3c8ddc06f49a06ce07d2855bd..2294d129838829955ffc08c5ecb9df91d05073c9 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -24,6 +24,25 @@
#ifdef CONFIG_MALLOC_TLSF
void *malloc_add_pool(void *mem, size_t bytes);
#endif
+void *efi_malloc(size_t size);
+void efi_free(void *ptr);
+void *efi_realloc(void *ptr, size_t size);
+#ifdef MALLOC_EFI
+static inline void *efi_malloc(size_t size)
+{
+ errno = -ENOMEM;
+ return NULL;
+}
+
+static inline void efi_free(void *ptr) {}
+
+static inline void *efi_realloc(void *ptr, size_t size)
+{
+ errno = -ENOMEM;
+ return NULL;
+}
+#else
+#endif
#if IN_PROPER
void *malloc(size_t) __alloc_size(1);
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 12/15] configs: efi: arm64: x86: enable the use of efi malloc fallback.
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (10 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 11/15] malloc: tlsf: efi: add a fallback for allocate more memory when we are in efi Chali Anis
@ 2025-09-20 3:03 ` Chali Anis
2025-09-20 3:03 ` [PATCH 13/15] efi: payload: earlymem: allocate only the barebox needs in term of memory Chali Anis
` (3 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chali Anis @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis
Use the efi malloc fallback on all efi based systems.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
arch/arm/configs/efi_v8_defconfig | 1 +
arch/x86/configs/efi_defconfig | 1 +
efi/payload/Kconfig | 5 +++--
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/arm/configs/efi_v8_defconfig b/arch/arm/configs/efi_v8_defconfig
index 607ab44e473f6ad910c1944f2828b6255e5ade10..3afcdd6ed7f5cc711f2a1f7cbe1a6e84de902817 100644
--- a/arch/arm/configs/efi_v8_defconfig
+++ b/arch/arm/configs/efi_v8_defconfig
@@ -263,4 +263,5 @@ CONFIG_FS_RATP=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_DIGEST_SHA1_ARM64_CE=y
CONFIG_DIGEST_SHA256_ARM64_CE=y
+CONFIG_MALLOC_EFI=y
# CONFIG_MISSING_FIRMWARE_ERROR is not set
diff --git a/arch/x86/configs/efi_defconfig b/arch/x86/configs/efi_defconfig
index 1dd823af40ea6c27a6b4409edb4f3bea2bf896f0..884a6de0d41a20e47497ce170404150fbf787382 100644
--- a/arch/x86/configs/efi_defconfig
+++ b/arch/x86/configs/efi_defconfig
@@ -97,3 +97,4 @@ CONFIG_FS_EFIVARFS=y
CONFIG_FS_FAT=y
CONFIG_FS_FAT_WRITE=y
CONFIG_FS_FAT_LFN=y
+CONFIG_MALLOC_EFI=y
diff --git a/efi/payload/Kconfig b/efi/payload/Kconfig
index 47238208c527e8a6ab0e7f18a86dfb9a8ab79716..b1e4c373a17776a40f218ebc104fa7e23ec1c57a 100644
--- a/efi/payload/Kconfig
+++ b/efi/payload/Kconfig
@@ -2,9 +2,10 @@
config EFI_HANDOVER_PROTOCOL
bool "EFI Handover protocol"
- def_bool X86
+ def_bool !EFI_PAYLOAD_BOOTM
config EFI_PAYLOAD_BOOTM
bool "EFI bootm protocol"
- depends on !EFI_HANDOVER_PROTOCOL
+ def_bool EFI_PAYLOAD
select BOOTM_FITIMAGE
+ select MALLOC_EFI
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 13/15] efi: payload: earlymem: allocate only the barebox needs in term of memory.
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (11 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 12/15] configs: efi: arm64: x86: enable the use of efi malloc fallback Chali Anis
@ 2025-09-20 3:03 ` Chali Anis
2025-09-20 3:03 ` [PATCH 14/15] ARM: cpu: allow selecting CPU_V7/CPU_V8 directly chalianis1
` (2 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Chali Anis @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis
Since an EFI malloc callback is available to provide additional memory
on demand, limit early allocations to what barebox strictly requires.
This ensures more deterministic behavior and reduces the risk of OOM
conditions.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
efi/payload/early-mem.c | 18 ++++--------------
efi/payload/entry-multi.c | 5 ++---
efi/payload/entry-single.c | 5 ++---
include/efi/efi-payload.h | 2 +-
4 files changed, 9 insertions(+), 21 deletions(-)
diff --git a/efi/payload/early-mem.c b/efi/payload/early-mem.c
index 150a2a595afcdb69026f98c53f9a3bf3425da999..c5e94b33a756f3b8612eb261de27b99b46b0abba 100644
--- a/efi/payload/early-mem.c
+++ b/efi/payload/early-mem.c
@@ -6,27 +6,17 @@
#include <efi/efi-payload.h>
void *efi_earlymem_alloc(const struct efi_system_table *sys_table,
- size_t *memsize, enum efi_memory_type mem_type)
+ size_t memsize, enum efi_memory_type mem_type)
{
struct efi_boot_services *bs = sys_table->boottime;
efi_physical_addr_t mem;
efi_status_t efiret;
- size_t m_sz;
- if (IS_ENABLED(CONFIG_X86))
- m_sz = SZ_512M;
- else
- m_sz = SZ_256M;
-
- for (*memsize = m_sz; *memsize >= SZ_8M; *memsize /= 2) {
- efiret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES, mem_type,
- *memsize / EFI_PAGE_SIZE, &mem);
- if (!EFI_ERROR(efiret) || efiret != EFI_OUT_OF_RESOURCES)
- break;
- }
+ efiret = bs->allocate_pages(EFI_ALLOCATE_ANY_PAGES, mem_type,
+ memsize / EFI_PAGE_SIZE, &mem);
if (EFI_ERROR(efiret))
panic("failed to allocate %zu byte memory pool: 0x%lx\n",
- *memsize, efiret);
+ memsize, efiret);
return efi_phys_to_virt(mem);
}
diff --git a/efi/payload/entry-multi.c b/efi/payload/entry-multi.c
index d5d54cdf70a141428edf35a5fcde45ff7b59a61e..82f3dfffe8709f9a4275c7f9ec246be979e605cd 100644
--- a/efi/payload/entry-multi.c
+++ b/efi/payload/entry-multi.c
@@ -23,7 +23,6 @@ static void efi_putc(void *ctx, int ch)
void __efistub_efi_pe_entry(void *image, struct efi_system_table *sys_table)
{
- size_t memsize;
void *mem;
static struct barebox_efi_data efidata;
@@ -37,7 +36,7 @@ void __efistub_efi_pe_entry(void *image, struct efi_system_table *sys_table)
handoff_data_add(HANDOFF_DATA_EFI, &efidata, sizeof(efidata));
- mem = efi_earlymem_alloc(sys_table, &memsize, EFI_LOADER_CODE);
+ mem = efi_earlymem_alloc(sys_table, SZ_16M, EFI_BOOT_SERVICES_CODE);
- barebox_pbl_entry((uintptr_t)mem, memsize, NULL);
+ barebox_pbl_entry((uintptr_t)mem, SZ_16M, NULL);
}
diff --git a/efi/payload/entry-single.c b/efi/payload/entry-single.c
index 8600bd845c49719da3ad62c5f5bf8d0b547aed74..f481d0942ba5dc96b2f97079c4e7575fc986e538 100644
--- a/efi/payload/entry-single.c
+++ b/efi/payload/entry-single.c
@@ -17,7 +17,6 @@
void efi_main(efi_handle_t image, struct efi_system_table *sys_table)
{
efi_status_t efiret;
- size_t memsize;
void *mem;
#ifdef DEBUG
@@ -37,9 +36,9 @@ void efi_main(efi_handle_t image, struct efi_system_table *sys_table)
BS->handle_protocol(efi_loaded_image->device_handle,
&efi_device_path_protocol_guid, (void **)&efi_device_path);
- mem = efi_earlymem_alloc(sys_table, &memsize, EFI_LOADER_DATA);
+ mem = efi_earlymem_alloc(sys_table, SZ_16M, EFI_BOOT_SERVICES_DATA);
- mem_malloc_init(mem, mem + memsize - 1);
+ mem_malloc_init(mem, mem + SZ_16M - 1);
start_barebox();
}
diff --git a/include/efi/efi-payload.h b/include/efi/efi-payload.h
index d8e66a187a870fcae9288d9c65984896e5196c31..337471117d5acecccfe8526ef470bb84429d31aa 100644
--- a/include/efi/efi-payload.h
+++ b/include/efi/efi-payload.h
@@ -32,7 +32,7 @@ int efi_set_variable(char *name, efi_guid_t *vendor, uint32_t attributes,
int efi_set_variable_usec(char *name, efi_guid_t *vendor, uint64_t usec);
void *efi_earlymem_alloc(const struct efi_system_table *sys_table,
- size_t *memsize, enum efi_memory_type mem_type);
+ size_t memsize, enum efi_memory_type mem_type);
int efi_initrd_register(void *initrd, size_t initrd_size);
void efi_initrd_unregister(void);
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 14/15] ARM: cpu: allow selecting CPU_V7/CPU_V8 directly
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (12 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 13/15] efi: payload: earlymem: allocate only the barebox needs in term of memory Chali Anis
@ 2025-09-20 3:03 ` chalianis1
2025-09-20 3:03 ` [PATCH 15/15] efi: payload: bootm: remove redundant reallocations in image loader Chali Anis
2025-09-22 7:37 ` [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels Ahmad Fatoum
15 siblings, 0 replies; 17+ messages in thread
From: chalianis1 @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis, Ahmad Fatoum
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
We currently lack a way to build a barebox EFI payload on ARM without
enabling some other subarchitecture. As CONFIG_EFI_PAYLOAD has a global
effect and adds EFI stubs to all enabled board, an EFI subarchitecture
doesn't fit into our current model.
Instead, let's make it possible to enable either CONFIG_CPU_V8 or
CONFIG_CPU_V7 directly.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Link: https://lore.barebox.org/20250904081626.93182-1-a.fatoum@pengutronix.de
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
arch/arm/cpu/Kconfig | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/Kconfig b/arch/arm/cpu/Kconfig
index e61bcadc8c355406867bf52d9f704bcca80d1ca3..fe0d1e470578c41f7d0c37b8aeac0c04f1bf2580 100644
--- a/arch/arm/cpu/Kconfig
+++ b/arch/arm/cpu/Kconfig
@@ -79,12 +79,15 @@ config CPU_V6
# ARMv7
config CPU_V7
- bool
+ bool "Generic ARMv7 support"
+ depends on 32BIT
select CPU_32v7
# ARMv8
config CPU_V8
- bool
+ bool "Generic ARMv8 support"
+ default y
+ depends on 64BIT
select CPU_64v8
select ARM_EXCEPTIONS
select GENERIC_FIND_NEXT_BIT
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 15/15] efi: payload: bootm: remove redundant reallocations in image loader
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (13 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 14/15] ARM: cpu: allow selecting CPU_V7/CPU_V8 directly chalianis1
@ 2025-09-20 3:03 ` Chali Anis
2025-09-22 7:37 ` [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels Ahmad Fatoum
15 siblings, 0 replies; 17+ messages in thread
From: Chali Anis @ 2025-09-20 3:03 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX; +Cc: Chali Anis
The EFI payload loader used to copy OS images, initrds and FDTs into
freshly allocated EFI pages before handing them to LoadImage() or
installing configuration tables. This resulted in unnecessary memory
moves, extra allocations and longer boot times.
Rework the loader to:
- pass buffers from read_file() or FIT images directly to
BS->load_image() without intermediate memcpy
- drop efi_allocate_pages()/efi_free_pages() wrappers where not needed
- avoid duplicate allocations for initrd and FDT data
- free only the original buffer after execution/unload
This eliminates redundant reallocations, simplifies the code, and
reduces boot overhead. Boot flow is now more deterministic with fewer
allocation failures possible on memory-constrained systems.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
efi/payload/bootm.c | 344 +++++++++++++++++++++-------------------------------
1 file changed, 136 insertions(+), 208 deletions(-)
diff --git a/efi/payload/bootm.c b/efi/payload/bootm.c
index 401aefe28188bb4335f73a8e259a16c605096626..6dabce60845e85965147d5492b2b12091469726a 100644
--- a/efi/payload/bootm.c
+++ b/efi/payload/bootm.c
@@ -37,51 +37,10 @@ struct efi_mem_resource {
size_t size;
} __attribute__ ((packed));
-struct efi_image_data {
- struct image_data *data;
-
- efi_handle_t handle;
- struct efi_loaded_image *loaded_image;
-
- struct efi_mem_resource image_res;
- struct efi_mem_resource oftree_res;
- struct efi_mem_resource *initrd_res;
-};
-
-
-static void *efi_allocate_pages(efi_physical_addr_t *mem,
- size_t size,
- enum efi_allocate_type allocate_type,
- enum efi_memory_type mem_type)
-{
- efi_status_t efiret;
-
- efiret = BS->allocate_pages(allocate_type, mem_type,
- DIV_ROUND_UP(size, EFI_PAGE_SIZE), mem);
- if (EFI_ERROR(efiret)) {
- errno = efi_errno(efiret);
- return NULL;
- }
-
- return efi_phys_to_virt(*mem);
-}
-
-static void efi_free_pages(void *_mem, size_t size)
-{
- efi_physical_addr_t mem = efi_virt_to_phys(_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_file_image(const char *file,
- struct efi_loaded_image **loaded_image,
- efi_handle_t *h)
+static void *efi_load_file_image(const char *file,
+ struct efi_loaded_image **loaded_image,
+ efi_handle_t *h)
{
- efi_physical_addr_t mem;
- void *exe;
char *buf;
size_t size;
efi_handle_t handle;
@@ -90,19 +49,9 @@ static int efi_load_file_image(const char *file,
buf = read_file(file, &size);
if (!buf)
- return -ENOMEM;
-
- exe = efi_allocate_pages(&mem, size, EFI_ALLOCATE_ANY_PAGES,
- EFI_LOADER_CODE);
- if (!exe) {
- pr_err("Failed to allocate pages for image\n");
- ret = -ENOMEM;
- goto free_buf;
- }
-
- memcpy(exe, buf, size);
+ return ERR_PTR(-ENOMEM);
- efiret = BS->load_image(false, efi_parent_image, efi_device_path, exe,
+ efiret = BS->load_image(false, efi_parent_image, efi_device_path, buf,
size, &handle);
if (EFI_ERROR(efiret)) {
ret = -efi_errno(efiret);
@@ -121,16 +70,12 @@ static int efi_load_file_image(const char *file,
}
*h = handle;
- free(buf);
- return 0;
+ return buf;
free_mem:
- efi_free_pages(exe, size);
-free_buf:
free(buf);
-
- return ret;
+ return ERR_PTR(ret);
}
static bool ramdisk_is_fit(struct image_data *data)
@@ -165,44 +110,31 @@ static bool fdt_is_fit(struct image_data *data)
data->fit_config, "fdt") > 0 : false;
}
-static int efi_load_os(struct efi_image_data *e)
+static void *efi_load_os(struct image_data *data,
+ struct efi_loaded_image **loaded_image,
+ efi_handle_t *handle)
{
efi_status_t efiret = EFI_SUCCESS;
- efi_physical_addr_t mem;
- size_t image_size = 0;
- void *image = NULL;
- void *vmem = NULL;
+ efi_handle_t h;
int ret = 0;
- if (!e->data->os_fit)
- return efi_load_file_image(e->data->os_file,
- &e->loaded_image, &e->handle);
-
- image = (void *)e->data->fit_kernel;
- image_size = e->data->fit_kernel_size;
+ if (!data->os_fit)
+ return efi_load_file_image(data->os_file,
+ loaded_image, handle);
- if (image_size <= 0 || !image)
- return -EINVAL;
+ if (data->fit_kernel_size <= 0 || !data->fit_kernel)
+ return ERR_PTR(-EINVAL);
- vmem = efi_allocate_pages(&mem, image_size, EFI_ALLOCATE_ANY_PAGES,
- EFI_LOADER_CODE);
- if (!vmem) {
- pr_err("Failed to allocate pages for image\n");
- return -ENOMEM;
- }
-
- memcpy(vmem, image, image_size);
-
- efiret = BS->load_image(false, efi_parent_image, efi_device_path, image,
- image_size, &e->handle);
+ efiret = BS->load_image(false, efi_parent_image, efi_device_path,
+ (void *)data->fit_kernel, data->fit_kernel_size, &h);
if (EFI_ERROR(efiret)) {
ret = -efi_errno(efiret);
pr_err("failed to LoadImage: %s\n", efi_strerror(efiret));
goto out_mem;
};
- efiret = BS->open_protocol(e->handle, &efi_loaded_image_protocol_guid,
- (void **)&e->loaded_image, efi_parent_image,
+ efiret = BS->open_protocol(h, &efi_loaded_image_protocol_guid,
+ (void **)loaded_image, efi_parent_image,
NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(efiret)) {
ret = -efi_errno(efiret);
@@ -210,172 +142,156 @@ static int efi_load_os(struct efi_image_data *e)
goto out_unload;
}
- e->image_res.base = mem;
- e->image_res.size = image_size;
+ *handle = h;
- return 0;
+ return (void *)data->fit_kernel;
-out_mem:
- efi_free_pages(vmem, image_size);
out_unload:
- BS->unload_image(e->handle);
- return ret;
+ BS->unload_image(h);
+out_mem:
+ return ERR_PTR(ret);
}
-static void efi_unload_os(struct efi_image_data *e)
+static void efi_unload_os(struct image_data *data,
+ void *image, efi_handle_t handle)
{
- BS->close_protocol(e->handle, &efi_loaded_image_protocol_guid,
+ BS->close_protocol(handle, &efi_loaded_image_protocol_guid,
efi_parent_image, NULL);
- BS->unload_image(e->handle);
- efi_free_pages(efi_phys_to_virt(e->image_res.base),
- e->image_res.size);
+ BS->unload_image(handle);
+
+ free(image);
}
-static int efi_load_ramdisk(struct efi_image_data *e)
+static int efi_load_ramdisk(struct image_data *data,
+ struct efi_mem_resource **initrd_res)
{
- void *vmem, *tmp = NULL;
- efi_physical_addr_t mem;
+ struct efi_mem_resource *res;
efi_status_t efiret = EFI_SUCCESS;
- const void *initrd;
unsigned long initrd_size;
+ void *initrd;
int ret;
- if (ramdisk_is_fit(e->data)) {
- ret = fit_open_image(e->data->os_fit, e->data->fit_config,
- "ramdisk", &initrd, &initrd_size);
+ if (ramdisk_is_fit(data)) {
+ ret = fit_open_image(data->os_fit, data->fit_config,
+ "ramdisk", (const void **)&initrd, &initrd_size);
if (ret) {
- pr_err("Cannot open ramdisk image in FIT image: %pe\n",
- ERR_PTR(ret));
+ pr_err("Cannot open ramdisk image in FIT image: %s\n",
+ strerror(ret));
return ret;
}
} else {
- if (!e->data->initrd_file)
+ if (!data->initrd_file)
return 0;
- pr_info("Loading ramdisk from '%s'\n", e->data->initrd_file);
- tmp = read_file(e->data->initrd_file, &initrd_size);
- if (!tmp || initrd_size <= 0) {
+ pr_info("Loading ramdisk from '%s'\n", data->initrd_file);
+ initrd = read_file(data->initrd_file, &initrd_size);
+ if (!initrd || initrd_size <= 0) {
pr_err("Failed to read initrd from file: %s\n",
- e->data->initrd_file);
+ data->initrd_file);
return -EINVAL;
}
- initrd = tmp;
}
efiret = BS->allocate_pool(EFI_LOADER_DATA,
sizeof(struct efi_mem_resource),
- (void **)&e->initrd_res);
- if (EFI_ERROR(efiret) || !e->initrd_res) {
+ (void **)&res);
+ if (EFI_ERROR(efiret) || !res) {
ret = -efi_errno(efiret);
pr_err("Failed to allocate initrd %s/n", efi_strerror(efiret));
goto free_mem;
}
- vmem = efi_allocate_pages(&mem, initrd_size,
- EFI_ALLOCATE_ANY_PAGES, EFI_LOADER_DATA);
- if (!vmem) {
- pr_err("Failed to allocate pages for initrd data: %s\n", strerror(errno));
- ret = -ENOMEM;
- goto free_pool;
- }
-
- memcpy(vmem, (void *)initrd, initrd_size);
- e->initrd_res->base = (uint64_t)mem;
- e->initrd_res->size = (uint64_t)initrd_size;
+ res->base = (uint64_t)efi_virt_to_phys(initrd);
+ res->size = (uint64_t)initrd_size;
if (IS_ENABLED(CONFIG_EFI_INITRD_INSTALL)) {
efiret = BS->install_configuration_table(
&efi_linux_initrd_media_guid,
- (void *)e->initrd_res);
+ (void *)res);
if (EFI_ERROR(efiret)) {
ret = -efi_errno(efiret);
pr_err("Failed to install INITRD %s/n",
efi_strerror(efiret));
- goto free_pages;
+ goto free_pool;
}
} else {
- ret = efi_initrd_register(vmem, initrd_size);
+ ret = efi_initrd_register(initrd, initrd_size);
if (ret) {
pr_err("Failed to register INITRD %s/n",
strerror(efiret));
- goto free_pages;
+ goto free_pool;
}
}
- free(tmp);
-
+ *initrd_res = res;
return 0;
-free_pages:
- efi_free_pages(vmem, initrd_size);
free_pool:
- BS->free_pool(e->initrd_res);
+ BS->free_pool(res);
free_mem:
- free(tmp);
+ free(initrd);
return ret;
}
-static void efi_unload_ramdisk(struct efi_image_data *e)
+static void efi_unload_ramdisk(struct image_data *data,
+ struct efi_mem_resource *initrd_res)
{
+ if (!initrd_res)
+ return;
+
if (IS_ENABLED(CONFIG_EFI_INITRD_INSTALL))
BS->install_configuration_table(
&efi_linux_initrd_media_guid, NULL);
else
efi_initrd_unregister();
- efi_free_pages(efi_phys_to_virt(e->initrd_res->base),
- e->initrd_res->size);
-
- BS->free_pool(e->initrd_res);
- e->initrd_res = NULL;
+ free(efi_phys_to_virt(initrd_res->base));
+ BS->free_pool(initrd_res);
+ initrd_res = NULL;
}
-static int efi_load_fdt(struct efi_image_data *e)
+static int efi_load_fdt(struct image_data *data, void **fdt)
{
- efi_status_t efiret = EFI_SUCCESS;
efi_physical_addr_t mem;
- void *vmem, *tmp = NULL;
- const void *of_tree;
+ efi_status_t efiret = EFI_SUCCESS;
+ void *of_tree, *vmem;
unsigned long of_size;
int ret;
- if (IS_ENABLED(CONFIG_EFI_FDT_FORCE))
- return 0;
-
- if (fdt_is_fit(e->data)) {
- ret = fit_open_image(e->data->os_fit, e->data->fit_config,
- "fdt", &of_tree, &of_size);
+ if (fdt_is_fit(data)) {
+ ret = fit_open_image(data->os_fit, data->fit_config,
+ "fdt", (const void **)&of_tree, &of_size);
if (ret) {
- pr_err("Cannot open FDT image in FIT image: %pe\n",
- ERR_PTR(ret));
+ pr_err("Cannot open FDT image in FIT image: %s\n",
+ strerror(ret));
return ret;
}
} else {
- if (!e->data->oftree_file)
+ if (!data->oftree_file)
return 0;
- pr_info("Loading devicetree from '%s'\n", e->data->oftree_file);
- tmp = read_file(e->data->oftree_file, &of_size);
- if (!tmp || of_size <= 0) {
+ pr_info("Loading devicetree from '%s'\n", data->oftree_file);
+ of_tree = read_file(data->oftree_file, &of_size);
+ if (!of_tree || of_size <= 0) {
pr_err("Failed to read initrd from file: %s\n",
- e->data->initrd_file);
+ data->initrd_file);
return -EINVAL;
}
- of_tree = tmp;
}
- vmem = efi_allocate_pages(&mem, SZ_128K,
- EFI_ALLOCATE_ANY_PAGES,
- EFI_ACPI_RECLAIM_MEMORY);
- if (!vmem) {
+ efiret = BS->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_ACPI_RECLAIM_MEMORY,
+ DIV_ROUND_UP(SZ_2M, EFI_PAGE_SIZE), &mem);
+ if (EFI_ERROR(efiret)) {
+ ret = -efi_errno(efiret);
pr_err("Failed to allocate pages for FDT\n");
- ret = -ENOMEM;
- goto free_file;
+ goto free_mem;
}
+ vmem = efi_phys_to_virt(mem);
memcpy(vmem, of_tree, of_size);
efiret = BS->install_configuration_table(&efi_fdt_guid,
@@ -383,83 +299,87 @@ static int efi_load_fdt(struct efi_image_data *e)
if (EFI_ERROR(efiret)) {
pr_err("Failed to install FDT %s/n", efi_strerror(efiret));
ret = -efi_errno(efiret);
- goto free_mem;
+ goto free_efi_mem;
}
- e->oftree_res.base = mem;
- e->oftree_res.size = SZ_128K;
-
- free(tmp);
-
+ *fdt = vmem;
return 0;
+free_efi_mem:
+ BS->free_pages(mem, DIV_ROUND_UP(SZ_2M, EFI_PAGE_SIZE));
free_mem:
- efi_free_pages(vmem, SZ_128K);
-free_file:
- free(tmp);
-
+ free(of_tree);
return ret;
}
-static void efi_unload_fdt(struct efi_image_data *e)
+static void efi_unload_fdt(void *fdt)
{
- if (IS_ENABLED(CONFIG_EFI_FDT_FORCE))
+ if (IS_ENABLED(CONFIG_EFI_FDT_FORCE) || !fdt)
return;
BS->install_configuration_table(&efi_fdt_guid, NULL);
-
- efi_free_pages(efi_phys_to_virt(e->oftree_res.base),
- e->oftree_res.size);
+ BS->free_pages(efi_virt_to_phys(fdt), SZ_2M);
}
static int do_bootm_efi_stub(struct image_data *data)
{
- struct efi_image_data e = { .data = data };
+ struct efi_mem_resource *initrd_res = NULL;
+ struct efi_loaded_image *loaded_image;
+ void *fdt = NULL, *image = NULL;
+ efi_handle_t handle;
enum filetype type;
int ret = 0;
- ret = efi_load_os(&e);
- if (ret)
- return ret;
+ image = efi_load_os(data, &loaded_image, &handle);
+ if (IS_ERR_OR_NULL(image))
+ return PTR_ERR(image);
- ret = efi_load_fdt(&e);
+ ret = efi_load_fdt(data, &fdt);
if (ret)
goto unload_os;
- ret = efi_load_ramdisk(&e);
+ ret = efi_load_ramdisk(data, &initrd_res);
if (ret)
goto unload_oftree;
- type = file_detect_type(e.loaded_image->image_base, PAGE_SIZE);
- ret = efi_execute_image(e.handle, e.loaded_image, type);
+ type = file_detect_type(loaded_image->image_base, PAGE_SIZE);
+ ret = efi_execute_image(handle, loaded_image, type);
if (ret)
goto unload_ramdisk;
return 0;
unload_ramdisk:
- if (e.initrd_res)
- efi_unload_ramdisk(&e);
+ efi_unload_ramdisk(data, initrd_res);
unload_oftree:
- efi_unload_fdt(&e);
+ efi_unload_fdt(fdt);
unload_os:
- efi_unload_os(&e);
+ efi_unload_os(data, image, handle);
return ret;
}
static int efi_app_execute(struct image_data *data)
{
- int ret;
- struct efi_image_data e = { .data = data };
+ struct efi_loaded_image *loaded_image;
+ efi_handle_t handle;
+ void *image;
enum filetype type;
+ int ret;
- ret = efi_load_file_image(data->os_file, &e.loaded_image, &e.handle);
+ image = efi_load_file_image(data->os_file, &loaded_image, &handle);
+ if (IS_ERR_OR_NULL(image))
+ return PTR_ERR(image);
+
+ type = file_detect_type(loaded_image->image_base, PAGE_SIZE);
+
+ ret = efi_execute_image(handle, loaded_image, type);
if (ret)
- return ret;
+ pr_err("EFI Application failed with error: %s\n",
+ strerror(ret));
- type = file_detect_type(e.loaded_image->image_base, PAGE_SIZE);
+ free(image);
- return efi_execute_image(e.handle, e.loaded_image, type);
+ return ret;
}
static struct image_handler efi_app_handle_tr = {
@@ -482,15 +402,23 @@ static struct image_handler efi_arm64_handle_tr = {
static int efi_execute(struct binfmt_hook *b, char *file, int argc, char **argv)
{
- int ret;
- efi_handle_t handle;
struct efi_loaded_image *loaded_image;
+ efi_handle_t handle;
+ void *image;
+ int ret;
+
+ image = efi_load_file_image(file, &loaded_image, &handle);
+ if (IS_ERR_OR_NULL(image))
+ return PTR_ERR(image);
- ret = efi_load_file_image(file, &loaded_image, &handle);
+ ret = efi_execute_image(handle, loaded_image, b->type);
if (ret)
- return ret;
+ pr_err("EFI Application failed with error: %s\n",
+ strerror(ret));
- return efi_execute_image(handle, loaded_image, b->type);
+ free(image);
+
+ return ret;
}
static struct binfmt_hook binfmt_efi_hook = {
@@ -532,13 +460,13 @@ static int efi_register_image_handler(void)
{
register_image_handler(&efi_app_handle_tr);
binfmt_register(&binfmt_efi_hook);
-
+
if (IS_ENABLED(CONFIG_X86)) {
register_image_handler(&non_efi_handle_linux_x86);
register_image_handler(&efi_x86_linux_handle_tr);
binfmt_register(&binfmt_x86_efi_hook);
}
-
+
if (IS_ENABLED(CONFIG_ARM64)) {
register_image_handler(&efi_arm64_handle_tr);
binfmt_register(&binfmt_arm64_efi_hook);
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels.
2025-09-20 3:03 [PATCH 00/15] Implement efi loader to run barebox as efi payload app and then load efi stubed application/kernels chalianis1
` (14 preceding siblings ...)
2025-09-20 3:03 ` [PATCH 15/15] efi: payload: bootm: remove redundant reallocations in image loader Chali Anis
@ 2025-09-22 7:37 ` Ahmad Fatoum
15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-09-22 7:37 UTC (permalink / raw)
To: chalianis1, Sascha Hauer, BAREBOX; +Cc: Ahmad Fatoum
On 20.09.25 05:03, chalianis1@gmail.com wrote:
> Signed-off-by: Chali Anis <chalianis1@gmail.com>
There's still some refactoring needed to avoid intermittent changes
that are removed/reworked in the same series.
I am collaborating on it with Anis and a revised series will follow
for wider review.
Cheers,
Ahmad
> ---
> Ahmad Fatoum (5):
> efi: payload: split image handling from legacy handover boot support
> efi: payload: add support for efi stub boot
> efi: payload: add support for fit image
> efi: payload: make selectable without COMPILE_TEST
> ARM: cpu: allow selecting CPU_V7/CPU_V8 directly
>
> Chali Anis (10):
> arm: efi: add a generic defconfig for v8 efi payload,
> efi: payload: initrd: implement efi initrd media protocol.
> common: filetype: add x86 linux filetype.
> efi: payload: early-mem: helps to correctly boot x86 linux.
> efi: payload: bootm: add x86 efi stub boot support.
> efi: payload: x86: enable the possibility to efi stub bootm for x86.
> malloc: tlsf: efi: add a fallback for allocate more memory when we are in efi.
> configs: efi: arm64: x86: enable the use of efi malloc fallback.
> efi: payload: earlymem: allocate only the barebox needs in term of memory.
> efi: payload: bootm: remove redundant reallocations in image loader
>
> arch/arm/configs/efi_v8_defconfig | 267 +++++++++++++++++++++
> arch/arm/cpu/Kconfig | 7 +-
> arch/x86/configs/efi_defconfig | 1 +
> common/Kconfig | 9 +
> common/Makefile | 1 +
> common/efi_malloc.c | 80 +++++++
> common/filetype.c | 4 +
> common/tlsf_malloc.c | 22 +-
> efi/Kconfig | 23 +-
> efi/guid.c | 7 +
> efi/payload/Kconfig | 11 +
> efi/payload/Makefile | 3 +
> efi/payload/bootm.c | 477 ++++++++++++++++++++++++++++++++++++++
> efi/payload/early-mem.c | 19 +-
> efi/payload/efi-initrd.c | 123 ++++++++++
> efi/payload/entry-multi.c | 5 +-
> efi/payload/entry-single.c | 5 +-
> efi/payload/handover.c | 195 ++++++++++++++++
> efi/payload/image.c | 228 +-----------------
> efi/payload/image.h | 14 ++
> efi/payload/setup_header.h | 63 +++++
> include/efi.h | 4 +
> include/efi/efi-payload.h | 5 +-
> include/filetype.h | 6 +
> include/malloc.h | 19 ++
> 25 files changed, 1352 insertions(+), 246 deletions(-)
> ---
> base-commit: 3366e9e04a284b7fed71c4b8729fe331b6547d6b
> change-id: 20250919-efi-loader-cdff44ad2d40
>
> Best regards,
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 17+ messages in thread