* [PATCH 1/7] drivers: video: efi-gop: fix null reference pointer.
@ 2025-08-31 3:55 chalianis1
2025-08-31 3:55 ` [PATCH 2/7] efi: video: gop: remove dependency to x86 chalianis1
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: chalianis1 @ 2025-08-31 3:55 UTC (permalink / raw)
To: s.hauer, a.fatoum; +Cc: barebox, Chali Anis
From: Chali Anis <chalianis1@gmail.com>
fix a null reference pointer on mode variable, that was never initialized,
the mode will be set by the framebuffer subsyetem after initialisation so
it's not necessary to change the resolution here.
Fixes: 6518b21c6c66 ("video: add EFI Graphics Output Protocol support")
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
drivers/video/efi_gop.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/video/efi_gop.c b/drivers/video/efi_gop.c
index f4f58d9271f5..cef8a6816cac 100644
--- a/drivers/video/efi_gop.c
+++ b/drivers/video/efi_gop.c
@@ -169,8 +169,6 @@ static int efi_gop_query(struct efi_gop_priv *priv)
priv->fb.screen_base = mode->frame_buffer_base;
priv->mode = mode->mode;
- priv->fb.xres = priv->fb.mode->xres;
- priv->fb.yres = priv->fb.mode->yres;
return 0;
}
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/7] efi: video: gop: remove dependency to x86.
2025-08-31 3:55 [PATCH 1/7] drivers: video: efi-gop: fix null reference pointer chalianis1
@ 2025-08-31 3:55 ` chalianis1
2025-08-31 3:55 ` [PATCH 3/7] efi: payload: initrd: implement efi initrd media protocol chalianis1
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: chalianis1 @ 2025-08-31 3:55 UTC (permalink / raw)
To: s.hauer, a.fatoum; +Cc: barebox, Chali Anis
From: Chali Anis <chalianis1@gmail.com>
efi GOP work also in arm64, the efi has drivers that implements
LCDs and expose them as GOP protocol.
Tested on QEMU ramfb and RPi3b 64 bit.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
drivers/video/Kconfig | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 9a0e54bddbaf..b2eccd5db7fe 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -32,7 +32,6 @@ config DRIVER_VIDEO_ATMEL_HLCD
config DRIVER_VIDEO_EFI_GOP
bool "EFI Graphics Output Protocol (GOP)"
depends on EFI_PAYLOAD
- depends on X86
config DRIVER_VIDEO_IMX
bool "i.MX framebuffer driver"
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/7] efi: payload: initrd: implement efi initrd media protocol.
2025-08-31 3:55 [PATCH 1/7] drivers: video: efi-gop: fix null reference pointer chalianis1
2025-08-31 3:55 ` [PATCH 2/7] efi: video: gop: remove dependency to x86 chalianis1
@ 2025-08-31 3:55 ` chalianis1
2025-08-31 3:55 ` [PATCH 4/7] arm: efi: add a generic efi machine chalianis1
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: chalianis1 @ 2025-08-31 3:55 UTC (permalink / raw)
To: s.hauer, a.fatoum; +Cc: barebox, Chali Anis
From: Chali Anis <chalianis1@gmail.com>
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/Makefile | 1 +
efi/payload/efi-initrd.c | 123 ++++++++++++++++++++++++++++++++++++++
include/efi.h | 4 ++
include/efi/efi-payload.h | 3 +
5 files changed, 138 insertions(+)
create mode 100644 efi/payload/efi-initrd.c
diff --git a/efi/guid.c b/efi/guid.c
index ef230a2b2403..7b572acb768b 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/Makefile b/efi/payload/Makefile
index a4a0332a8288..1250535302d3 100644
--- a/efi/payload/Makefile
+++ b/efi/payload/Makefile
@@ -2,6 +2,7 @@
obj-y += init.o
obj-y += image.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/efi-initrd.c b/efi/payload/efi-initrd.c
new file mode 100644
index 000000000000..633fbc29c137
--- /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 40b69fdb0188..bd339ea097c3 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 fe45864dd8a7..d8e66a187a87 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] 7+ messages in thread
* [PATCH 4/7] arm: efi: add a generic efi machine.
2025-08-31 3:55 [PATCH 1/7] drivers: video: efi-gop: fix null reference pointer chalianis1
2025-08-31 3:55 ` [PATCH 2/7] efi: video: gop: remove dependency to x86 chalianis1
2025-08-31 3:55 ` [PATCH 3/7] efi: payload: initrd: implement efi initrd media protocol chalianis1
@ 2025-08-31 3:55 ` chalianis1
2025-08-31 3:55 ` [PATCH 5/7] lib: fdt: add lib fdt padding size chalianis1
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: chalianis1 @ 2025-08-31 3:55 UTC (permalink / raw)
To: s.hauer, a.fatoum; +Cc: barebox, Chali Anis
From: Chali Anis <chalianis1@gmail.com>
add a generic arm64 machine that can select the CPU_V8 and the
required efi payload minimal configs. this machine permits to have
a clean arm64 efi payload, idealy we don't need the other machine
that comes from multi arch since they execute code that is specific
for the correspondig hardware. with this generic efi machine the
barebox log shell is more clean. to get a pure clean efi payload
you need to unselect all the other arch machines and keep only the
EFI ARM64.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
arch/arm/Kconfig | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index cce71b50eb04..0a098440ddde 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -254,6 +254,18 @@ config ARCH_ZYNQMP
select GPIOLIB
select HAS_MACB
+config EFI_ARM64
+ bool "EFI on ARM64"
+ select CPU_V8
+ select CPU_SUPPORTS_64BIT_KERNEL
+ select HAVE_EFI_PAYLOAD
+ select EFI_PAYLOAD
+ select BOOTM_FITIMAGE
+ select CLOCKSOURCE_EFI
+ select DRIVER_VIDEO_EFI_GOP
+ depends on 64BIT
+ default y if ARCH_MULTIARCH
+
source "arch/arm/cpu/Kconfig"
source "arch/arm/mach-at91/Kconfig"
source "arch/arm/mach-bcm283x/Kconfig"
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 5/7] lib: fdt: add lib fdt padding size.
2025-08-31 3:55 [PATCH 1/7] drivers: video: efi-gop: fix null reference pointer chalianis1
` (2 preceding siblings ...)
2025-08-31 3:55 ` [PATCH 4/7] arm: efi: add a generic efi machine chalianis1
@ 2025-08-31 3:55 ` chalianis1
2025-08-31 3:55 ` [PATCH 6/7] efi: payload: add support for efi stub boot and fit image chalianis1
2025-08-31 3:55 ` [PATCH 7/7] efi: payload: add options for FDT force and initrd direct install chalianis1
5 siblings, 0 replies; 7+ messages in thread
From: chalianis1 @ 2025-08-31 3:55 UTC (permalink / raw)
To: s.hauer, a.fatoum; +Cc: barebox, Chali Anis
From: Chali Anis <chalianis1@gmail.com>
When loading an unflating an FDT in some cases we need to have
a padding space to be able to apply fixes.
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
lib/Kconfig | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/Kconfig b/lib/Kconfig
index d07e2f3b6959..89e95d202c2c 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -121,6 +121,10 @@ config FSL_QE_FIRMWARE
select CRC32
bool
+config FDT_PADDING
+ int "FDT padding size for fixups"
+ default 4096
+
config LIBFDT
bool
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 6/7] efi: payload: add support for efi stub boot and fit image.
2025-08-31 3:55 [PATCH 1/7] drivers: video: efi-gop: fix null reference pointer chalianis1
` (3 preceding siblings ...)
2025-08-31 3:55 ` [PATCH 5/7] lib: fdt: add lib fdt padding size chalianis1
@ 2025-08-31 3:55 ` chalianis1
2025-08-31 3:55 ` [PATCH 7/7] efi: payload: add options for FDT force and initrd direct install chalianis1
5 siblings, 0 replies; 7+ messages in thread
From: chalianis1 @ 2025-08-31 3:55 UTC (permalink / raw)
To: s.hauer, a.fatoum; +Cc: barebox, Chali Anis
From: Chali Anis <chalianis1@gmail.com>
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/image.c | 457 ++++++++++++++++++++++++++++++++++++++------
1 file changed, 403 insertions(+), 54 deletions(-)
diff --git a/efi/payload/image.c b/efi/payload/image.c
index 33c5e18dac27..38d52a32ea64 100644
--- a/efi/payload/image.c
+++ b/efi/payload/image.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>
@@ -77,42 +78,41 @@ struct linux_kernel_header {
uint32_t handover_offset; /** */
} __attribute__ ((packed));
-static void *efi_read_file(const char *file, size_t *size)
-{
- efi_physical_addr_t mem;
- efi_status_t efiret;
- struct stat s;
- char *buf;
- ssize_t ret;
+struct efi_mem_resource {
+ efi_physical_addr_t base;
+ size_t size;
+} __attribute__ ((packed));
- buf = read_file(file, size);
- if (buf || errno != ENOMEM)
- return buf;
+struct efi_image_data {
+ struct image_data *data;
- ret = stat(file, &s);
- if (ret)
- return NULL;
+ efi_handle_t handle;
+ struct efi_loaded_image *loaded_image;
- efiret = BS->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
- EFI_LOADER_CODE,
- DIV_ROUND_UP(s.st_size, EFI_PAGE_SIZE),
- &mem);
+ 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;
}
- buf = efi_phys_to_virt(mem);
-
- ret = read_file_into_buf(file, buf, s.st_size);
- if (ret < 0)
- return NULL;
-
- *size = ret;
- return buf;
+ return efi_phys_to_virt(*mem);
}
-static void efi_free_file(void *_mem, size_t size)
+static void efi_free_pages(void *_mem, size_t size)
{
efi_physical_addr_t mem = efi_virt_to_phys(_mem);
@@ -122,28 +122,40 @@ 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)
+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;
- exe = efi_read_file(file, &size);
- if (!exe)
- return -errno;
+ buf = read_file(file, &size);
+ if (!buf)
+ return -ENOMEM;
- efiret = BS->load_image(false, efi_parent_image, efi_device_path, exe, size,
- &handle);
+ exe = efi_allocate_pages(&mem, size, EFI_ALLOCATE_ANY_PAGES,
+ EFI_LOADER_CODE);
+ if (!exe) {
+ pr_err("Failed to allocate pages for image\n");
+ return -ENOMEM;
+ }
+
+ memcpy(exe, buf, size);
+
+ efiret = BS->load_image(false, efi_parent_image, efi_device_path, exe,
+ size, &handle);
if (EFI_ERROR(efiret)) {
pr_err("failed to LoadImage: %s\n", efi_strerror(efiret));
goto out;
};
efiret = BS->open_protocol(handle, &efi_loaded_image_protocol_guid,
- (void **)loaded_image,
- efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ (void **)loaded_image, efi_parent_image,
+ NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(efiret)) {
pr_err("failed to OpenProtocol: %s\n", efi_strerror(efiret));
BS->unload_image(handle);
@@ -151,8 +163,10 @@ static int efi_load_image(const char *file, struct efi_loaded_image **loaded_ima
}
*h = handle;
+
+ return 0;
out:
- efi_free_file(exe, size);
+ efi_free_pages(exe, size);
return -efi_errno(efiret);
}
@@ -171,20 +185,16 @@ static bool is_linux_image(enum filetype filetype, const void *base)
return false;
}
-static int efi_execute_image(enum filetype filetype, const char *file)
+static 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) ||
+ is_driver =
+ (loaded_image->image_code_type == EFI_BOOT_SERVICES_CODE) ||
(loaded_image->image_code_type == EFI_RUNTIME_SERVICES_CODE);
if (is_linux_image(filetype, loaded_image->image_base)) {
@@ -192,7 +202,8 @@ static int efi_execute_image(enum filetype filetype, const char *file)
options = linux_bootargs_get();
pr_info("add linux options '%s'\n", options);
if (options) {
- loaded_image->load_options = xstrdup_char_to_wchar(options);
+ loaded_image->load_options =
+ xstrdup_char_to_wchar(options);
loaded_image->load_options_size =
(strlen(options) + 1) * sizeof(wchar_t);
}
@@ -216,11 +227,11 @@ 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);
+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)
+ struct linux_kernel_header *header)
{
handover_fn handover;
uintptr_t addr;
@@ -244,7 +255,7 @@ static int do_bootm_efi(struct image_data *data)
struct efi_loaded_image *loaded_image;
struct linux_kernel_header *image_header, *boot_header;
- ret = efi_load_image(data->os_file, &loaded_image, &handle);
+ ret = efi_load_file_image(data->os_file, &loaded_image, &handle);
if (ret)
return ret;
@@ -284,8 +295,9 @@ static int do_bootm_efi(struct image_data *data)
boot_header->cmdline_size = strlen(options);
}
- boot_header->code32_start = efi_virt_to_phys(loaded_image->image_base +
- (image_header->setup_sects+1) * 512);
+ 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);
@@ -311,15 +323,350 @@ 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 ? (bool)fit_has_image(data->os_fit,
+ data->fit_config, "ramdisk") : 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->initrd_file, &st) && st.st_size > 0)
+ return false;
+ }
+
+ return data->os_fit ? (bool)fit_has_image(data->os_fit,
+ data->fit_config, "fdt") : false;
+}
+
+static int efi_load_os(struct efi_image_data *e)
+{
+ 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) {
+ image = (void *)e->data->fit_kernel;
+ image_size = e->data->fit_kernel_size;
+ } else if (e->data->os_file)
+ return efi_load_file_image(e->data->os_file,
+ &e->loaded_image, &e->handle);
+
+ 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)
+{
+ 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;
+ bool from_fit;
+ int ret;
+
+ from_fit = ramdisk_is_fit(e->data);
+
+ if (from_fit) {
+ 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;
+ }
+ }
+
+ if (!from_fit) {
+ 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;
+ }
+ }
+
+ if (!from_fit && tmp)
+ free(tmp);
+
+ return 0;
+
+free_pages:
+ efi_free_pages(vmem, initrd_size);
+free_pool:
+ BS->free_pool(e->initrd_res);
+free_mem:
+ if (!from_fit && tmp)
+ 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;
+ bool from_fit;
+ int ret;
+
+ if (IS_ENABLED(CONFIG_EFI_FDT_FORCE))
+ return 0;
+
+ from_fit = fdt_is_fit(e->data);
+ if (from_fit) {
+ 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;
+ }
+ }
+
+ if (!from_fit) {
+ 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, of_size + CONFIG_FDT_PADDING,
+ EFI_ALLOCATE_ANY_PAGES,
+ EFI_ACPI_RECLAIM_MEMORY);
+ if (!vmem) {
+ pr_err("Failed to allocate pages for FDT\n");
+ goto free_file;
+ return -ENOMEM;
+ }
+
+ 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 = of_size + CONFIG_FDT_PADDING;
+
+ if (!from_fit && tmp)
+ free(tmp);
+
+ return 0;
+
+free_mem:
+ efi_free_pages(vmem, of_size);
+free_file:
+ if (!from_fit && tmp)
+ 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)
{
- return efi_execute_image(b->type, file);
+ 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 = {
@@ -360,8 +707,10 @@ static int efi_register_image_handler(void)
if (IS_ENABLED(CONFIG_X86))
register_image_handler(&non_efi_handle_linux_x86);
- if (IS_ENABLED(CONFIG_ARM64))
+ if (IS_ENABLED(CONFIG_ARM64)) {
+ register_image_handler(&efi_arm64_handle_tr);
binfmt_register(&binfmt_arm64_efi_hook);
+ }
return 0;
}
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 7/7] efi: payload: add options for FDT force and initrd direct install
2025-08-31 3:55 [PATCH 1/7] drivers: video: efi-gop: fix null reference pointer chalianis1
` (4 preceding siblings ...)
2025-08-31 3:55 ` [PATCH 6/7] efi: payload: add support for efi stub boot and fit image chalianis1
@ 2025-08-31 3:55 ` chalianis1
5 siblings, 0 replies; 7+ messages in thread
From: chalianis1 @ 2025-08-31 3:55 UTC (permalink / raw)
To: s.hauer, a.fatoum; +Cc: barebox, Chali Anis
From: Chali Anis <chalianis1@gmail.com>
Signed-off-by: Chali Anis <chalianis1@gmail.com>
---
efi/Kconfig | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/efi/Kconfig b/efi/Kconfig
index 84f670fd23d3..c3811574920d 100644
--- a/efi/Kconfig
+++ b/efi/Kconfig
@@ -50,4 +50,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
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-08-31 3:56 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-08-31 3:55 [PATCH 1/7] drivers: video: efi-gop: fix null reference pointer chalianis1
2025-08-31 3:55 ` [PATCH 2/7] efi: video: gop: remove dependency to x86 chalianis1
2025-08-31 3:55 ` [PATCH 3/7] efi: payload: initrd: implement efi initrd media protocol chalianis1
2025-08-31 3:55 ` [PATCH 4/7] arm: efi: add a generic efi machine chalianis1
2025-08-31 3:55 ` [PATCH 5/7] lib: fdt: add lib fdt padding size chalianis1
2025-08-31 3:55 ` [PATCH 6/7] efi: payload: add support for efi stub boot and fit image chalianis1
2025-08-31 3:55 ` [PATCH 7/7] efi: payload: add options for FDT force and initrd direct install chalianis1
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox