From: chalianis1@gmail.com
To: s.hauer@pengutronix.de, a.fatoum@pengutronix.de
Cc: barebox@lists.infradead.org, Chali Anis <chalianis1@gmail.com>
Subject: [PATCH 3/7] efi: payload: initrd: implement efi initrd media protocol.
Date: Sat, 30 Aug 2025 23:55:38 -0400 [thread overview]
Message-ID: <20250831035542.1623695-3-chalianis1@gmail.com> (raw)
In-Reply-To: <20250831035542.1623695-1-chalianis1@gmail.com>
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
next prev parent reply other threads:[~2025-08-31 3:56 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250831035542.1623695-3-chalianis1@gmail.com \
--to=chalianis1@gmail.com \
--cc=a.fatoum@pengutronix.de \
--cc=barebox@lists.infradead.org \
--cc=s.hauer@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox