OvmfPkg/GenericQemuLoadImageLib: support booting via shim

Try load shim first.  In case that succeeded update the command line to
list 'kernel' first so shim will fetch the kernel from the kernel loader
file system.

This allows to use direct kernel boot with distro kernels and secure
boot enabled.  Usually distro kernels can only be verified by distro
shim using the distro keys compiled into the shim binary.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2024-04-11 08:15:22 +02:00 committed by Ard Biesheuvel
parent 3da39f2cb6
commit 4b507b4966

View File

@ -57,6 +57,25 @@ STATIC CONST KERNEL_VENMEDIA_FILE_DEVPATH mKernelDevicePath = {
} }
}; };
STATIC CONST KERNEL_VENMEDIA_FILE_DEVPATH mShimDevicePath = {
{
{
MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,
{ sizeof (VENDOR_DEVICE_PATH) }
},
QEMU_KERNEL_LOADER_FS_MEDIA_GUID
}, {
{
MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP,
{ sizeof (KERNEL_FILE_DEVPATH) }
},
L"shim",
}, {
END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
{ sizeof (EFI_DEVICE_PATH_PROTOCOL) }
}
};
STATIC CONST SINGLE_VENMEDIA_NODE_DEVPATH mQemuKernelLoaderFsDevicePath = { STATIC CONST SINGLE_VENMEDIA_NODE_DEVPATH mQemuKernelLoaderFsDevicePath = {
{ {
{ {
@ -174,6 +193,7 @@ QemuLoadKernelImage (
UINTN CommandLineSize; UINTN CommandLineSize;
CHAR8 *CommandLine; CHAR8 *CommandLine;
UINTN InitrdSize; UINTN InitrdSize;
BOOLEAN Shim;
// //
// Load the image. This should call back into the QEMU EFI loader file system. // Load the image. This should call back into the QEMU EFI loader file system.
@ -181,11 +201,35 @@ QemuLoadKernelImage (
Status = gBS->LoadImage ( Status = gBS->LoadImage (
FALSE, // BootPolicy: exact match required FALSE, // BootPolicy: exact match required
gImageHandle, // ParentImageHandle gImageHandle, // ParentImageHandle
(EFI_DEVICE_PATH_PROTOCOL *)&mKernelDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&mShimDevicePath,
NULL, // SourceBuffer NULL, // SourceBuffer
0, // SourceSize 0, // SourceSize
&KernelImageHandle &KernelImageHandle
); );
if (Status == EFI_SUCCESS) {
Shim = TRUE;
DEBUG ((DEBUG_INFO, "%a: booting via shim\n", __func__));
} else {
Shim = FALSE;
if (Status == EFI_SECURITY_VIOLATION) {
gBS->UnloadImage (KernelImageHandle);
}
if (Status != EFI_NOT_FOUND) {
DEBUG ((DEBUG_INFO, "%a: LoadImage(shim): %r\n", __func__, Status));
return Status;
}
Status = gBS->LoadImage (
FALSE, // BootPolicy: exact match required
gImageHandle, // ParentImageHandle
(EFI_DEVICE_PATH_PROTOCOL *)&mKernelDevicePath,
NULL, // SourceBuffer
0, // SourceSize
&KernelImageHandle
);
}
switch (Status) { switch (Status) {
case EFI_SUCCESS: case EFI_SUCCESS:
break; break;
@ -303,6 +347,13 @@ QemuLoadKernelImage (
KernelLoadedImage->LoadOptionsSize += sizeof (L" initrd=initrd") - 2; KernelLoadedImage->LoadOptionsSize += sizeof (L" initrd=initrd") - 2;
} }
if (Shim) {
//
// Prefix 'kernel ' in UTF-16.
//
KernelLoadedImage->LoadOptionsSize += sizeof (L"kernel ") - 2;
}
if (KernelLoadedImage->LoadOptionsSize == 0) { if (KernelLoadedImage->LoadOptionsSize == 0) {
KernelLoadedImage->LoadOptions = NULL; KernelLoadedImage->LoadOptions = NULL;
} else { } else {
@ -323,7 +374,8 @@ QemuLoadKernelImage (
UnicodeSPrintAsciiFormat ( UnicodeSPrintAsciiFormat (
KernelLoadedImage->LoadOptions, KernelLoadedImage->LoadOptions,
KernelLoadedImage->LoadOptionsSize, KernelLoadedImage->LoadOptionsSize,
"%a%a", "%a%a%a",
(Shim == FALSE) ? "" : "kernel ",
(CommandLineSize == 0) ? "" : CommandLine, (CommandLineSize == 0) ? "" : CommandLine,
(InitrdSize == 0) ? "" : " initrd=initrd" (InitrdSize == 0) ? "" : " initrd=initrd"
); );