* [PATCH v2 0/2] xen/efi: Make boot more flexible, especially with GRUB2
@ 2025-06-24 14:27 Frediano Ziglio
2025-06-24 14:27 ` [PATCH v2 1/2] xen/efi: Handle cases where file didn't come from ESP Frediano Ziglio
2025-06-24 14:27 ` [PATCH v2 2/2] xen/efi: Support loading initrd using GRUB2 LoadFile2 protocol Frediano Ziglio
0 siblings, 2 replies; 4+ messages in thread
From: Frediano Ziglio @ 2025-06-24 14:27 UTC (permalink / raw)
To: xen-devel
Cc: Frediano Ziglio, Daniel P. Smith, Marek Marczykowski-Górecki,
Jan Beulich
The combination of GRUB2, EFI and UKI allows potentially more flexibility.
For instance is possible to load xen.efi from a no ESP partition leaving
a boot loader like GRUB2 taking care of the file loading.
This however requires some changes in Xen to be less restrictive.
Specifically for GRUB2 these changes allows the usage of "chainloader"
command with UKI and reading xen.efi from no ESP (so no DeviceHandle
set) and usage of "linux" and "initrd" commands to load separately
the kernel (embedding using UKI) and initrd (using LoadFile2 protocol).
Changes since v1:
- keep read_file fatal when it was so;
- attempt to use LoadFile2 after trying object section;
- minor changes (see details on specific changes).
Frediano Ziglio (2):
xen/efi: Handle cases where file didn't come from ESP
xen/efi: Support loading initrd using GRUB2 LoadFile2 protocol
xen/common/efi/boot.c | 105 +++++++++++++++++++++++++++++++++++---
xen/include/efi/efidevp.h | 21 ++++++++
2 files changed, 120 insertions(+), 6 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/2] xen/efi: Handle cases where file didn't come from ESP
2025-06-24 14:27 [PATCH v2 0/2] xen/efi: Make boot more flexible, especially with GRUB2 Frediano Ziglio
@ 2025-06-24 14:27 ` Frediano Ziglio
2025-06-24 14:39 ` Marek Marczykowski-Górecki
2025-06-24 14:27 ` [PATCH v2 2/2] xen/efi: Support loading initrd using GRUB2 LoadFile2 protocol Frediano Ziglio
1 sibling, 1 reply; 4+ messages in thread
From: Frediano Ziglio @ 2025-06-24 14:27 UTC (permalink / raw)
To: xen-devel
Cc: Frediano Ziglio, Daniel P. Smith, Marek Marczykowski-Górecki,
Jan Beulich
A boot loader can load files from outside ESP.
In these cases device could be not provided or path could
be something not supported.
In these cases allows to boot anyway, all information
could be provided using UKI or using other boot loader
features.
Signed-off-by: Frediano Ziglio <frediano.ziglio@cloud.com>
---
Changes since v1:
- set "leaf" to NULL instead of a buffer with an empty string;
- keep read_file fatal if cannot load file (except configuration).
---
xen/common/efi/boot.c | 34 +++++++++++++++++++++++++++++-----
1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 1a9b4e7dae..b18af2f1f4 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -443,6 +443,18 @@ static EFI_FILE_HANDLE __init get_parent_handle(const EFI_LOADED_IMAGE *loaded_i
CHAR16 *pathend, *ptr;
EFI_STATUS ret;
+ /*
+ * In some cases the image could not come from a specific device.
+ * For instance this can happen if Xen was loaded using GRUB2 "linux"
+ * command.
+ */
+ *leaf = NULL;
+ if ( !loaded_image->DeviceHandle )
+ {
+ PrintStr(L"Xen image loaded without providing a device\r\n");
+ return NULL;
+ }
+
do {
EFI_FILE_IO_INTERFACE *fio;
@@ -466,7 +478,15 @@ static EFI_FILE_HANDLE __init get_parent_handle(const EFI_LOADED_IMAGE *loaded_i
if ( DevicePathType(dp) != MEDIA_DEVICE_PATH ||
DevicePathSubType(dp) != MEDIA_FILEPATH_DP )
- blexit(L"Unsupported device path component");
+ {
+ /*
+ * The image could come from an unsupported device.
+ * For instance this can happen if Xen was loaded using GRUB2
+ * "chainloader" command and the file was not from ESP.
+ */
+ PrintStr(L"Unsupported device path component\r\n");
+ return NULL;
+ }
if ( *buffer )
{
@@ -772,8 +792,11 @@ static bool __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
if ( !name )
PrintErrMesg(L"No filename", EFI_OUT_OF_RESOURCES);
- ret = dir_handle->Open(dir_handle, &FileHandle, name,
- EFI_FILE_MODE_READ, 0);
+ if ( dir_handle )
+ ret = dir_handle->Open(dir_handle, &FileHandle, name,
+ EFI_FILE_MODE_READ, 0);
+ else
+ ret = EFI_NOT_FOUND;
if ( file == &cfg && ret == EFI_NOT_FOUND )
return false;
if ( EFI_ERROR(ret) )
@@ -1404,7 +1427,7 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE ImageHandle,
/* Read and parse the config file. */
if ( read_section(loaded_image, L"config", &cfg, NULL) )
PrintStr(L"Using builtin config file\r\n");
- else if ( !cfg_file_name )
+ else if ( !cfg_file_name && file_name)
{
CHAR16 *tail;
@@ -1515,7 +1538,8 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE ImageHandle,
efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
cfg.addr = 0;
- dir_handle->Close(dir_handle);
+ if ( dir_handle )
+ dir_handle->Close(dir_handle);
if ( gop && !base_video )
{
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/2] xen/efi: Support loading initrd using GRUB2 LoadFile2 protocol
2025-06-24 14:27 [PATCH v2 0/2] xen/efi: Make boot more flexible, especially with GRUB2 Frediano Ziglio
2025-06-24 14:27 ` [PATCH v2 1/2] xen/efi: Handle cases where file didn't come from ESP Frediano Ziglio
@ 2025-06-24 14:27 ` Frediano Ziglio
1 sibling, 0 replies; 4+ messages in thread
From: Frediano Ziglio @ 2025-06-24 14:27 UTC (permalink / raw)
To: xen-devel
Cc: Frediano Ziglio, Daniel P. Smith, Marek Marczykowski-Górecki,
Jan Beulich
Allows to load Xen using "linux" and "initrd" GRUB2 commands.
This can be used with UKI to separate initrd in a different module
instead of bundling all together.
Bundling all together can be a problem with Secure Boot where
we need to sign the bundle making harder to change it.
As initrd content does not need to be signed for Secure Boot
bundling it force it to be signed too.
Signed-off-by: Frediano Ziglio <frediano.ziglio@cloud.com>
---
Changes since v1:
- attempt to use LoadFile2 protocol after embedded section.
---
xen/common/efi/boot.c | 71 ++++++++++++++++++++++++++++++++++++++-
xen/include/efi/efidevp.h | 21 ++++++++++++
2 files changed, 91 insertions(+), 1 deletion(-)
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index b18af2f1f4..b6ce3a0257 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -850,6 +850,74 @@ static bool __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
return true;
}
+#pragma pack(1)
+typedef struct {
+ VENDOR_DEVICE_PATH VenMediaNode;
+ EFI_DEVICE_PATH EndNode;
+} SINGLE_NODE_VENDOR_MEDIA_DEVPATH;
+#pragma pack()
+
+static bool __init initrd_load_file2(const CHAR16 *name, struct file *file)
+{
+ static const SINGLE_NODE_VENDOR_MEDIA_DEVPATH __initconst initrd_dev_path = {
+ {
+ {
+ MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH) }
+ },
+ LINUX_EFI_INITRD_MEDIA_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ { sizeof (EFI_DEVICE_PATH) }
+ }
+ };
+ static EFI_GUID __initdata lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;
+ EFI_DEVICE_PATH *dp;
+ EFI_LOAD_FILE2_PROTOCOL *lf2;
+ EFI_HANDLE handle;
+ EFI_STATUS ret;
+ UINTN size;
+
+ dp = (EFI_DEVICE_PATH *)&initrd_dev_path;
+ ret = efi_bs->LocateDevicePath(&lf2_proto_guid, &dp, &handle);
+ if ( EFI_ERROR(ret) )
+ {
+ if ( ret == EFI_NOT_FOUND)
+ return false;
+ PrintErrMesg(L"Error getting file with LoadFile2 interface", ret);
+ }
+
+ ret = efi_bs->HandleProtocol(handle, &lf2_proto_guid, (void **)&lf2);
+ if ( EFI_ERROR(ret) )
+ PrintErrMesg(L"LoadFile2 file does not provide correct protocol", ret);
+
+ size = 0;
+ ret = lf2->LoadFile(lf2, dp, false, &size, NULL);
+ if ( ret != EFI_BUFFER_TOO_SMALL )
+ PrintErrMesg(L"Loading failed", ret);
+
+ file->addr = min(1UL << (32 + PAGE_SHIFT),
+ HYPERVISOR_VIRT_END - DIRECTMAP_VIRT_START);
+ ret = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
+ PFN_UP(size), &file->addr);
+ if ( EFI_ERROR(ret) )
+ PrintErrMesg(L"Allocation failed", ret);
+
+ file->need_to_free = true;
+ file->size = size;
+
+ ret = lf2->LoadFile(lf2, dp, false, &size, file->str);
+ if ( EFI_ERROR(ret) )
+ {
+ efi_bs->FreePages(file->addr, PFN_UP(size));
+ PrintErrMesg(L"Loading failed", ret);
+ }
+
+ efi_arch_handle_module(file, name, NULL);
+
+ return true;
+}
+
static bool __init read_section(const EFI_LOADED_IMAGE *image,
const CHAR16 *name, struct file *file,
const char *options)
@@ -1493,7 +1561,8 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE ImageHandle,
kernel_verified = true;
}
- if ( !read_section(loaded_image, L"ramdisk", &ramdisk, NULL) )
+ if ( !read_section(loaded_image, L"ramdisk", &ramdisk, NULL) &&
+ !initrd_load_file2(L"ramdisk", &ramdisk) )
{
name.s = get_value(&cfg, section.s, "ramdisk");
if ( name.s )
diff --git a/xen/include/efi/efidevp.h b/xen/include/efi/efidevp.h
index beb5785a45..b240c15d2a 100644
--- a/xen/include/efi/efidevp.h
+++ b/xen/include/efi/efidevp.h
@@ -398,5 +398,26 @@ typedef union {
} EFI_DEV_PATH_PTR;
+#define EFI_LOAD_FILE2_PROTOCOL_GUID \
+ { 0x4006c0c1, 0xfcb3, 0x403e, {0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d } }
+
+typedef struct EFI_LOAD_FILE2_PROTOCOL EFI_LOAD_FILE2_PROTOCOL;
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_LOAD_FILE2)(
+ IN EFI_LOAD_FILE2_PROTOCOL *This,
+ IN EFI_DEVICE_PATH *FilePath,
+ IN BOOLEAN BootPolicy,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer OPTIONAL
+ );
+
+struct EFI_LOAD_FILE2_PROTOCOL {
+ EFI_LOAD_FILE2 LoadFile;
+};
+
+#define LINUX_EFI_INITRD_MEDIA_GUID \
+ { 0x5568e427, 0x68fc, 0x4f3d, {0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68} }
#endif
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/2] xen/efi: Handle cases where file didn't come from ESP
2025-06-24 14:27 ` [PATCH v2 1/2] xen/efi: Handle cases where file didn't come from ESP Frediano Ziglio
@ 2025-06-24 14:39 ` Marek Marczykowski-Górecki
0 siblings, 0 replies; 4+ messages in thread
From: Marek Marczykowski-Górecki @ 2025-06-24 14:39 UTC (permalink / raw)
To: Frediano Ziglio; +Cc: xen-devel, Daniel P. Smith, Jan Beulich
[-- Attachment #1: Type: text/plain, Size: 3725 bytes --]
On Tue, Jun 24, 2025 at 03:27:08PM +0100, Frediano Ziglio wrote:
> A boot loader can load files from outside ESP.
> In these cases device could be not provided or path could
> be something not supported.
> In these cases allows to boot anyway, all information
> could be provided using UKI or using other boot loader
> features.
>
> Signed-off-by: Frediano Ziglio <frediano.ziglio@cloud.com>
Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
> ---
> Changes since v1:
> - set "leaf" to NULL instead of a buffer with an empty string;
> - keep read_file fatal if cannot load file (except configuration).
> ---
> xen/common/efi/boot.c | 34 +++++++++++++++++++++++++++++-----
> 1 file changed, 29 insertions(+), 5 deletions(-)
>
> diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
> index 1a9b4e7dae..b18af2f1f4 100644
> --- a/xen/common/efi/boot.c
> +++ b/xen/common/efi/boot.c
> @@ -443,6 +443,18 @@ static EFI_FILE_HANDLE __init get_parent_handle(const EFI_LOADED_IMAGE *loaded_i
> CHAR16 *pathend, *ptr;
> EFI_STATUS ret;
>
> + /*
> + * In some cases the image could not come from a specific device.
> + * For instance this can happen if Xen was loaded using GRUB2 "linux"
> + * command.
> + */
> + *leaf = NULL;
> + if ( !loaded_image->DeviceHandle )
> + {
> + PrintStr(L"Xen image loaded without providing a device\r\n");
> + return NULL;
> + }
> +
> do {
> EFI_FILE_IO_INTERFACE *fio;
>
> @@ -466,7 +478,15 @@ static EFI_FILE_HANDLE __init get_parent_handle(const EFI_LOADED_IMAGE *loaded_i
>
> if ( DevicePathType(dp) != MEDIA_DEVICE_PATH ||
> DevicePathSubType(dp) != MEDIA_FILEPATH_DP )
> - blexit(L"Unsupported device path component");
> + {
> + /*
> + * The image could come from an unsupported device.
> + * For instance this can happen if Xen was loaded using GRUB2
> + * "chainloader" command and the file was not from ESP.
> + */
> + PrintStr(L"Unsupported device path component\r\n");
> + return NULL;
> + }
>
> if ( *buffer )
> {
> @@ -772,8 +792,11 @@ static bool __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
>
> if ( !name )
> PrintErrMesg(L"No filename", EFI_OUT_OF_RESOURCES);
> - ret = dir_handle->Open(dir_handle, &FileHandle, name,
> - EFI_FILE_MODE_READ, 0);
> + if ( dir_handle )
> + ret = dir_handle->Open(dir_handle, &FileHandle, name,
> + EFI_FILE_MODE_READ, 0);
> + else
> + ret = EFI_NOT_FOUND;
> if ( file == &cfg && ret == EFI_NOT_FOUND )
> return false;
> if ( EFI_ERROR(ret) )
> @@ -1404,7 +1427,7 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE ImageHandle,
> /* Read and parse the config file. */
> if ( read_section(loaded_image, L"config", &cfg, NULL) )
> PrintStr(L"Using builtin config file\r\n");
> - else if ( !cfg_file_name )
> + else if ( !cfg_file_name && file_name)
> {
> CHAR16 *tail;
>
> @@ -1515,7 +1538,8 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE ImageHandle,
> efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
> cfg.addr = 0;
>
> - dir_handle->Close(dir_handle);
> + if ( dir_handle )
> + dir_handle->Close(dir_handle);
>
> if ( gop && !base_video )
> {
> --
> 2.43.0
>
--
Best Regards,
Marek Marczykowski-Górecki
Invisible Things Lab
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-06-24 14:39 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-24 14:27 [PATCH v2 0/2] xen/efi: Make boot more flexible, especially with GRUB2 Frediano Ziglio
2025-06-24 14:27 ` [PATCH v2 1/2] xen/efi: Handle cases where file didn't come from ESP Frediano Ziglio
2025-06-24 14:39 ` Marek Marczykowski-Górecki
2025-06-24 14:27 ` [PATCH v2 2/2] xen/efi: Support loading initrd using GRUB2 LoadFile2 protocol Frediano Ziglio
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.