From 4b507b49664514d7f09e6b7a9ca2da25a5e440fd Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 11 Apr 2024 08:15:22 +0200
Subject: [PATCH 08/10] 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>

CVE: CVE-2025-2296
Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/4b507b49664514d7f09e6b7a9ca2da25a5e440fd]
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
---
 .../GenericQemuLoadImageLib.c                 | 56 ++++++++++++++++++-
 1 file changed, 54 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c b/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c
index b99fb350aa..9d0ba77755 100644
--- a/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c
+++ b/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c
@@ -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 = {
   {
     {
@@ -174,6 +193,7 @@ QemuLoadKernelImage (
   UINTN                            CommandLineSize;
   CHAR8                            *CommandLine;
   UINTN                            InitrdSize;
+  BOOLEAN                          Shim;
 
   //
   // Load the image. This should call back into the QEMU EFI loader file system.
@@ -181,11 +201,35 @@ QemuLoadKernelImage (
   Status = gBS->LoadImage (
                   FALSE,                    // BootPolicy: exact match required
                   gImageHandle,             // ParentImageHandle
-                  (EFI_DEVICE_PATH_PROTOCOL *)&mKernelDevicePath,
+                  (EFI_DEVICE_PATH_PROTOCOL *)&mShimDevicePath,
                   NULL,                     // SourceBuffer
                   0,                        // SourceSize
                   &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) {
     case EFI_SUCCESS:
       break;
@@ -303,6 +347,13 @@ QemuLoadKernelImage (
     KernelLoadedImage->LoadOptionsSize += sizeof (L" initrd=initrd") - 2;
   }
 
+  if (Shim) {
+    //
+    // Prefix 'kernel ' in UTF-16.
+    //
+    KernelLoadedImage->LoadOptionsSize += sizeof (L"kernel ") - 2;
+  }
+
   if (KernelLoadedImage->LoadOptionsSize == 0) {
     KernelLoadedImage->LoadOptions = NULL;
   } else {
@@ -323,7 +374,8 @@ QemuLoadKernelImage (
     UnicodeSPrintAsciiFormat (
       KernelLoadedImage->LoadOptions,
       KernelLoadedImage->LoadOptionsSize,
-      "%a%a",
+      "%a%a%a",
+      (Shim == FALSE)        ?  "" : "kernel ",
       (CommandLineSize == 0) ?  "" : CommandLine,
       (InitrdSize == 0)      ?  "" : " initrd=initrd"
       );
-- 
2.49.0

