From: Andrew Jones <andrew.jones@linux.dev>
To: kvm@vger.kernel.org, kvmarm@lists.linux.dev
Cc: alexandru.elisei@arm.com, eric.auger@redhat.com,
nikos.nikoleris@arm.com, shahuang@redhat.com,
pbonzini@redhat.com, thuth@redhat.com
Subject: [kvm-unit-tests PATCH v3 09/18] lib/efi: Add support for loading the initrd
Date: Tue, 5 Mar 2024 17:46:33 +0100 [thread overview]
Message-ID: <20240305164623.379149-29-andrew.jones@linux.dev> (raw)
In-Reply-To: <20240305164623.379149-20-andrew.jones@linux.dev>
When loading non-efi tests with QEMU's '-kernel' option we also load
an environ with the '-initrd' option. Now that efi tests can also be
loaded with the '-kernel' option also provide the '-initrd' environ.
For EFI, we use the EFI_LOAD_FILE2_PROTOCOL_GUID protocol to load
LINUX_EFI_INITRD_MEDIA_GUID. Each architecture which wants to use the
initrd for the environ will need to call setup_env() on the initrd
data. As usual, the new efi function is heavily influenced by Linux's
implementation.
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Signed-off-by: Andrew Jones <andrew.jones@linux.dev>
---
lib/efi.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
lib/linux/efi.h | 27 ++++++++++++++++++++
2 files changed, 92 insertions(+)
diff --git a/lib/efi.c b/lib/efi.c
index 4d1126b4a64e..12c66c6ffd1f 100644
--- a/lib/efi.c
+++ b/lib/efi.c
@@ -14,6 +14,10 @@
#include "efi.h"
#include "libfdt/libfdt.h"
+/* From each arch */
+extern char *initrd;
+extern u32 initrd_size;
+
/* From lib/argv.c */
extern int __argc, __envc;
extern char *__argv[100];
@@ -302,6 +306,65 @@ static void *efi_get_fdt(efi_handle_t handle, struct efi_loaded_image_64 *image)
return fdt_check_header(fdt) == 0 ? fdt : NULL;
}
+static const struct {
+ struct efi_vendor_dev_path vendor;
+ struct efi_generic_dev_path end;
+} __packed initrd_dev_path = {
+ {
+ {
+ EFI_DEV_MEDIA,
+ EFI_DEV_MEDIA_VENDOR,
+ sizeof(struct efi_vendor_dev_path),
+ },
+ LINUX_EFI_INITRD_MEDIA_GUID
+ }, {
+ EFI_DEV_END_PATH,
+ EFI_DEV_END_ENTIRE,
+ sizeof(struct efi_generic_dev_path)
+ }
+};
+
+static void efi_load_initrd(void)
+{
+ efi_guid_t lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;
+ efi_device_path_protocol_t *dp;
+ efi_load_file2_protocol_t *lf2;
+ efi_handle_t handle;
+ efi_status_t status;
+ unsigned long file_size = 0;
+
+ initrd = NULL;
+ initrd_size = 0;
+
+ dp = (efi_device_path_protocol_t *)&initrd_dev_path;
+ status = efi_bs_call(locate_device_path, &lf2_proto_guid, &dp, &handle);
+ if (status != EFI_SUCCESS)
+ return;
+
+ status = efi_bs_call(handle_protocol, handle, &lf2_proto_guid, (void **)&lf2);
+ assert(status == EFI_SUCCESS);
+
+ status = efi_call_proto(lf2, load_file, dp, false, &file_size, NULL);
+ assert(status == EFI_BUFFER_TOO_SMALL);
+
+ status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, file_size, (void **)&initrd);
+ assert(status == EFI_SUCCESS);
+
+ status = efi_call_proto(lf2, load_file, dp, false, &file_size, (void *)initrd);
+ assert(status == EFI_SUCCESS);
+
+ initrd_size = (u32)file_size;
+
+ /*
+ * UEFI appends initrd=initrd to the command line when an initrd is present.
+ * Remove it in order to avoid confusing unit tests.
+ */
+ if (!strcmp(__argv[__argc - 1], "initrd=initrd")) {
+ __argv[__argc - 1] = NULL;
+ __argc -= 1;
+ }
+}
+
efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
{
int ret;
@@ -340,6 +403,8 @@ efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
}
setup_args(cmdline_ptr);
+ efi_load_initrd();
+
efi_bootinfo.fdt = efi_get_fdt(handle, image);
/* Set up efi_bootinfo */
efi_bootinfo.mem_map.map = ↦
diff --git a/lib/linux/efi.h b/lib/linux/efi.h
index 92d798f79767..8fa23ad078ce 100644
--- a/lib/linux/efi.h
+++ b/lib/linux/efi.h
@@ -70,6 +70,9 @@ typedef guid_t efi_guid_t;
#define LOADED_IMAGE_PROTOCOL_GUID EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+#define EFI_LOAD_FILE2_PROTOCOL_GUID EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e, 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
+#define LINUX_EFI_INITRD_MEDIA_GUID EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68)
+
typedef struct {
efi_guid_t guid;
void *table;
@@ -248,6 +251,12 @@ struct efi_generic_dev_path {
u16 length;
} __packed;
+struct efi_vendor_dev_path {
+ struct efi_generic_dev_path header;
+ efi_guid_t vendorguid;
+ u8 vendordata[];
+} __packed;
+
typedef struct efi_generic_dev_path efi_device_path_protocol_t;
/*
@@ -449,6 +458,19 @@ typedef struct _efi_simple_file_system_protocol efi_simple_file_system_protocol_
typedef struct _efi_file_protocol efi_file_protocol_t;
typedef efi_simple_file_system_protocol_t efi_file_io_interface_t;
typedef efi_file_protocol_t efi_file_t;
+typedef union efi_load_file_protocol efi_load_file_protocol_t;
+typedef union efi_load_file_protocol efi_load_file2_protocol_t;
+
+union efi_load_file_protocol {
+ struct {
+ efi_status_t (__efiapi *load_file)(efi_load_file_protocol_t *,
+ efi_device_path_protocol_t *,
+ bool, unsigned long *, void *);
+ };
+ struct {
+ u32 load_file;
+ } mixed_mode;
+};
typedef efi_status_t efi_simple_file_system_protocol_open_volume(
efi_simple_file_system_protocol_t *this,
@@ -544,7 +566,12 @@ typedef struct {
efi_char16_t file_name[1];
} efi_file_info_t;
+#define efi_fn_call(inst, func, ...) (inst)->func(__VA_ARGS__)
#define efi_bs_call(func, ...) efi_system_table->boottime->func(__VA_ARGS__)
#define efi_rs_call(func, ...) efi_system_table->runtime->func(__VA_ARGS__)
+#define efi_call_proto(inst, func, ...) ({ \
+ __typeof__(inst) __inst = (inst); \
+ efi_fn_call(__inst, func, __inst, ##__VA_ARGS__); \
+})
#endif /* __LINUX_UEFI_H */
--
2.44.0
next prev parent reply other threads:[~2024-03-05 16:46 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-05 16:46 [kvm-unit-tests PATCH v3 00/18] arm64: EFI improvements Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 01/18] runtime: Update MAX_SMP probe Andrew Jones
2024-03-07 2:29 ` Shaoqin Huang
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 02/18] runtime: Add yet another 'no kernel' error message Andrew Jones
2024-03-07 2:39 ` Shaoqin Huang
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 03/18] arm64: efi: Don't create dummy test Andrew Jones
2024-03-07 3:37 ` Shaoqin Huang
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 04/18] arm64: efi: Make running tests on EFI can be parallel Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 05/18] arm64: efi: Remove redundant dtb generation Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 06/18] arm64: efi: Move run code into a function Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 07/18] arm64: efi: Remove EFI_USE_DTB Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 08/18] arm64: efi: Improve device tree discovery Andrew Jones
2024-03-25 16:24 ` Paluri, PavanKumar
2024-03-25 21:59 ` Nikos Nikoleris
2024-03-26 9:03 ` Andrew Jones
2024-03-05 16:46 ` Andrew Jones [this message]
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 10/18] arm64: efi: Allow running tests directly Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 11/18] arm/arm64: Factor out some initial setup Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 12/18] arm/arm64: Factor out allocator init from mem_init Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 13/18] arm64: Simplify efi_mem_init Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 14/18] arm64: Add memregions_efi_init Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 15/18] arm64: efi: Don't map reserved regions Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 16/18] arm64: efi: Fix _start returns from failed _relocate Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 17/18] arm64: efi: Switch to our own stack Andrew Jones
2024-03-05 16:46 ` [kvm-unit-tests PATCH v3 18/18] arm64: efi: Add gitlab CI Andrew Jones
2024-03-18 16:47 ` [kvm-unit-tests PATCH v3 00/18] arm64: EFI improvements Andrew Jones
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=20240305164623.379149-29-andrew.jones@linux.dev \
--to=andrew.jones@linux.dev \
--cc=alexandru.elisei@arm.com \
--cc=eric.auger@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=nikos.nikoleris@arm.com \
--cc=pbonzini@redhat.com \
--cc=shahuang@redhat.com \
--cc=thuth@redhat.com \
/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