1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 * Generic Linux boot protocol using the EFI/PE entry point of the kernel. Passes
5 * initrd with the LINUX_INITRD_MEDIA_GUID DevicePath and cmdline with
6 * EFI LoadedImageProtocol.
8 * This method works for Linux 5.8 and newer on ARM/Aarch64, x86/x68_64 and RISC-V.
17 #include "secure-boot.h"
20 #define STUB_PAYLOAD_GUID \
21 { 0x55c5d1f8, 0x04cd, 0x46b5, { 0x8a, 0x20, 0xe5, 0x6c, 0xbb, 0x30, 0x52, 0xd0 } }
26 const EFI_DEVICE_PATH
*device_path
;
29 static bool validate_payload(
30 const void *ctx
, const EFI_DEVICE_PATH
*device_path
, const void *file_buffer
, size_t file_size
) {
32 const ValidationContext
*payload
= ASSERT_PTR(ctx
);
34 if (device_path
!= payload
->device_path
)
37 /* Security arch (1) protocol does not provide a file buffer. Instead we are supposed to fetch the payload
38 * ourselves, which is not needed as we already have everything in memory and the device paths match. */
39 if (file_buffer
&& (file_buffer
!= payload
->addr
|| file_size
!= payload
->len
))
45 static EFI_STATUS
load_image(EFI_HANDLE parent
, const void *source
, size_t len
, EFI_HANDLE
*ret_image
) {
50 /* We could pass a NULL device path, but it's nicer to provide something and it allows us to identify
51 * the loaded image from within the security hooks. */
53 VENDOR_DEVICE_PATH payload
;
55 } _packed_ payload_device_path
= {
58 .Type
= MEDIA_DEVICE_PATH
,
59 .SubType
= MEDIA_VENDOR_DP
,
60 .Length
= { sizeof(payload_device_path
.payload
), 0 },
62 .Guid
= STUB_PAYLOAD_GUID
,
65 .Type
= END_DEVICE_PATH_TYPE
,
66 .SubType
= END_ENTIRE_DEVICE_PATH_SUBTYPE
,
67 .Length
= { sizeof(payload_device_path
.end
), 0 },
71 /* We want to support unsigned kernel images as payload, which is safe to do under secure boot
72 * because it is embedded in this stub loader (and since it is already running it must be trusted). */
73 install_security_override(
75 &(ValidationContext
) {
78 .device_path
= &payload_device_path
.payload
.Header
,
81 EFI_STATUS ret
= BS
->LoadImage(
84 &payload_device_path
.payload
.Header
,
89 uninstall_security_override();
94 EFI_STATUS
linux_exec(
96 const char16_t
*cmdline
,
97 const void *linux_buffer
,
99 const void *initrd_buffer
,
100 size_t initrd_length
) {
102 uint32_t compat_address
;
106 assert(linux_buffer
&& linux_length
> 0);
107 assert(initrd_buffer
|| initrd_length
== 0);
109 err
= pe_kernel_info(linux_buffer
, &compat_address
);
110 #if defined(__i386__) || defined(__x86_64__)
111 if (err
== EFI_UNSUPPORTED
)
112 /* Kernel is too old to support LINUX_INITRD_MEDIA_GUID, try the deprecated EFI handover
114 return linux_exec_efi_handover(
122 if (err
!= EFI_SUCCESS
)
123 return log_error_status(err
, "Bad kernel image: %m");
125 _cleanup_(unload_imagep
) EFI_HANDLE kernel_image
= NULL
;
126 err
= load_image(parent
, linux_buffer
, linux_length
, &kernel_image
);
127 if (err
!= EFI_SUCCESS
)
128 return log_error_status(err
, "Error loading kernel image: %m");
130 EFI_LOADED_IMAGE_PROTOCOL
*loaded_image
;
131 err
= BS
->HandleProtocol(kernel_image
, &LoadedImageProtocol
, (void **) &loaded_image
);
132 if (err
!= EFI_SUCCESS
)
133 return log_error_status(err
, "Error getting kernel loaded image protocol: %m");
136 loaded_image
->LoadOptions
= (void *) cmdline
;
137 loaded_image
->LoadOptionsSize
= strsize16(loaded_image
->LoadOptions
);
140 _cleanup_(cleanup_initrd
) EFI_HANDLE initrd_handle
= NULL
;
141 err
= initrd_register(initrd_buffer
, initrd_length
, &initrd_handle
);
142 if (err
!= EFI_SUCCESS
)
143 return log_error_status(err
, "Error registering initrd: %m");
146 err
= BS
->StartImage(kernel_image
, NULL
, NULL
);
148 /* Try calling the kernel compat entry point if one exists. */
149 if (err
== EFI_UNSUPPORTED
&& compat_address
> 0) {
150 EFI_IMAGE_ENTRY_POINT compat_entry
=
151 (EFI_IMAGE_ENTRY_POINT
) ((uint8_t *) loaded_image
->ImageBase
+ compat_address
);
152 err
= compat_entry(kernel_image
, ST
);
155 return log_error_status(err
, "Error starting kernel image: %m");