--- /dev/null
+From dbec8dc5ba6341d816ffd495fcd7eeece1716bb4 Mon Sep 17 00:00:00 2001
+From: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>
+Date: Mon, 29 Apr 2024 20:07:19 +0000
+Subject: [PATCH] AmdSev: Halt on failed blob allocation
+
+A malicious host may be able to undermine the fw_cfg
+interface such that loading a blob fails.
+
+In this case rather than continuing to the next boot
+option, the blob verifier should halt.
+
+For non-confidential guests, the error should be non-fatal.
+
+Signed-off-by: Tobin Feldman-Fitzthum <tobin@linux.ibm.com>
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/10b4bb8d6d0c515ed9663691aea3684be8f7b0fc]
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ .../BlobVerifierSevHashes.c | 17 ++++++++++++++++-
+ OvmfPkg/Include/Library/BlobVerifierLib.h | 11 +++++++----
+ .../BlobVerifierLibNull/BlobVerifierNull.c | 13 ++++++++-----
+ .../QemuKernelLoaderFsDxe.c | 9 ++++-----
+ 4 files changed, 35 insertions(+), 15 deletions(-)
+
+diff --git a/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c b/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c
+index 2e58794c3c..6477c5c3d3 100644
+--- a/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c
++++ b/OvmfPkg/AmdSev/BlobVerifierLibSevHashes/BlobVerifierSevHashes.c
+@@ -80,6 +80,7 @@ FindBlobEntryGuid (
+ @param[in] BlobName The name of the blob\r
+ @param[in] Buf The data of the blob\r
+ @param[in] BufSize The size of the blob in bytes\r
++ @param[in] FetchStatus The status of the previous blob fetch\r
+ \r
+ @retval EFI_SUCCESS The blob was verified successfully.\r
+ @retval EFI_ACCESS_DENIED The blob could not be verified, and therefore\r
+@@ -90,13 +91,27 @@ EFIAPI
+ VerifyBlob (\r
+ IN CONST CHAR16 *BlobName,\r
+ IN CONST VOID *Buf,\r
+- IN UINT32 BufSize\r
++ IN UINT32 BufSize,\r
++ IN EFI_STATUS FetchStatus\r
+ )\r
+ {\r
+ CONST GUID *Guid;\r
+ INT32 Remaining;\r
+ HASH_TABLE *Entry;\r
+ \r
++ // Enter a dead loop if the fetching of this blob\r
++ // failed. This prevents a malicious host from\r
++ // circumventing the following checks.\r
++ if (EFI_ERROR (FetchStatus)) {\r
++ DEBUG ((\r
++ DEBUG_ERROR,\r
++ "%a: Fetching blob failed.\n",\r
++ __func__\r
++ ));\r
++\r
++ CpuDeadLoop ();\r
++ }\r
++\r
+ if ((mHashesTable == NULL) || (mHashesTableSize == 0)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+diff --git a/OvmfPkg/Include/Library/BlobVerifierLib.h b/OvmfPkg/Include/Library/BlobVerifierLib.h
+index 7e1af27574..09af1b77de 100644
+--- a/OvmfPkg/Include/Library/BlobVerifierLib.h
++++ b/OvmfPkg/Include/Library/BlobVerifierLib.h
+@@ -22,17 +22,20 @@
+ @param[in] BlobName The name of the blob\r
+ @param[in] Buf The data of the blob\r
+ @param[in] BufSize The size of the blob in bytes\r
++ @param[in] FetchStatus The status of fetching this blob\r
+ \r
+- @retval EFI_SUCCESS The blob was verified successfully.\r
+- @retval EFI_ACCESS_DENIED The blob could not be verified, and therefore\r
+- should be considered non-secure.\r
++ @retval EFI_SUCCESS The blob was verified successfully or was not\r
++ found in the hash table.\r
++ @retval EFI_ACCESS_DENIED Kernel hashes not supported but the boot can\r
++ continue safely.\r
+ **/\r
+ EFI_STATUS\r
+ EFIAPI\r
+ VerifyBlob (\r
+ IN CONST CHAR16 *BlobName,\r
+ IN CONST VOID *Buf,\r
+- IN UINT32 BufSize\r
++ IN UINT32 BufSize,\r
++ IN EFI_STATUS FetchStatus\r
+ );\r
+ \r
+ #endif\r
+diff --git a/OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierNull.c b/OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierNull.c
+index e817c3cc95..db5320571c 100644
+--- a/OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierNull.c
++++ b/OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierNull.c
+@@ -16,18 +16,21 @@
+ @param[in] BlobName The name of the blob\r
+ @param[in] Buf The data of the blob\r
+ @param[in] BufSize The size of the blob in bytes\r
++ @param[in] FetchStatus The status of the fetch of this blob\r
+ \r
+- @retval EFI_SUCCESS The blob was verified successfully.\r
+- @retval EFI_ACCESS_DENIED The blob could not be verified, and therefore\r
+- should be considered non-secure.\r
++ @retval EFI_SUCCESS The blob was verified successfully or was not\r
++ found in the hash table.\r
++ @retval EFI_ACCESS_DENIED Kernel hashes not supported but the boot can\r
++ continue safely.\r
+ **/\r
+ EFI_STATUS\r
+ EFIAPI\r
+ VerifyBlob (\r
+ IN CONST CHAR16 *BlobName,\r
+ IN CONST VOID *Buf,\r
+- IN UINT32 BufSize\r
++ IN UINT32 BufSize,\r
++ IN EFI_STATUS FetchStatus\r
+ )\r
+ {\r
+- return EFI_SUCCESS;\r
++ return FetchStatus;\r
+ }\r
+diff --git a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+index 3c12085f6c..cf58c97cd2 100644
+--- a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
++++ b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+@@ -1042,6 +1042,7 @@ QemuKernelLoaderFsDxeEntrypoint (
+ KERNEL_BLOB *CurrentBlob;\r
+ KERNEL_BLOB *KernelBlob;\r
+ EFI_STATUS Status;\r
++ EFI_STATUS FetchStatus;\r
+ EFI_HANDLE FileSystemHandle;\r
+ EFI_HANDLE InitrdLoadFile2Handle;\r
+ \r
+@@ -1060,15 +1061,13 @@ QemuKernelLoaderFsDxeEntrypoint (
+ //\r
+ for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {\r
+ CurrentBlob = &mKernelBlob[BlobType];\r
+- Status = FetchBlob (CurrentBlob);\r
+- if (EFI_ERROR (Status)) {\r
+- goto FreeBlobs;\r
+- }\r
++ FetchStatus = FetchBlob (CurrentBlob);\r
+ \r
+ Status = VerifyBlob (\r
+ CurrentBlob->Name,\r
+ CurrentBlob->Data,\r
+- CurrentBlob->Size\r
++ CurrentBlob->Size,\r
++ FetchStatus\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeBlobs;\r
+--
+2.49.0
+
--- /dev/null
+From 459f5ffa24ae8574657c4105af0ff7dc30ac428d Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 14 Jan 2025 17:36:39 +0100
+Subject: [PATCH 01/10] OvmfPkg/QemuKernelLoaderFsDxe: rework direct kernel
+ boot filesystem
+
+Split KERNEL_BLOB struct into two:
+
+ * One (KERNEL_BLOB_ITEMS) static array describing how to load (unnamed)
+ blobs from fw_cfg.
+ * And one (KERNEL_BLOB) dynamically allocated linked list carrying the
+ data blobs for the pseudo filesystem.
+
+Also add some debug logging. Prefix most functions with 'QemuKernel'
+for consistency and easier log file grepping. Add some small helper
+functions.
+
+This refactoring prepares for loading blobs in other ways.
+No (intentional) change in filesystem protocol behavior.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+
+CVE: CVE-2025-2296
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/459f5ffa24ae8574657c4105af0ff7dc30ac428d]
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ .../QemuKernelLoaderFsDxe.c | 345 +++++++++++-------
+ 1 file changed, 205 insertions(+), 140 deletions(-)
+
+diff --git a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+index cf58c97cd2..7ad1b3828f 100644
+--- a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
++++ b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+@@ -31,13 +31,6 @@
+ //\r
+ // Static data that hosts the fw_cfg blobs and serves file requests.\r
+ //\r
+-typedef enum {\r
+- KernelBlobTypeKernel,\r
+- KernelBlobTypeInitrd,\r
+- KernelBlobTypeCommandLine,\r
+- KernelBlobTypeMax\r
+-} KERNEL_BLOB_TYPE;\r
+-\r
+ typedef struct {\r
+ CONST CHAR16 Name[8];\r
+ struct {\r
+@@ -45,11 +38,17 @@ typedef struct {
+ FIRMWARE_CONFIG_ITEM CONST DataKey;\r
+ UINT32 Size;\r
+ } FwCfgItem[2];\r
+- UINT32 Size;\r
+- UINT8 *Data;\r
+-} KERNEL_BLOB;\r
++} KERNEL_BLOB_ITEMS;\r
++\r
++typedef struct KERNEL_BLOB KERNEL_BLOB;\r
++struct KERNEL_BLOB {\r
++ CHAR16 Name[8];\r
++ UINT32 Size;\r
++ UINT8 *Data;\r
++ KERNEL_BLOB *Next;\r
++};\r
+ \r
+-STATIC KERNEL_BLOB mKernelBlob[KernelBlobTypeMax] = {\r
++STATIC KERNEL_BLOB_ITEMS mKernelBlobItems[] = {\r
+ {\r
+ L"kernel",\r
+ {\r
+@@ -69,7 +68,9 @@ STATIC KERNEL_BLOB mKernelBlob[KernelBlobTypeMax] = {
+ }\r
+ };\r
+ \r
+-STATIC UINT64 mTotalBlobBytes;\r
++STATIC KERNEL_BLOB *mKernelBlobs;\r
++STATIC UINT64 mKernelBlobCount;\r
++STATIC UINT64 mTotalBlobBytes;\r
+ \r
+ //\r
+ // Device path for the handle that incorporates our "EFI stub filesystem".\r
+@@ -117,7 +118,7 @@ STATIC EFI_TIME mInitTime;
+ typedef struct {\r
+ UINT64 Signature; // Carries STUB_FILE_SIG.\r
+ \r
+- KERNEL_BLOB_TYPE BlobType; // Index into mKernelBlob. KernelBlobTypeMax\r
++ KERNEL_BLOB *Blob; // Index into mKernelBlob. KernelBlobTypeMax\r
+ // denotes the root directory of the filesystem.\r
+ \r
+ UINT64 Position; // Byte position for regular files;\r
+@@ -177,7 +178,7 @@ typedef struct {
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileOpen (\r
++QemuKernelStubFileOpen (\r
+ IN EFI_FILE_PROTOCOL *This,\r
+ OUT EFI_FILE_PROTOCOL **NewHandle,\r
+ IN CHAR16 *FileName,\r
+@@ -196,7 +197,7 @@ StubFileOpen (
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileClose (\r
++QemuKernelStubFileClose (\r
+ IN EFI_FILE_PROTOCOL *This\r
+ )\r
+ {\r
+@@ -219,7 +220,7 @@ StubFileClose (
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileDelete (\r
++QemuKernelStubFileDelete (\r
+ IN EFI_FILE_PROTOCOL *This\r
+ )\r
+ {\r
+@@ -229,18 +230,17 @@ StubFileDelete (
+ \r
+ /**\r
+ Helper function that formats an EFI_FILE_INFO structure into the\r
+- user-allocated buffer, for any valid KERNEL_BLOB_TYPE value (including\r
+- KernelBlobTypeMax, which stands for the root directory).\r
++ user-allocated buffer, for any valid KERNEL_BLOB (including NULL,\r
++ which stands for the root directory).\r
+ \r
+ The interface follows the EFI_FILE_GET_INFO -- and for directories, the\r
+ EFI_FILE_READ -- interfaces.\r
+ \r
+- @param[in] BlobType The KERNEL_BLOB_TYPE value identifying the fw_cfg\r
++ @param[in] Blob The KERNEL_BLOB identifying the fw_cfg\r
+ blob backing the STUB_FILE that information is\r
+- being requested about. If BlobType equals\r
+- KernelBlobTypeMax, then information will be\r
+- provided about the root directory of the\r
+- filesystem.\r
++ being requested about. If Blob is NULL,\r
++ then information will be provided about the root\r
++ directory of the filesystem.\r
+ \r
+ @param[in,out] BufferSize On input, the size of Buffer. On output, the\r
+ amount of data returned in Buffer. In both cases,\r
+@@ -257,10 +257,10 @@ StubFileDelete (
+ **/\r
+ STATIC\r
+ EFI_STATUS\r
+-ConvertKernelBlobTypeToFileInfo (\r
+- IN KERNEL_BLOB_TYPE BlobType,\r
+- IN OUT UINTN *BufferSize,\r
+- OUT VOID *Buffer\r
++QemuKernelBlobTypeToFileInfo (\r
++ IN KERNEL_BLOB *Blob,\r
++ IN OUT UINTN *BufferSize,\r
++ OUT VOID *Buffer\r
+ )\r
+ {\r
+ CONST CHAR16 *Name;\r
+@@ -272,17 +272,16 @@ ConvertKernelBlobTypeToFileInfo (
+ EFI_FILE_INFO *FileInfo;\r
+ UINTN OriginalBufferSize;\r
+ \r
+- if (BlobType == KernelBlobTypeMax) {\r
++ if (Blob == NULL) {\r
+ //\r
+ // getting file info about the root directory\r
+ //\r
++ DEBUG ((DEBUG_INFO, "%a: file info: directory\n", __func__));\r
+ Name = L"\\";\r
+- FileSize = KernelBlobTypeMax;\r
++ FileSize = mKernelBlobCount;\r
+ Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;\r
+ } else {\r
+- CONST KERNEL_BLOB *Blob;\r
+-\r
+- Blob = &mKernelBlob[BlobType];\r
++ DEBUG ((DEBUG_INFO, "%a: file info: \"%s\"\n", __func__, Blob->Name));\r
+ Name = Blob->Name;\r
+ FileSize = Blob->Size;\r
+ Attribute = EFI_FILE_READ_ONLY;\r
+@@ -312,6 +311,23 @@ ConvertKernelBlobTypeToFileInfo (
+ return EFI_SUCCESS;\r
+ }\r
+ \r
++STATIC\r
++KERNEL_BLOB *\r
++FindKernelBlob (\r
++ CHAR16 *FileName\r
++ )\r
++{\r
++ KERNEL_BLOB *Blob;\r
++\r
++ for (Blob = mKernelBlobs; Blob != NULL; Blob = Blob->Next) {\r
++ if (StrCmp (FileName, Blob->Name) == 0) {\r
++ return Blob;\r
++ }\r
++ }\r
++\r
++ return NULL;\r
++}\r
++\r
+ /**\r
+ Reads data from a file, or continues scanning a directory.\r
+ \r
+@@ -349,25 +365,25 @@ ConvertKernelBlobTypeToFileInfo (
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileRead (\r
++QemuKernelStubFileRead (\r
+ IN EFI_FILE_PROTOCOL *This,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+ {\r
+- STUB_FILE *StubFile;\r
+- CONST KERNEL_BLOB *Blob;\r
+- UINT64 Left;\r
++ STUB_FILE *StubFile;\r
++ KERNEL_BLOB *Blob;\r
++ UINT64 Left, Pos;\r
+ \r
+ StubFile = STUB_FILE_FROM_FILE (This);\r
+ \r
+ //\r
+ // Scanning the root directory?\r
+ //\r
+- if (StubFile->BlobType == KernelBlobTypeMax) {\r
++ if (StubFile->Blob == NULL) {\r
+ EFI_STATUS Status;\r
+ \r
+- if (StubFile->Position == KernelBlobTypeMax) {\r
++ if (StubFile->Position == mKernelBlobCount) {\r
+ //\r
+ // Scanning complete.\r
+ //\r
+@@ -375,8 +391,16 @@ StubFileRead (
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+- Status = ConvertKernelBlobTypeToFileInfo (\r
+- (KERNEL_BLOB_TYPE)StubFile->Position,\r
++ for (Pos = 0, Blob = mKernelBlobs;\r
++ Pos < StubFile->Position;\r
++ Pos++, Blob = Blob->Next)\r
++ {\r
++ }\r
++\r
++ DEBUG ((DEBUG_INFO, "%a: file list: #%d \"%s\"\n", __func__, Pos, Blob->Name));\r
++\r
++ Status = QemuKernelBlobTypeToFileInfo (\r
++ Blob,\r
+ BufferSize,\r
+ Buffer\r
+ );\r
+@@ -391,7 +415,7 @@ StubFileRead (
+ //\r
+ // Reading a file.\r
+ //\r
+- Blob = &mKernelBlob[StubFile->BlobType];\r
++ Blob = StubFile->Blob;\r
+ if (StubFile->Position > Blob->Size) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+@@ -402,6 +426,7 @@ StubFileRead (
+ }\r
+ \r
+ if (Blob->Data != NULL) {\r
++ DEBUG ((DEBUG_INFO, "%a: file read: \"%s\", %d bytes\n", __func__, Blob->Name, *BufferSize));\r
+ CopyMem (Buffer, Blob->Data + StubFile->Position, *BufferSize);\r
+ }\r
+ \r
+@@ -435,7 +460,7 @@ StubFileRead (
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileWrite (\r
++QemuKernelStubFileWrite (\r
+ IN EFI_FILE_PROTOCOL *This,\r
+ IN OUT UINTN *BufferSize,\r
+ IN VOID *Buffer\r
+@@ -444,7 +469,7 @@ StubFileWrite (
+ STUB_FILE *StubFile;\r
+ \r
+ StubFile = STUB_FILE_FROM_FILE (This);\r
+- return (StubFile->BlobType == KernelBlobTypeMax) ?\r
++ return (StubFile->Blob == NULL) ?\r
+ EFI_UNSUPPORTED :\r
+ EFI_WRITE_PROTECTED;\r
+ }\r
+@@ -466,7 +491,7 @@ StubFileWrite (
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileGetPosition (\r
++QemuKernelStubFileGetPosition (\r
+ IN EFI_FILE_PROTOCOL *This,\r
+ OUT UINT64 *Position\r
+ )\r
+@@ -474,7 +499,7 @@ StubFileGetPosition (
+ STUB_FILE *StubFile;\r
+ \r
+ StubFile = STUB_FILE_FROM_FILE (This);\r
+- if (StubFile->BlobType == KernelBlobTypeMax) {\r
++ if (StubFile->Blob == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ \r
+@@ -501,7 +526,7 @@ StubFileGetPosition (
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileSetPosition (\r
++QemuKernelStubFileSetPosition (\r
+ IN EFI_FILE_PROTOCOL *This,\r
+ IN UINT64 Position\r
+ )\r
+@@ -511,7 +536,7 @@ StubFileSetPosition (
+ \r
+ StubFile = STUB_FILE_FROM_FILE (This);\r
+ \r
+- if (StubFile->BlobType == KernelBlobTypeMax) {\r
++ if (StubFile->Blob == NULL) {\r
+ if (Position == 0) {\r
+ //\r
+ // rewinding a directory scan is allowed\r
+@@ -526,7 +551,7 @@ StubFileSetPosition (
+ //\r
+ // regular file seek\r
+ //\r
+- Blob = &mKernelBlob[StubFile->BlobType];\r
++ Blob = StubFile->Blob;\r
+ if (Position == MAX_UINT64) {\r
+ //\r
+ // seek to end\r
+@@ -583,7 +608,7 @@ StubFileSetPosition (
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileGetInfo (\r
++QemuKernelStubFileGetInfo (\r
+ IN EFI_FILE_PROTOCOL *This,\r
+ IN EFI_GUID *InformationType,\r
+ IN OUT UINTN *BufferSize,\r
+@@ -596,8 +621,8 @@ StubFileGetInfo (
+ StubFile = STUB_FILE_FROM_FILE (This);\r
+ \r
+ if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
+- return ConvertKernelBlobTypeToFileInfo (\r
+- StubFile->BlobType,\r
++ return QemuKernelBlobTypeToFileInfo (\r
++ StubFile->Blob,\r
+ BufferSize,\r
+ Buffer\r
+ );\r
+@@ -685,7 +710,7 @@ StubFileGetInfo (
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileSetInfo (\r
++QemuKernelStubFileSetInfo (\r
+ IN EFI_FILE_PROTOCOL *This,\r
+ IN EFI_GUID *InformationType,\r
+ IN UINTN BufferSize,\r
+@@ -712,7 +737,7 @@ StubFileSetInfo (
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileFlush (\r
++QemuKernelStubFileFlush (\r
+ IN EFI_FILE_PROTOCOL *This\r
+ )\r
+ {\r
+@@ -724,16 +749,16 @@ StubFileFlush (
+ //\r
+ STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = {\r
+ EFI_FILE_PROTOCOL_REVISION, // revision 1\r
+- StubFileOpen,\r
+- StubFileClose,\r
+- StubFileDelete,\r
+- StubFileRead,\r
+- StubFileWrite,\r
+- StubFileGetPosition,\r
+- StubFileSetPosition,\r
+- StubFileGetInfo,\r
+- StubFileSetInfo,\r
+- StubFileFlush,\r
++ QemuKernelStubFileOpen,\r
++ QemuKernelStubFileClose,\r
++ QemuKernelStubFileDelete,\r
++ QemuKernelStubFileRead,\r
++ QemuKernelStubFileWrite,\r
++ QemuKernelStubFileGetPosition,\r
++ QemuKernelStubFileSetPosition,\r
++ QemuKernelStubFileGetInfo,\r
++ QemuKernelStubFileSetInfo,\r
++ QemuKernelStubFileFlush,\r
+ NULL, // OpenEx, revision 2\r
+ NULL, // ReadEx, revision 2\r
+ NULL, // WriteEx, revision 2\r
+@@ -743,7 +768,7 @@ STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = {
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileOpen (\r
++QemuKernelStubFileOpen (\r
+ IN EFI_FILE_PROTOCOL *This,\r
+ OUT EFI_FILE_PROTOCOL **NewHandle,\r
+ IN CHAR16 *FileName,\r
+@@ -752,7 +777,7 @@ StubFileOpen (
+ )\r
+ {\r
+ CONST STUB_FILE *StubFile;\r
+- UINTN BlobType;\r
++ KERNEL_BLOB *Blob;\r
+ STUB_FILE *NewStubFile;\r
+ \r
+ //\r
+@@ -774,21 +799,20 @@ StubFileOpen (
+ // Only the root directory supports opening files in it.\r
+ //\r
+ StubFile = STUB_FILE_FROM_FILE (This);\r
+- if (StubFile->BlobType != KernelBlobTypeMax) {\r
++ if (StubFile->Blob != NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ \r
+ //\r
+ // Locate the file.\r
+ //\r
+- for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {\r
+- if (StrCmp (FileName, mKernelBlob[BlobType].Name) == 0) {\r
+- break;\r
+- }\r
+- }\r
++ Blob = FindKernelBlob (FileName);\r
+ \r
+- if (BlobType == KernelBlobTypeMax) {\r
++ if (Blob == NULL) {\r
++ DEBUG ((DEBUG_INFO, "%a: file not found: \"%s\"\n", __func__, FileName));\r
+ return EFI_NOT_FOUND;\r
++ } else {\r
++ DEBUG ((DEBUG_INFO, "%a: file opened: \"%s\"\n", __func__, FileName));\r
+ }\r
+ \r
+ //\r
+@@ -800,7 +824,7 @@ StubFileOpen (
+ }\r
+ \r
+ NewStubFile->Signature = STUB_FILE_SIG;\r
+- NewStubFile->BlobType = (KERNEL_BLOB_TYPE)BlobType;\r
++ NewStubFile->Blob = Blob;\r
+ NewStubFile->Position = 0;\r
+ CopyMem (\r
+ &NewStubFile->File,\r
+@@ -842,7 +866,7 @@ StubFileOpen (
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-StubFileSystemOpenVolume (\r
++QemuKernelStubFileSystemOpenVolume (\r
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,\r
+ OUT EFI_FILE_PROTOCOL **Root\r
+ )\r
+@@ -855,7 +879,7 @@ StubFileSystemOpenVolume (
+ }\r
+ \r
+ StubFile->Signature = STUB_FILE_SIG;\r
+- StubFile->BlobType = KernelBlobTypeMax;\r
++ StubFile->Blob = NULL;\r
+ StubFile->Position = 0;\r
+ CopyMem (\r
+ &StubFile->File,\r
+@@ -869,13 +893,13 @@ StubFileSystemOpenVolume (
+ \r
+ STATIC CONST EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mFileSystem = {\r
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,\r
+- StubFileSystemOpenVolume\r
++ QemuKernelStubFileSystemOpenVolume\r
+ };\r
+ \r
+ STATIC\r
+ EFI_STATUS\r
+ EFIAPI\r
+-InitrdLoadFile2 (\r
++QemuKernelInitrdLoadFile2 (\r
+ IN EFI_LOAD_FILE2_PROTOCOL *This,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ IN BOOLEAN BootPolicy,\r
+@@ -883,8 +907,11 @@ InitrdLoadFile2 (
+ OUT VOID *Buffer OPTIONAL\r
+ )\r
+ {\r
+- CONST KERNEL_BLOB *InitrdBlob = &mKernelBlob[KernelBlobTypeInitrd];\r
++ KERNEL_BLOB *InitrdBlob;\r
+ \r
++ DEBUG ((DEBUG_INFO, "%a: initrd read\n", __func__));\r
++ InitrdBlob = FindKernelBlob (L"initrd");\r
++ ASSERT (InitrdBlob != NULL);\r
+ ASSERT (InitrdBlob->Size > 0);\r
+ \r
+ if (BootPolicy) {\r
+@@ -913,17 +940,33 @@ InitrdLoadFile2 (
+ }\r
+ \r
+ STATIC CONST EFI_LOAD_FILE2_PROTOCOL mInitrdLoadFile2 = {\r
+- InitrdLoadFile2,\r
++ QemuKernelInitrdLoadFile2,\r
+ };\r
+ \r
+ //\r
+ // Utility functions.\r
+ //\r
+ \r
++STATIC VOID\r
++QemuKernelChunkedRead (\r
++ UINT8 *Dest,\r
++ UINT32 Bytes\r
++ )\r
++{\r
++ UINT32 Chunk;\r
++\r
++ while (Bytes > 0) {\r
++ Chunk = (Bytes < SIZE_1MB) ? Bytes : SIZE_1MB;\r
++ QemuFwCfgReadBytes (Chunk, Dest);\r
++ Bytes -= Chunk;\r
++ Dest += Chunk;\r
++ }\r
++}\r
++\r
+ /**\r
+ Populate a blob in mKernelBlob.\r
+ \r
+- param[in,out] Blob Pointer to the KERNEL_BLOB element in mKernelBlob that is\r
++ param[in,out] Blob Pointer to the KERNEL_BLOB_ITEMS that is\r
+ to be filled from fw_cfg.\r
+ \r
+ @retval EFI_SUCCESS Blob has been populated. If fw_cfg reported a\r
+@@ -934,35 +977,46 @@ STATIC CONST EFI_LOAD_FILE2_PROTOCOL mInitrdLoadFile2 = {
+ **/\r
+ STATIC\r
+ EFI_STATUS\r
+-FetchBlob (\r
+- IN OUT KERNEL_BLOB *Blob\r
++QemuKernelFetchBlob (\r
++ IN KERNEL_BLOB_ITEMS *BlobItems\r
+ )\r
+ {\r
+- UINT32 Left;\r
+- UINTN Idx;\r
+- UINT8 *ChunkData;\r
++ UINT32 Size;\r
++ UINTN Idx;\r
++ UINT8 *ChunkData;\r
++ KERNEL_BLOB *Blob;\r
++ EFI_STATUS Status;\r
+ \r
+ //\r
+ // Read blob size.\r
+ //\r
+- Blob->Size = 0;\r
+- for (Idx = 0; Idx < ARRAY_SIZE (Blob->FwCfgItem); Idx++) {\r
+- if (Blob->FwCfgItem[Idx].SizeKey == 0) {\r
++ for (Size = 0, Idx = 0; Idx < ARRAY_SIZE (BlobItems->FwCfgItem); Idx++) {\r
++ if (BlobItems->FwCfgItem[Idx].SizeKey == 0) {\r
+ break;\r
+ }\r
+ \r
+- QemuFwCfgSelectItem (Blob->FwCfgItem[Idx].SizeKey);\r
+- Blob->FwCfgItem[Idx].Size = QemuFwCfgRead32 ();\r
+- Blob->Size += Blob->FwCfgItem[Idx].Size;\r
++ QemuFwCfgSelectItem (BlobItems->FwCfgItem[Idx].SizeKey);\r
++ BlobItems->FwCfgItem[Idx].Size = QemuFwCfgRead32 ();\r
++ Size += BlobItems->FwCfgItem[Idx].Size;\r
+ }\r
+ \r
+- if (Blob->Size == 0) {\r
++ if (Size == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
++ Blob = AllocatePool (sizeof (*Blob));\r
++ if (Blob->Data == NULL) {\r
++ return EFI_OUT_OF_RESOURCES;\r
++ }\r
++\r
++ ZeroMem (Blob, sizeof (*Blob));\r
++\r
+ //\r
+ // Read blob.\r
+ //\r
++ Status = StrCpyS (Blob->Name, sizeof (Blob->Name), BlobItems->Name);\r
++ ASSERT (!EFI_ERROR (Status));\r
++ Blob->Size = Size;\r
+ Blob->Data = AllocatePool (Blob->Size);\r
+ if (Blob->Data == NULL) {\r
+ DEBUG ((\r
+@@ -972,6 +1026,7 @@ FetchBlob (
+ (INT64)Blob->Size,\r
+ Blob->Name\r
+ ));\r
++ FreePool (Blob);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+@@ -984,34 +1039,48 @@ FetchBlob (
+ ));\r
+ \r
+ ChunkData = Blob->Data;\r
+- for (Idx = 0; Idx < ARRAY_SIZE (Blob->FwCfgItem); Idx++) {\r
+- if (Blob->FwCfgItem[Idx].DataKey == 0) {\r
++ for (Idx = 0; Idx < ARRAY_SIZE (BlobItems->FwCfgItem); Idx++) {\r
++ if (BlobItems->FwCfgItem[Idx].DataKey == 0) {\r
+ break;\r
+ }\r
+ \r
+- QemuFwCfgSelectItem (Blob->FwCfgItem[Idx].DataKey);\r
++ QemuFwCfgSelectItem (BlobItems->FwCfgItem[Idx].DataKey);\r
++ QemuKernelChunkedRead (ChunkData, BlobItems->FwCfgItem[Idx].Size);\r
++ ChunkData += BlobItems->FwCfgItem[Idx].Size;\r
++ }\r
+ \r
+- Left = Blob->FwCfgItem[Idx].Size;\r
+- while (Left > 0) {\r
+- UINT32 Chunk;\r
++ Blob->Next = mKernelBlobs;\r
++ mKernelBlobs = Blob;\r
++ mKernelBlobCount++;\r
++ mTotalBlobBytes += Blob->Size;\r
++ return EFI_SUCCESS;\r
++}\r
+ \r
+- Chunk = (Left < SIZE_1MB) ? Left : SIZE_1MB;\r
+- QemuFwCfgReadBytes (Chunk, ChunkData + Blob->FwCfgItem[Idx].Size - Left);\r
+- Left -= Chunk;\r
+- DEBUG ((\r
+- DEBUG_VERBOSE,\r
+- "%a: %Ld bytes remaining for \"%s\" (%d)\n",\r
+- __func__,\r
+- (INT64)Left,\r
+- Blob->Name,\r
+- (INT32)Idx\r
+- ));\r
+- }\r
++STATIC\r
++EFI_STATUS\r
++QemuKernelVerifyBlob (\r
++ CHAR16 *FileName,\r
++ EFI_STATUS FetchStatus\r
++ )\r
++{\r
++ KERNEL_BLOB *Blob;\r
++ EFI_STATUS Status;\r
+ \r
+- ChunkData += Blob->FwCfgItem[Idx].Size;\r
++ if ((StrCmp (FileName, L"kernel") != 0) &&\r
++ (StrCmp (FileName, L"initrd") != 0) &&\r
++ (StrCmp (FileName, L"cmdline") != 0))\r
++ {\r
++ return EFI_SUCCESS;\r
+ }\r
+ \r
+- return EFI_SUCCESS;\r
++ Blob = FindKernelBlob (FileName);\r
++ Status = VerifyBlob (\r
++ FileName,\r
++ Blob ? Blob->Data : NULL,\r
++ Blob ? Blob->Size : 0,\r
++ FetchStatus\r
++ );\r
++ return Status;\r
+ }\r
+ \r
+ //\r
+@@ -1038,13 +1107,13 @@ QemuKernelLoaderFsDxeEntrypoint (
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+ {\r
+- UINTN BlobType;\r
+- KERNEL_BLOB *CurrentBlob;\r
+- KERNEL_BLOB *KernelBlob;\r
+- EFI_STATUS Status;\r
+- EFI_STATUS FetchStatus;\r
+- EFI_HANDLE FileSystemHandle;\r
+- EFI_HANDLE InitrdLoadFile2Handle;\r
++ UINTN BlobIdx;\r
++ KERNEL_BLOB_ITEMS *BlobItems;\r
++ KERNEL_BLOB *Blob;\r
++ EFI_STATUS Status;\r
++ EFI_STATUS FetchStatus;\r
++ EFI_HANDLE FileSystemHandle;\r
++ EFI_HANDLE InitrdLoadFile2Handle;\r
+ \r
+ if (!QemuFwCfgIsAvailable ()) {\r
+ return EFI_NOT_FOUND;\r
+@@ -1059,26 +1128,22 @@ QemuKernelLoaderFsDxeEntrypoint (
+ //\r
+ // Fetch all blobs.\r
+ //\r
+- for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {\r
+- CurrentBlob = &mKernelBlob[BlobType];\r
+- FetchStatus = FetchBlob (CurrentBlob);\r
+-\r
+- Status = VerifyBlob (\r
+- CurrentBlob->Name,\r
+- CurrentBlob->Data,\r
+- CurrentBlob->Size,\r
++ for (BlobIdx = 0; BlobIdx < ARRAY_SIZE (mKernelBlobItems); ++BlobIdx) {\r
++ BlobItems = &mKernelBlobItems[BlobIdx];\r
++ FetchStatus = QemuKernelFetchBlob (BlobItems);\r
++\r
++ Status = QemuKernelVerifyBlob (\r
++ (CHAR16 *)BlobItems->Name,\r
+ FetchStatus\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeBlobs;\r
+ }\r
+-\r
+- mTotalBlobBytes += CurrentBlob->Size;\r
+ }\r
+ \r
+- KernelBlob = &mKernelBlob[KernelBlobTypeKernel];\r
+-\r
+- if (KernelBlob->Data == NULL) {\r
++ Blob = FindKernelBlob (L"kernel");\r
++ if (Blob == NULL) {\r
++ DEBUG ((DEBUG_INFO, "%a: no kernel present -> quit\n", __func__));\r
+ Status = EFI_NOT_FOUND;\r
+ goto FreeBlobs;\r
+ }\r
+@@ -1106,7 +1171,9 @@ QemuKernelLoaderFsDxeEntrypoint (
+ goto FreeBlobs;\r
+ }\r
+ \r
+- if (KernelBlob[KernelBlobTypeInitrd].Size > 0) {\r
++ Blob = FindKernelBlob (L"initrd");\r
++ if (Blob != NULL) {\r
++ DEBUG ((DEBUG_INFO, "%a: initrd setup\n", __func__));\r
+ InitrdLoadFile2Handle = NULL;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &InitrdLoadFile2Handle,\r
+@@ -1141,13 +1208,11 @@ UninstallFileSystemHandle:
+ ASSERT_EFI_ERROR (Status);\r
+ \r
+ FreeBlobs:\r
+- while (BlobType > 0) {\r
+- CurrentBlob = &mKernelBlob[--BlobType];\r
+- if (CurrentBlob->Data != NULL) {\r
+- FreePool (CurrentBlob->Data);\r
+- CurrentBlob->Size = 0;\r
+- CurrentBlob->Data = NULL;\r
+- }\r
++ while (mKernelBlobs != NULL) {\r
++ Blob = mKernelBlobs;\r
++ mKernelBlobs = Blob->Next;\r
++ FreePool (Blob->Data);\r
++ FreePool (Blob);\r
+ }\r
+ \r
+ return Status;\r
+--
+2.49.0
+
--- /dev/null
+From 20df7c42bd446fe725bfc78cdb40577456c421d8 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Wed, 15 Jan 2025 00:29:52 +0100
+Subject: [PATCH 02/10] OvmfPkg/QemuKernelLoaderFsDxe: add support for named
+ blobs
+
+Load all named fw_cfg blobs with "etc/boot/" prefix into the pseudo
+filesystem.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+
+CVE: CVE-2025-2296
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/20df7c42bd446fe725bfc78cdb40577456c421d8]
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ .../QemuKernelLoaderFsDxe.c | 94 ++++++++++++++++---
+ .../QemuKernelLoaderFsDxe.inf | 1 +
+ 2 files changed, 84 insertions(+), 11 deletions(-)
+
+diff --git a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+index 7ad1b3828f..1f63adda0b 100644
+--- a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
++++ b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+@@ -21,6 +21,7 @@
+ #include <Library/DebugLib.h>\r
+ #include <Library/DevicePathLib.h>\r
+ #include <Library/MemoryAllocationLib.h>\r
++#include <Library/PrintLib.h>\r
+ #include <Library/QemuFwCfgLib.h>\r
+ #include <Library/UefiBootServicesTableLib.h>\r
+ #include <Library/UefiRuntimeServicesTableLib.h>\r
+@@ -32,12 +33,12 @@
+ // Static data that hosts the fw_cfg blobs and serves file requests.\r
+ //\r
+ typedef struct {\r
+- CONST CHAR16 Name[8];\r
++ CHAR16 Name[8];\r
+ struct {\r
+- FIRMWARE_CONFIG_ITEM CONST SizeKey;\r
+- FIRMWARE_CONFIG_ITEM CONST DataKey;\r
+- UINT32 Size;\r
+- } FwCfgItem[2];\r
++ FIRMWARE_CONFIG_ITEM SizeKey;\r
++ FIRMWARE_CONFIG_ITEM DataKey;\r
++ UINT32 Size;\r
++ } FwCfgItem[2];\r
+ } KERNEL_BLOB_ITEMS;\r
+ \r
+ typedef struct KERNEL_BLOB KERNEL_BLOB;\r
+@@ -989,15 +990,23 @@ QemuKernelFetchBlob (
+ \r
+ //\r
+ // Read blob size.\r
++ // Size != 0 -> use size as-is\r
++ // SizeKey != 0 -> read size from fw_cfg\r
++ // both are 0 -> unused entry\r
+ //\r
+ for (Size = 0, Idx = 0; Idx < ARRAY_SIZE (BlobItems->FwCfgItem); Idx++) {\r
+- if (BlobItems->FwCfgItem[Idx].SizeKey == 0) {\r
++ if ((BlobItems->FwCfgItem[Idx].SizeKey == 0) &&\r
++ (BlobItems->FwCfgItem[Idx].Size == 0))\r
++ {\r
+ break;\r
+ }\r
+ \r
+- QemuFwCfgSelectItem (BlobItems->FwCfgItem[Idx].SizeKey);\r
+- BlobItems->FwCfgItem[Idx].Size = QemuFwCfgRead32 ();\r
+- Size += BlobItems->FwCfgItem[Idx].Size;\r
++ if (BlobItems->FwCfgItem[Idx].SizeKey) {\r
++ QemuFwCfgSelectItem (BlobItems->FwCfgItem[Idx].SizeKey);\r
++ BlobItems->FwCfgItem[Idx].Size = QemuFwCfgRead32 ();\r
++ }\r
++\r
++ Size += BlobItems->FwCfgItem[Idx].Size;\r
+ }\r
+ \r
+ if (Size == 0) {\r
+@@ -1083,6 +1092,55 @@ QemuKernelVerifyBlob (
+ return Status;\r
+ }\r
+ \r
++STATIC\r
++EFI_STATUS\r
++QemuKernelFetchNamedBlobs (\r
++ VOID\r
++ )\r
++{\r
++ struct {\r
++ UINT32 FileSize;\r
++ UINT16 FileSelect;\r
++ UINT16 Reserved;\r
++ CHAR8 FileName[QEMU_FW_CFG_FNAME_SIZE];\r
++ } *DirEntry;\r
++ KERNEL_BLOB_ITEMS Items;\r
++ EFI_STATUS Status;\r
++ EFI_STATUS FetchStatus;\r
++ UINT32 Count;\r
++ UINT32 Idx;\r
++\r
++ QemuFwCfgSelectItem (QemuFwCfgItemFileDir);\r
++ Count = SwapBytes32 (QemuFwCfgRead32 ());\r
++\r
++ DirEntry = AllocatePool (sizeof (*DirEntry) * Count);\r
++ QemuFwCfgReadBytes (sizeof (*DirEntry) * Count, DirEntry);\r
++\r
++ for (Idx = 0; Idx < Count; ++Idx) {\r
++ if (AsciiStrnCmp (DirEntry[Idx].FileName, "etc/boot/", 9) != 0) {\r
++ continue;\r
++ }\r
++\r
++ ZeroMem (&Items, sizeof (Items));\r
++ UnicodeSPrint (Items.Name, sizeof (Items.Name), L"%a", DirEntry[Idx].FileName + 9);\r
++ Items.FwCfgItem[0].DataKey = SwapBytes16 (DirEntry[Idx].FileSelect);\r
++ Items.FwCfgItem[0].Size = SwapBytes32 (DirEntry[Idx].FileSize);\r
++\r
++ FetchStatus = QemuKernelFetchBlob (&Items);\r
++ Status = QemuKernelVerifyBlob (\r
++ (CHAR16 *)Items.Name,\r
++ FetchStatus\r
++ );\r
++ if (EFI_ERROR (Status)) {\r
++ FreePool (DirEntry);\r
++ return Status;\r
++ }\r
++ }\r
++\r
++ FreePool (DirEntry);\r
++ return EFI_SUCCESS;\r
++}\r
++\r
+ //\r
+ // The entry point of the feature.\r
+ //\r
+@@ -1126,10 +1184,24 @@ QemuKernelLoaderFsDxeEntrypoint (
+ }\r
+ \r
+ //\r
+- // Fetch all blobs.\r
++ // Fetch named blobs.\r
+ //\r
++ DEBUG ((DEBUG_INFO, "%a: named blobs (etc/boot/*)\n", __func__));\r
++ Status = QemuKernelFetchNamedBlobs ();\r
++ if (EFI_ERROR (Status)) {\r
++ goto FreeBlobs;\r
++ }\r
++\r
++ //\r
++ // Fetch traditional blobs.\r
++ //\r
++ DEBUG ((DEBUG_INFO, "%a: traditional blobs\n", __func__));\r
+ for (BlobIdx = 0; BlobIdx < ARRAY_SIZE (mKernelBlobItems); ++BlobIdx) {\r
+- BlobItems = &mKernelBlobItems[BlobIdx];\r
++ BlobItems = &mKernelBlobItems[BlobIdx];\r
++ if (FindKernelBlob (BlobItems->Name)) {\r
++ continue;\r
++ }\r
++\r
+ FetchStatus = QemuKernelFetchBlob (BlobItems);\r
+ \r
+ Status = QemuKernelVerifyBlob (\r
+diff --git a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf
+index 7b35adb8e0..a2f44bbca1 100644
+--- a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf
++++ b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf
+@@ -30,6 +30,7 @@
+ DebugLib\r
+ DevicePathLib\r
+ MemoryAllocationLib\r
++ PrintLib\r
+ QemuFwCfgLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+--
+2.49.0
+
--- /dev/null
+From adf385ecab69631952bdc8b774ebd77e82b94a00 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Thu, 16 Jan 2025 15:42:13 +0100
+Subject: [PATCH 03/10] OvmfPkg/QemuKernelLoaderFsDxe: allow longer file names
+
+QEMU_FW_CFG_FNAME_SIZE is 56. 'etc/boot/' prefix is minus 9. Add one
+for the terminating '\0'. Effective max size is 48.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+
+CVE: CVE-2025-2296
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/adf385ecab69631952bdc8b774ebd77e82b94a00]
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+index 1f63adda0b..0947b6bf2d 100644
+--- a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
++++ b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+@@ -33,7 +33,7 @@
+ // Static data that hosts the fw_cfg blobs and serves file requests.\r
+ //\r
+ typedef struct {\r
+- CHAR16 Name[8];\r
++ CHAR16 Name[48];\r
+ struct {\r
+ FIRMWARE_CONFIG_ITEM SizeKey;\r
+ FIRMWARE_CONFIG_ITEM DataKey;\r
+@@ -43,7 +43,7 @@ typedef struct {
+ \r
+ typedef struct KERNEL_BLOB KERNEL_BLOB;\r
+ struct KERNEL_BLOB {\r
+- CHAR16 Name[8];\r
++ CHAR16 Name[48];\r
+ UINT32 Size;\r
+ UINT8 *Data;\r
+ KERNEL_BLOB *Next;\r
+--
+2.49.0
+
--- /dev/null
+From 1111e9fe7078eed9e5c50e1808776ee40a629e16 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Thu, 16 Jan 2025 15:52:54 +0100
+Subject: [PATCH 04/10] OvmfPkg/QemuKernelLoaderFsDxe: drop bogus assert
+
+Triggers when trying to get root directory info.
+Reproducer:
+ * Use qemu -kernel with something edk2 can not load.
+ * When dropped into the efi shell try inspect the file system.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+
+CVE: CVE-2025-2296
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1111e9fe7078eed9e5c50e1808776ee40a629e16]
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+index 0947b6bf2d..3e1a876bf0 100644
+--- a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
++++ b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+@@ -290,7 +290,6 @@ QemuKernelBlobTypeToFileInfo (
+ \r
+ NameSize = (StrLen (Name) + 1) * 2;\r
+ FileInfoSize = OFFSET_OF (EFI_FILE_INFO, FileName) + NameSize;\r
+- ASSERT (FileInfoSize >= sizeof *FileInfo);\r
+ \r
+ OriginalBufferSize = *BufferSize;\r
+ *BufferSize = FileInfoSize;\r
+--
+2.49.0
+
--- /dev/null
+From 46ae4e4b9574530e5081e98af0495d6f6d28379f Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Thu, 16 Jan 2025 16:03:01 +0100
+Subject: [PATCH 05/10] OvmfPkg/QemuKernelLoaderFsDxe: accept absolute paths
+
+EFI shell looks for "\startup.nsh".
+Try "-fw_cfg name=etc/boot/startup.nsh,string='echo hello'" ;)
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+
+CVE: CVE-2025-2296
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/46ae4e4b9574530e5081e98af0495d6f6d28379f]
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+index 3e1a876bf0..5b90420dad 100644
+--- a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
++++ b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+@@ -806,6 +806,11 @@ QemuKernelStubFileOpen (
+ //\r
+ // Locate the file.\r
+ //\r
++ if (FileName[0] == '\\') {\r
++ // also accept absolute paths, i.e. '\kernel' for 'kernel'\r
++ FileName++;\r
++ }\r
++\r
+ Blob = FindKernelBlob (FileName);\r
+ \r
+ if (Blob == NULL) {\r
+--
+2.49.0
+
--- /dev/null
+From c45051450efbdae4a38f07998b3e7b77abe7173a Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Mon, 20 Jan 2025 11:28:37 +0100
+Subject: [PATCH 06/10] OvmfPkg/QemuKernelLoaderFsDxe: don't quit when named
+ blobs are present
+
+Allows to use the qemu kernel loader pseudo file system for other
+purposes than loading a linux kernel (or efi binary). Passing
+startup.nsh for EFI shell is one example.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+
+CVE: CVE-2025-2296
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/c45051450efbdae4a38f07998b3e7b77abe7173a]
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+index 5b90420dad..add914daa8 100644
+--- a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
++++ b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
+@@ -71,6 +71,7 @@ STATIC KERNEL_BLOB_ITEMS mKernelBlobItems[] = {
+ \r
+ STATIC KERNEL_BLOB *mKernelBlobs;\r
+ STATIC UINT64 mKernelBlobCount;\r
++STATIC UINT64 mKernelNamedBlobCount;\r
+ STATIC UINT64 mTotalBlobBytes;\r
+ \r
+ //\r
+@@ -1139,6 +1140,8 @@ QemuKernelFetchNamedBlobs (
+ FreePool (DirEntry);\r
+ return Status;\r
+ }\r
++\r
++ mKernelNamedBlobCount++;\r
+ }\r
+ \r
+ FreePool (DirEntry);\r
+@@ -1218,8 +1221,8 @@ QemuKernelLoaderFsDxeEntrypoint (
+ }\r
+ \r
+ Blob = FindKernelBlob (L"kernel");\r
+- if (Blob == NULL) {\r
+- DEBUG ((DEBUG_INFO, "%a: no kernel present -> quit\n", __func__));\r
++ if ((Blob == NULL) && (mKernelNamedBlobCount == 0)) {\r
++ DEBUG ((DEBUG_INFO, "%a: no kernel and no named blobs present -> quit\n", __func__));\r
+ Status = EFI_NOT_FOUND;\r
+ goto FreeBlobs;\r
+ }\r
+--
+2.49.0
+
--- /dev/null
+From 3da39f2cb681eb69f4eef54acd4b25d25cd7103d Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Wed, 10 Apr 2024 17:25:03 +0200
+Subject: [PATCH 07/10] OvmfPkg/X86QemuLoadImageLib: 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/3da39f2cb681eb69f4eef54acd4b25d25cd7103d]
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ .../X86QemuLoadImageLib/X86QemuLoadImageLib.c | 56 ++++++++++++++++++-
+ 1 file changed, 54 insertions(+), 2 deletions(-)
+
+diff --git a/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c b/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c
+index a7ab43ca74..e4dbc2dc7e 100644
+--- a/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c
++++ b/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c
+@@ -57,6 +57,25 @@ STATIC CONST KERNEL_VENMEDIA_FILE_DEVPATH mKernelDevicePath = {
+ }\r
+ };\r
+ \r
++STATIC CONST KERNEL_VENMEDIA_FILE_DEVPATH mShimDevicePath = {\r
++ {\r
++ {\r
++ MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,\r
++ { sizeof (VENDOR_DEVICE_PATH) }\r
++ },\r
++ QEMU_KERNEL_LOADER_FS_MEDIA_GUID\r
++ }, {\r
++ {\r
++ MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP,\r
++ { sizeof (KERNEL_FILE_DEVPATH) }\r
++ },\r
++ L"shim",\r
++ }, {\r
++ END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
++ { sizeof (EFI_DEVICE_PATH_PROTOCOL) }\r
++ }\r
++};\r
++\r
+ STATIC\r
+ VOID\r
+ FreeLegacyImage (\r
+@@ -339,6 +358,7 @@ QemuLoadKernelImage (
+ UINTN CommandLineSize;\r
+ CHAR8 *CommandLine;\r
+ UINTN InitrdSize;\r
++ BOOLEAN Shim;\r
+ \r
+ //\r
+ // Redundant assignment to work around GCC48/GCC49 limitations.\r
+@@ -351,11 +371,35 @@ QemuLoadKernelImage (
+ Status = gBS->LoadImage (\r
+ FALSE, // BootPolicy: exact match required\r
+ gImageHandle, // ParentImageHandle\r
+- (EFI_DEVICE_PATH_PROTOCOL *)&mKernelDevicePath,\r
++ (EFI_DEVICE_PATH_PROTOCOL *)&mShimDevicePath,\r
+ NULL, // SourceBuffer\r
+ 0, // SourceSize\r
+ &KernelImageHandle\r
+ );\r
++ if (Status == EFI_SUCCESS) {\r
++ Shim = TRUE;\r
++ DEBUG ((DEBUG_INFO, "%a: booting via shim\n", __func__));\r
++ } else {\r
++ Shim = FALSE;\r
++ if (Status == EFI_SECURITY_VIOLATION) {\r
++ gBS->UnloadImage (KernelImageHandle);\r
++ }\r
++\r
++ if (Status != EFI_NOT_FOUND) {\r
++ DEBUG ((DEBUG_INFO, "%a: LoadImage(shim): %r\n", __func__, Status));\r
++ return Status;\r
++ }\r
++\r
++ Status = gBS->LoadImage (\r
++ FALSE, // BootPolicy: exact match required\r
++ gImageHandle, // ParentImageHandle\r
++ (EFI_DEVICE_PATH_PROTOCOL *)&mKernelDevicePath,\r
++ NULL, // SourceBuffer\r
++ 0, // SourceSize\r
++ &KernelImageHandle\r
++ );\r
++ }\r
++\r
+ switch (Status) {\r
+ case EFI_SUCCESS:\r
+ break;\r
+@@ -465,6 +509,13 @@ QemuLoadKernelImage (
+ KernelLoadedImage->LoadOptionsSize += sizeof (L" initrd=initrd") - 2;\r
+ }\r
+ \r
++ if (Shim) {\r
++ //\r
++ // Prefix 'kernel ' in UTF-16.\r
++ //\r
++ KernelLoadedImage->LoadOptionsSize += sizeof (L"kernel ") - 2;\r
++ }\r
++\r
+ if (KernelLoadedImage->LoadOptionsSize == 0) {\r
+ KernelLoadedImage->LoadOptions = NULL;\r
+ } else {\r
+@@ -485,7 +536,8 @@ QemuLoadKernelImage (
+ UnicodeSPrintAsciiFormat (\r
+ KernelLoadedImage->LoadOptions,\r
+ KernelLoadedImage->LoadOptionsSize,\r
+- "%a%a",\r
++ "%a%a%a",\r
++ (Shim == FALSE) ? "" : "kernel ",\r
+ (CommandLineSize == 0) ? "" : CommandLine,\r
+ (InitrdSize == 0) ? "" : " initrd=initrd"\r
+ );\r
+--
+2.49.0
+
--- /dev/null
+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 = {
+ }\r
+ };\r
+ \r
++STATIC CONST KERNEL_VENMEDIA_FILE_DEVPATH mShimDevicePath = {\r
++ {\r
++ {\r
++ MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,\r
++ { sizeof (VENDOR_DEVICE_PATH) }\r
++ },\r
++ QEMU_KERNEL_LOADER_FS_MEDIA_GUID\r
++ }, {\r
++ {\r
++ MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP,\r
++ { sizeof (KERNEL_FILE_DEVPATH) }\r
++ },\r
++ L"shim",\r
++ }, {\r
++ END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
++ { sizeof (EFI_DEVICE_PATH_PROTOCOL) }\r
++ }\r
++};\r
++\r
+ STATIC CONST SINGLE_VENMEDIA_NODE_DEVPATH mQemuKernelLoaderFsDevicePath = {\r
+ {\r
+ {\r
+@@ -174,6 +193,7 @@ QemuLoadKernelImage (
+ UINTN CommandLineSize;\r
+ CHAR8 *CommandLine;\r
+ UINTN InitrdSize;\r
++ BOOLEAN Shim;\r
+ \r
+ //\r
+ // Load the image. This should call back into the QEMU EFI loader file system.\r
+@@ -181,11 +201,35 @@ QemuLoadKernelImage (
+ Status = gBS->LoadImage (\r
+ FALSE, // BootPolicy: exact match required\r
+ gImageHandle, // ParentImageHandle\r
+- (EFI_DEVICE_PATH_PROTOCOL *)&mKernelDevicePath,\r
++ (EFI_DEVICE_PATH_PROTOCOL *)&mShimDevicePath,\r
+ NULL, // SourceBuffer\r
+ 0, // SourceSize\r
+ &KernelImageHandle\r
+ );\r
++ if (Status == EFI_SUCCESS) {\r
++ Shim = TRUE;\r
++ DEBUG ((DEBUG_INFO, "%a: booting via shim\n", __func__));\r
++ } else {\r
++ Shim = FALSE;\r
++ if (Status == EFI_SECURITY_VIOLATION) {\r
++ gBS->UnloadImage (KernelImageHandle);\r
++ }\r
++\r
++ if (Status != EFI_NOT_FOUND) {\r
++ DEBUG ((DEBUG_INFO, "%a: LoadImage(shim): %r\n", __func__, Status));\r
++ return Status;\r
++ }\r
++\r
++ Status = gBS->LoadImage (\r
++ FALSE, // BootPolicy: exact match required\r
++ gImageHandle, // ParentImageHandle\r
++ (EFI_DEVICE_PATH_PROTOCOL *)&mKernelDevicePath,\r
++ NULL, // SourceBuffer\r
++ 0, // SourceSize\r
++ &KernelImageHandle\r
++ );\r
++ }\r
++\r
+ switch (Status) {\r
+ case EFI_SUCCESS:\r
+ break;\r
+@@ -303,6 +347,13 @@ QemuLoadKernelImage (
+ KernelLoadedImage->LoadOptionsSize += sizeof (L" initrd=initrd") - 2;\r
+ }\r
+ \r
++ if (Shim) {\r
++ //\r
++ // Prefix 'kernel ' in UTF-16.\r
++ //\r
++ KernelLoadedImage->LoadOptionsSize += sizeof (L"kernel ") - 2;\r
++ }\r
++\r
+ if (KernelLoadedImage->LoadOptionsSize == 0) {\r
+ KernelLoadedImage->LoadOptions = NULL;\r
+ } else {\r
+@@ -323,7 +374,8 @@ QemuLoadKernelImage (
+ UnicodeSPrintAsciiFormat (\r
+ KernelLoadedImage->LoadOptions,\r
+ KernelLoadedImage->LoadOptionsSize,\r
+- "%a%a",\r
++ "%a%a%a",\r
++ (Shim == FALSE) ? "" : "kernel ",\r
+ (CommandLineSize == 0) ? "" : CommandLine,\r
+ (InitrdSize == 0) ? "" : " initrd=initrd"\r
+ );\r
+--
+2.49.0
+
--- /dev/null
+From 1549bf11cc94b135b6ad8fa5ebc34bdf7c18ba9c Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Tue, 17 Dec 2024 09:59:21 +0100
+Subject: [PATCH 09/10] OvmfPkg/X86QemuLoadImageLib: make legacy loader
+ configurable.
+
+Add the 'opt/org.tianocore/EnableLegacyLoader' FwCfg option to
+enable/disable the insecure legacy linux kernel loader.
+
+For now this is enabled by default. Probably the default will be
+flipped to disabled at some point in the future.
+
+Also print a warning to the screen in case the linux kernel secure
+boot verification has failed.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+
+CVE: CVE-2025-2296
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1549bf11cc94b135b6ad8fa5ebc34bdf7c18ba9c]
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ .../X86QemuLoadImageLib/X86QemuLoadImageLib.c | 48 ++++++++++++++++---
+ .../X86QemuLoadImageLib.inf | 1 +
+ 2 files changed, 42 insertions(+), 7 deletions(-)
+
+diff --git a/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c b/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c
+index e4dbc2dc7e..2d610f6bd3 100644
+--- a/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c
++++ b/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c
+@@ -19,8 +19,10 @@
+ #include <Library/MemoryAllocationLib.h>\r
+ #include <Library/PrintLib.h>\r
+ #include <Library/QemuFwCfgLib.h>\r
++#include <Library/QemuFwCfgSimpleParserLib.h>\r
+ #include <Library/QemuLoadImageLib.h>\r
+ #include <Library/UefiBootServicesTableLib.h>\r
++#include <Library/UefiLib.h>\r
+ #include <Protocol/DevicePath.h>\r
+ #include <Protocol/LoadedImage.h>\r
+ #include <Protocol/OvmfLoadedX86LinuxKernel.h>\r
+@@ -421,13 +423,45 @@ QemuLoadKernelImage (
+ // Fall through\r
+ //\r
+ case EFI_ACCESS_DENIED:\r
+- //\r
+- // We are running with UEFI secure boot enabled, and the image failed to\r
+- // authenticate. For compatibility reasons, we fall back to the legacy\r
+- // loader in this case.\r
+- //\r
+- // Fall through\r
+- //\r
++ //\r
++ // We are running with UEFI secure boot enabled, and the image failed to\r
++ // authenticate. For compatibility reasons, we fall back to the legacy\r
++ // loader in this case (unless disabled via fw_cfg).\r
++ //\r
++ {\r
++ EFI_STATUS RetStatus;\r
++ BOOLEAN Enabled = TRUE;\r
++\r
++ AsciiPrint (\r
++ "OVMF: Secure boot image verification failed. Consider using the '-shim'\n"\r
++ "OVMF: command line switch for qemu (available in version 10.0 + newer).\n"\r
++ "\n"\r
++ );\r
++\r
++ RetStatus = QemuFwCfgParseBool (\r
++ "opt/org.tianocore/EnableLegacyLoader",\r
++ &Enabled\r
++ );\r
++ if (EFI_ERROR (RetStatus)) {\r
++ Enabled = TRUE;\r
++ }\r
++\r
++ if (!Enabled) {\r
++ AsciiPrint (\r
++ "OVMF: Fallback to insecure legacy linux kernel loader is disabled.\n"\r
++ "\n"\r
++ );\r
++ return EFI_ACCESS_DENIED;\r
++ } else {\r
++ AsciiPrint (\r
++ "OVMF: Using legacy linux kernel loader (insecure and deprecated).\n"\r
++ "\n"\r
++ );\r
++ //\r
++ // Fall through\r
++ //\r
++ }\r
++ }\r
+ case EFI_UNSUPPORTED:\r
+ //\r
+ // The image is not natively supported or cross-type supported. Let's try\r
+diff --git a/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.inf b/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.inf
+index c7ec041cb7..09babd3be8 100644
+--- a/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.inf
++++ b/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.inf
+@@ -33,6 +33,7 @@
+ LoadLinuxLib\r
+ PrintLib\r
+ QemuFwCfgLib\r
++ QemuFwCfgSimpleParserLib\r
+ ReportStatusCodeLib\r
+ UefiBootServicesTableLib\r
+ \r
+--
+2.49.0
+
file://0006-BaseTools-StringFuncs-fix-gcc-16-warning.patch \
file://0007-BaseTools-EfiRom-fix-compiler-warning.patch \
file://0008-BaseTools-Pccts-set-C-standard.patch \
+ file://0001-AmdSev-Halt-on-failed-blob-allocation.patch \
+ file://CVE-2025-2296-1.patch \
+ file://CVE-2025-2296-2.patch \
+ file://CVE-2025-2296-3.patch \
+ file://CVE-2025-2296-4.patch \
+ file://CVE-2025-2296-5.patch \
+ file://CVE-2025-2296-6.patch \
+ file://CVE-2025-2296-7.patch \
+ file://CVE-2025-2296-8.patch \
+ file://CVE-2025-2296-9.patch \
"
PV = "edk2-stable202402"