From f816957ff6e478bc3e2cbc24bd805e790d0690bb Mon Sep 17 00:00:00 2001 From: Renbo Date: Tue, 28 May 2024 14:12:21 +0800 Subject: [PATCH 1/4] update to edk2-20220126gitbb1bba3d77-13.src.rpm Signed-off-by: Renbo --- ...g-Add-StandardSignatureIsHygonGenuin.patch | 140 - ...g-LocalApicLib-Exclude-second-SendIp.patch | 83 - ...dd-CSV-secure-call-library-on-Hygon-.patch | 672 ---- ...cg-Add-CsvLib-for-TpmMmioSevDecryptP.patch | 27 - ...esetVector-Support-CSV-in-ResetVecto.patch | 222 -- ...latformPei-Initialize-CSV-VM-s-memor.patch | 202 -- ...aseMemcryptSevLib-update-page-status.patch | 75 - 0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch | 616 ---- ...mfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch | 724 ---- ...eserve-a-CPUID-table-page-for-CSV-gu.patch | 137 - ...ncryptLib-Detect-SEV-live-migration-.patch | 325 -- ...ncryptLib-Hypercall-API-for-page-enc.patch | 298 -- ...ncryptLib-Invoke-page-encryption-sta.patch | 91 - ...ib-Encryption-state-change-hypercall.patch | 46 - ...Pei-Mark-SEC-GHCB-page-as-unencrypte.patch | 43 - ...e-Add-support-for-SEV-live-migration.patch | 185 - ...aseMemcryptSevLib-Correct-the-calcul.patch | 35 - ...aseMemEncryptLib-Return-SUCCESS-if-n.patch | 36 - ...aseMemEncryptLib-Save-memory-encrypt.patch | 144 - ...ecretDxe-Allocate-secret-location-as.patch | 73 - dist | 1 + download | 2 +- ...-changes-to-.c-.h-files-in-the-Netwo.patch | 1735 ++++++++++ ...rtQemu-migrate-to-OVMF-s-VirtNorFlas.patch | 149 + ...kg-Hob-Integer-Overflow-in-CreateHob.patch | 174 + ...-CcMeasurementProtocol-for-CC-Guest-.patch | 390 +++ ...nit-tests-to-CI-and-create-Host-Test.patch | 169 + ...workPkg-Adds-a-SecurityFix.yaml-file.patch | 170 + ...tworkPkg-Apply-uncrustify-changes-p2.patch | 2054 ++++++++++++ ...-NetworkPkg-Apply-uncrustify-changes.patch | 1937 +++++++++++ ...Dxe-Packet-Length-is-not-updated-bef.patch | 69 + ...Dxe-Removes-duplicate-check-and-repl.patch | 161 + ...Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch | 621 ++++ ...Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch | 257 ++ ...Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch | 1644 +++++++++ ...Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch | 629 ++++ ...e-SECURITY-PATCH-CVE-2023-45231-Patc.patch | 78 + ...e-SECURITY-PATCH-CVE-2023-45231-Unit.patch | 277 ++ ...e-SECURITY-PATCH-CVE-2023-45232-Patc.patch | 377 +++ ...e-SECURITY-PATCH-CVE-2023-45232-Unit.patch | 430 +++ ...xeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch | 168 + ...BcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch | 511 +++ ...BcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch | 257 ++ ...BcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch | 409 +++ ...lashDxe-ValidateFvHeader-unwritten-s.patch | 47 + ...lashDxe-add-a-loop-for-NorFlashWrite.patch | 73 + ...lashDxe-add-casts-to-UINTN-and-UINT3.patch | 55 + ...lashDxe-allow-larger-writes-without-.patch | 65 + ...lashDxe-avoid-array-mode-switch-afte.patch | 89 + ...lashDxe-avoid-switching-between-mode.patch | 303 ++ ...lashDxe-clarify-block-write-logic-fi.patch | 110 + ...lashDxe-clone-ArmPlatformPkg-s-NOR-f.patch | 2973 +++++++++++++++++ ...lashDxe-drop-block-I-O-protocol-impl.patch | 504 +++ ...lashDxe-map-flash-memory-as-uncachea.patch | 67 + ...lashDxe-move-DoErase-code-block-into.patch | 131 + ...lashDxe-remove-CheckBlockLocked-feat.patch | 94 + ...lashDxe-remove-disk-I-O-protocol-imp.patch | 386 +++ ...rtNorFlashDxe-sanity-check-variable2.patch | 216 ++ ...rtNorFlashDxe-sanity-check-variables.patch | 216 ++ ...lashDxe-stop-accepting-gEfiVariable2.patch | 49 + ...lashDxe-stop-accepting-gEfiVariableG.patch | 47 + ...lashDxe-use-EFI_MEMORY_WC-and-drop-A.patch | 150 + ...rFlashPlatformLib-into-VirtNorFlashP.patch | 80 + ...ng-CVE-2022-36763-to-SecurityFixes.y.patch | 68 + ...-Change-OPTIONAL-keyword-usage-style.patch | 403 +++ ...tyPkg-Change-use-of-EFI_D_-to-DEBUG_.patch | 2923 ++++++++++++++++ ...eTpm2MeasureBootLib-SEC-PATCH-4118-2.patch | 272 ++ ...pm2MeasureBootLib-SECURITY-PATCH-411.patch | 1066 ++++++ ...pm2MeasureBootLib-SECURITY-PATCH-418.patch | 286 ++ ...xeTpmMeasureBootLib-SEC-PATCH-4117-2.patch | 279 ++ ...pmMeasureBootLib-SECURITY-PATCH-4117.patch | 960 ++++++ ...pmMeasureBootLib-SECURITY-PATCH-4118.patch | 307 ++ ...ort-CcMeasurementProtocol-in-DxeTpm2.patch | 584 ++++ ...ort-CcMeasurementProtocol-in-DxeTpmM.patch | 255 ++ ...ting-SecurityFixes.yaml-after-symbol.patch | 84 + ...kg-Hob-Integer-Overflow-in-CreateHob.patch | 150 + edk2-ovmf-cc.json | 1 + edk2.spec | 341 +- 78 files changed, 26264 insertions(+), 4213 deletions(-) delete mode 100644 0029-anolis-UefiCpuPkg-Add-StandardSignatureIsHygonGenuin.patch delete mode 100644 0030-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch delete mode 100644 0031-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch delete mode 100644 0032-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch delete mode 100644 0033-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch delete mode 100644 0034-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch delete mode 100644 0035-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch delete mode 100644 0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch delete mode 100644 0037-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch delete mode 100644 0038-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch delete mode 100644 0039-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch delete mode 100644 0040-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch delete mode 100644 0041-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch delete mode 100644 0042-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch delete mode 100644 0043-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch delete mode 100644 0044-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch delete mode 100644 0045-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch delete mode 100644 0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch delete mode 100644 0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch delete mode 100644 0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch create mode 100644 dist create mode 100644 edk2-Apply-uncrustify-changes-to-.c-.h-files-in-the-Netwo.patch create mode 100644 edk2-ArmVirtPkg-ArmVirtQemu-migrate-to-OVMF-s-VirtNorFlas.patch create mode 100644 edk2-EmbeddedPkg-Hob-Integer-Overflow-in-CreateHob.patch create mode 100644 edk2-MdePkg-Introduce-CcMeasurementProtocol-for-CC-Guest-.patch create mode 100644 edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch create mode 100644 edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch create mode 100644 edk2-NetworkPkg-Apply-uncrustify-changes-p2.patch create mode 100644 edk2-NetworkPkg-Apply-uncrustify-changes.patch create mode 100644 edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch create mode 100644 edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch create mode 100644 edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch create mode 100644 edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch create mode 100644 edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch create mode 100644 edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch create mode 100644 edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch create mode 100644 edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch create mode 100644 edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch create mode 100644 edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch create mode 100644 edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch create mode 100644 edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch create mode 100644 edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch create mode 100644 edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-avoid-array-mode-switch-afte.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-avoid-switching-between-mode.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-clone-ArmPlatformPkg-s-NOR-f.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-drop-block-I-O-protocol-impl.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-map-flash-memory-as-uncachea.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-remove-CheckBlockLocked-feat.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-remove-disk-I-O-protocol-imp.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variable2.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variables.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariable2.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariableG.patch create mode 100644 edk2-OvmfPkg-VirtNorFlashDxe-use-EFI_MEMORY_WC-and-drop-A.patch create mode 100644 edk2-OvmfPkg-clone-NorFlashPlatformLib-into-VirtNorFlashP.patch create mode 100644 edk2-SecurityPkg-Adding-CVE-2022-36763-to-SecurityFixes.y.patch create mode 100644 edk2-SecurityPkg-Change-OPTIONAL-keyword-usage-style.patch create mode 100644 edk2-SecurityPkg-Change-use-of-EFI_D_-to-DEBUG_.patch create mode 100644 edk2-SecurityPkg-DxeTpm2MeasureBootLib-SEC-PATCH-4118-2.patch create mode 100644 edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch create mode 100644 edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-418.patch create mode 100644 edk2-SecurityPkg-DxeTpmMeasureBootLib-SEC-PATCH-4117-2.patch create mode 100644 edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4117.patch create mode 100644 edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4118.patch create mode 100644 edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpm2.patch create mode 100644 edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpmM.patch create mode 100644 edk2-SecurityPkg-Updating-SecurityFixes.yaml-after-symbol.patch create mode 100644 edk2-StandaloneMmPkg-Hob-Integer-Overflow-in-CreateHob.patch diff --git a/0029-anolis-UefiCpuPkg-Add-StandardSignatureIsHygonGenuin.patch b/0029-anolis-UefiCpuPkg-Add-StandardSignatureIsHygonGenuin.patch deleted file mode 100644 index 5abf6fc..0000000 --- a/0029-anolis-UefiCpuPkg-Add-StandardSignatureIsHygonGenuin.patch +++ /dev/null @@ -1,140 +0,0 @@ -From c5906a1813f0a370e76d0e4910f1959edd552af4 Mon Sep 17 00:00:00 2001 -From: jiangxin -Date: Thu, 21 Apr 2022 16:03:08 +0800 -Subject: [PATCH 29/46] anolis: UefiCpuPkg: Add - StandardSignatureIsHygonGenuine() in BaseUefiCpuLib - -This function allows IA32/X64 code to determine if it is running on an -Hygon brand processor. - -Signed-off-by: Xin Jiang -Change-Id: I72594196f0ce6003fce43856120e3ca4609b8bb2 ---- - UefiCpuPkg/Include/Library/UefiCpuLib.h | 13 +++++ - UefiCpuPkg/Include/Register/Hygon/Cpuid.h | 47 +++++++++++++++++++ - .../Library/BaseUefiCpuLib/BaseUefiCpuLib.c | 24 ++++++++++ - 3 files changed, 84 insertions(+) - create mode 100644 UefiCpuPkg/Include/Register/Hygon/Cpuid.h - -diff --git a/UefiCpuPkg/Include/Library/UefiCpuLib.h b/UefiCpuPkg/Include/Library/UefiCpuLib.h -index 092c1d2..c64fe26 100644 ---- a/UefiCpuPkg/Include/Library/UefiCpuLib.h -+++ b/UefiCpuPkg/Include/Library/UefiCpuLib.h -@@ -43,6 +43,19 @@ StandardSignatureIsAuthenticAMD ( - VOID - ); - -+/** -+ Determine if the standard CPU signature is "HygonGenuine". -+ -+ @retval TRUE The CPU signature matches. -+ @retval FALSE The CPU signature does not match. -+ -+**/ -+BOOLEAN -+EFIAPI -+StandardSignatureIsHygonGenuine ( -+ VOID -+ ); -+ - /** - Return the 32bit CPU family and model value. - -diff --git a/UefiCpuPkg/Include/Register/Hygon/Cpuid.h b/UefiCpuPkg/Include/Register/Hygon/Cpuid.h -new file mode 100644 -index 0000000..e8a2c76 ---- /dev/null -+++ b/UefiCpuPkg/Include/Register/Hygon/Cpuid.h -@@ -0,0 +1,47 @@ -+/** @file -+ CPUID leaf definitions. -+ -+ Provides defines for CPUID leaf indexes. Data structures are provided for -+ registers returned by a CPUID leaf that contain one or more bit fields. -+ If a register returned is a single 32-bit value, then a data structure is -+ not provided for that register. -+ -+ Copyright (c) 2022, HYGON. All rights reserved.
-+ -+ This program and the accompanying materials are licensed and made available -+ under the terms and conditions of the BSD License which accompanies this -+ distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+**/ -+ -+#ifndef __HYGON_CPUID_H__ -+#define __HYGON_CPUID_H__ -+ -+/** -+CPUID Signature Information -+ -+@param EAX CPUID_SIGNATURE (0x00) -+ -+@retval EAX Returns the highest value the CPUID instruction recognizes for -+ returning basic processor information. The value is returned is -+ processor specific. -+@retval EBX First 4 characters of a vendor identification string. -+@retval ECX Last 4 characters of a vendor identification string. -+@retval EDX Middle 4 characters of a vendor identification string. -+ -+**/ -+ -+/// -+/// @{ CPUID signature values returned by HYGON processors -+/// -+#define CPUID_SIGNATURE_AUTHENTIC_HYGON_EBX SIGNATURE_32 ('H', 'y', 'g', 'o') -+#define CPUID_SIGNATURE_AUTHENTIC_HYGON_EDX SIGNATURE_32 ('n', 'G', 'e', 'n') -+#define CPUID_SIGNATURE_AUTHENTIC_HYGON_ECX SIGNATURE_32 ('u', 'i', 'n', 'e') -+/// -+/// @} -+/// -+ -+#endif -diff --git a/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c b/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c -index 5089161..700d633 100644 ---- a/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c -+++ b/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c -@@ -11,6 +11,7 @@ - - #include - #include -+#include - - #include - #include -@@ -38,6 +39,29 @@ StandardSignatureIsAuthenticAMD ( - RegEdx == CPUID_SIGNATURE_AUTHENTIC_AMD_EDX); - } - -+/** -+ Determine if the standard CPU signature is "HygonGenuine". -+ -+ @retval TRUE The CPU signature matches. -+ @retval FALSE The CPU signature does not match. -+ -+**/ -+BOOLEAN -+EFIAPI -+StandardSignatureIsHygonGenuine ( -+ VOID -+ ) -+{ -+ UINT32 RegEbx; -+ UINT32 RegEcx; -+ UINT32 RegEdx; -+ -+ AsmCpuid (CPUID_SIGNATURE, NULL, &RegEbx, &RegEcx, &RegEdx); -+ return (RegEbx == CPUID_SIGNATURE_AUTHENTIC_HYGON_EBX && -+ RegEcx == CPUID_SIGNATURE_AUTHENTIC_HYGON_ECX && -+ RegEdx == CPUID_SIGNATURE_AUTHENTIC_HYGON_EDX); -+} -+ - /** - Return the 32bit CPU family and model value. - --- -2.17.1 - diff --git a/0030-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch b/0030-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch deleted file mode 100644 index ccb5fd6..0000000 --- a/0030-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 573b40aeb685842d7fd4e7985cd197fc79fe8cff Mon Sep 17 00:00:00 2001 -From: jiangxin -Date: Sun, 10 Apr 2022 21:50:15 -0400 -Subject: [PATCH 30/46] anolis: UefiCpuPkg/LocalApicLib: Exclude second SendIpi - sequence on HYGON hardware - -On HYGON processors the second SendIpi in the SendInitSipiSipi and -SendInitSipiSipiAllExcludingSelf routines is not required, and may cause -undesired side-effects during MP initialization. - -This patch leverages the StandardSignatureIsHygonGenuine check to exclude -the second SendIpi and its associated MicroSecondDelay (200). - -Signed-off-by: Xin Jiang -Change-Id: I59defdaf10fb36981c5dfb7e3b69e8bf5aaf46cc ---- - UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c | 5 +++-- - UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c | 5 +++-- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c -index 52bd90d..fac41bd 100644 ---- a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c -+++ b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - // - // Library internal functions -@@ -527,7 +528,7 @@ SendInitSipiSipi ( - IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; - IcrLow.Bits.Level = 1; - SendIpi (IcrLow.Uint32, ApicId); -- if (!StandardSignatureIsAuthenticAMD ()) { -+ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { - MicroSecondDelay (200); - SendIpi (IcrLow.Uint32, ApicId); - } -@@ -563,7 +564,7 @@ SendInitSipiSipiAllExcludingSelf ( - IcrLow.Bits.Level = 1; - IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; - SendIpi (IcrLow.Uint32, 0); -- if (!StandardSignatureIsAuthenticAMD ()) { -+ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { - MicroSecondDelay (200); - SendIpi (IcrLow.Uint32, 0); - } -diff --git a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c -index cdcbca0..a8fea8b 100644 ---- a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c -+++ b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - // - // Library internal functions -@@ -622,7 +623,7 @@ SendInitSipiSipi ( - IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; - IcrLow.Bits.Level = 1; - SendIpi (IcrLow.Uint32, ApicId); -- if (!StandardSignatureIsAuthenticAMD ()) { -+ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { - MicroSecondDelay (200); - SendIpi (IcrLow.Uint32, ApicId); - } -@@ -658,7 +659,7 @@ SendInitSipiSipiAllExcludingSelf ( - IcrLow.Bits.Level = 1; - IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; - SendIpi (IcrLow.Uint32, 0); -- if (!StandardSignatureIsAuthenticAMD ()) { -+ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { - MicroSecondDelay (200); - SendIpi (IcrLow.Uint32, 0); - } --- -2.17.1 - diff --git a/0031-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch b/0031-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch deleted file mode 100644 index 72ebc6f..0000000 --- a/0031-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch +++ /dev/null @@ -1,672 +0,0 @@ -From 98354124fe8c4cd7e6aed0fb6feabbe3a4de1836 Mon Sep 17 00:00:00 2001 -From: Liu Zixing -Date: Fri, 25 Feb 2022 14:25:11 +0800 -Subject: [PATCH 31/46] anolis: OvmfPkg: Add CSV secure call library on Hygon - CPU - -CSV is the secure virtualization feature on Hygon CPU. -A CSV virtual machine is composed of private memory and shared memory. -The private memory or shared memory can be converted to the other by -the following steps: - - guest clear/set the c-bit in the guest page table - - guest send a update command to Hygon Secure Processor - -While the update command has to be forwarded by the VMM to the Secure -Processor, to prevent the malicious VMM from attacking the update -command, a reliable command channel is required between the CSV VM -and the Hygon Secure Processor. - -The secure call library is created to build a secure command channel -between the VM and the Secure Processor by #NPF on a special private -page which the VMM is not able to access. -This special page is called secure call page. -The VM puts command in the secure call page and triggers a #NPF -to reach the Secure Processor. -The Secure Processor then puts the response in the same page and -finishes the #NPF. -The information is protected in the secure call page all the way. - -CsvLib is added to implement the functionality and new PCDs are added -accordingly. - -Signed-off-by: Xin Jiang -Change-Id: If62f0cb37faf003a79ed8a117bf582f8b90cdf89 ---- - OvmfPkg/Include/Library/CsvLib.h | 84 +++++++ - OvmfPkg/Library/CsvLib/CsvLib.c | 82 ++++++ - OvmfPkg/Library/CsvLib/CsvLib.inf | 55 ++++ - .../Library/CsvLib/Ia32/UpdateMemoryCsvLib.c | 53 ++++ - .../Library/CsvLib/X64/UpdateMemoryCsvLib.c | 238 ++++++++++++++++++ - OvmfPkg/OvmfPkg.dec | 8 + - OvmfPkg/OvmfPkgIa32.dsc | 1 + - OvmfPkg/OvmfPkgIa32X64.dsc | 1 + - OvmfPkg/OvmfPkgX64.dsc | 1 + - OvmfPkg/OvmfPkgX64.fdf | 3 + - 10 files changed, 526 insertions(+) - create mode 100644 OvmfPkg/Include/Library/CsvLib.h - create mode 100644 OvmfPkg/Library/CsvLib/CsvLib.c - create mode 100644 OvmfPkg/Library/CsvLib/CsvLib.inf - create mode 100644 OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c - create mode 100644 OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c - -diff --git a/OvmfPkg/Include/Library/CsvLib.h b/OvmfPkg/Include/Library/CsvLib.h -new file mode 100644 -index 0000000..0cb6218 ---- /dev/null -+++ b/OvmfPkg/Include/Library/CsvLib.h -@@ -0,0 +1,84 @@ -+/** @file -+ -+ CSV base library helper function -+ -+ Copyright (c) 2022, HYGON. All rights reserved.
-+ -+ This program and the accompanying materials are licensed and made available -+ under the terms and conditions of the BSD License which accompanies this -+ distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ -+**/ -+ -+#ifndef _CSV_LIB_H_ -+#define _CSV_LIB_H_ -+ -+#include -+ -+typedef struct { -+ IN UINT64 BaseAddress; -+ IN UINT64 Size; -+} CSV_SECURE_CMD_SHARED_REGION; -+ -+typedef enum { -+ CsvSecureCmdEnc = 1, -+ CsvSecureCmdDec, -+ CsvSecureCmdReset, -+ CsvSecureCmdUpdateSecureCallTable, -+ CsvSecureCmdMapLowerMemory, //secure memory range below 4G -+ CsvSecureCmdMapUpperMemory //secure memory range above 4G -+} CSV_SECURE_COMMAND_TYPE; -+ -+/** -+ Returns a boolean to indicate whether CSV is enabled -+ -+ @retval TRUE CSV is enabled -+ @retval FALSE CSV is not enabled -+**/ -+BOOLEAN -+EFIAPI -+CsvIsEnabled ( -+ VOID -+ ); -+ -+#define CSV_SHARED_MEMORY_SIGNATURE SIGNATURE_32('C','S','V',' ') -+ -+typedef struct { -+ UINTN Signature; -+ LIST_ENTRY Link; -+ UINT64 Start; -+ UINT64 Length; -+} CsvSharedMemoryEntry; -+ -+VOID -+EFIAPI -+CsvUpdateMemory ( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages, -+ IN BOOLEAN Dec -+); -+ -+VOID -+EFIAPI -+CsvResetMemory ( -+ VOID -+); -+ -+VOID -+EFIAPI -+CsvUpdateMapLowerMemory ( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages -+); -+ -+VOID -+EFIAPI -+CsvUpdateMapUpperMemory ( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages -+); -+#endif // _CSV_LIB_H_ -diff --git a/OvmfPkg/Library/CsvLib/CsvLib.c b/OvmfPkg/Library/CsvLib/CsvLib.c -new file mode 100644 -index 0000000..7e7f8ef ---- /dev/null -+++ b/OvmfPkg/Library/CsvLib/CsvLib.c -@@ -0,0 +1,82 @@ -+/** @file -+ -+ CSV library helper function -+ -+ Copyright (c) 2022, HYGON. All rights reserved.
-+ -+ This program and the accompanying materials are licensed and made available -+ under the terms and conditions of the BSD License which accompanies this -+ distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ -+**/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+STATIC BOOLEAN mCsvStatus = FALSE; -+STATIC BOOLEAN mCsvStatusChecked = FALSE; -+ -+/** -+ -+ Reads and sets the status of CSV features -+ **/ -+STATIC -+VOID -+EFIAPI -+InternalCsvStatus ( -+ VOID -+ ) -+{ -+ UINT32 RegEax; -+ -+ // -+ // Check if memory encryption leaf exist -+ // -+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); -+ if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) { -+ if(StandardSignatureIsHygonGenuine ()){ -+ // -+ // Check MSR_0xC0010131 Bit 30 (Csv Enabled) -+ // -+ MSR_SEV_STATUS_REGISTER Msr; -+ Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS); -+ if (Msr.Uint32 & (1 << 30)) { -+ mCsvStatus = TRUE; -+ DEBUG ((EFI_D_INFO, "CSV is enabled\n")); -+ } -+ } -+ } -+ mCsvStatusChecked = TRUE; -+} -+ -+/** -+ Returns a boolean to indicate whether CSV is enabled -+ -+ @retval TRUE CSV is enabled -+ @retval FALSE CSV is not enabled -+**/ -+BOOLEAN -+EFIAPI -+CsvIsEnabled ( -+ VOID -+ ) -+{ -+ if (!mCsvStatusChecked) { -+ InternalCsvStatus (); -+ } -+ -+ return MemEncryptSevEsIsEnabled () && mCsvStatus; -+} -diff --git a/OvmfPkg/Library/CsvLib/CsvLib.inf b/OvmfPkg/Library/CsvLib/CsvLib.inf -new file mode 100644 -index 0000000..25859c3 ---- /dev/null -+++ b/OvmfPkg/Library/CsvLib/CsvLib.inf -@@ -0,0 +1,55 @@ -+## @file -+# Library provides the helper functions for CSV guest -+# -+# Copyright (c) 2022 HYGON. All rights reserved.
-+# -+# This program and the accompanying materials -+# are licensed and made available under the terms and conditions of the BSD -+# License which accompanies this distribution. The full text of the license -+# may be found at http://opensource.org/licenses/bsd-license.php -+# -+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED. -+# -+# -+## -+ -+[Defines] -+ INF_VERSION = 1.25 -+ BASE_NAME = CsvLib -+ FILE_GUID = 9460ef3a-b9c3-11e9-8324-7371ac35e1e3 -+ MODULE_TYPE = BASE -+ VERSION_STRING = 1.0 -+ LIBRARY_CLASS = CsvLib|PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER -+ -+# -+# The following information is for reference only and not required by the build -+# tools. -+# -+# VALID_ARCHITECTURES = Ia32 X64 -+# -+ -+[Packages] -+ MdePkg/MdePkg.dec -+ OvmfPkg/OvmfPkg.dec -+ UefiCpuPkg/UefiCpuPkg.dec -+ -+[Sources] -+ CsvLib.c -+ -+[Sources.X64] -+ X64/UpdateMemoryCsvLib.c -+[Sources.IA32] -+ Ia32/UpdateMemoryCsvLib.c -+ -+[LibraryClasses] -+ BaseLib -+ CpuLib -+ DebugLib -+ MemEncryptSevLib -+ UefiCpuLib -+ -+[Pcd] -+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase -+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize -diff --git a/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c b/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c -new file mode 100644 -index 0000000..15d3aa8 ---- /dev/null -+++ b/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c -@@ -0,0 +1,53 @@ -+/** @file -+ -+ CSV library helper function -+ -+ Copyright (c) 2022, HYGON. All rights reserved.
-+ -+ This program and the accompanying materials are licensed and made available -+ under the terms and conditions of the BSD License which accompanies this -+ distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ -+**/ -+ -+#include -+ -+VOID -+EFIAPI -+CsvUpdateMemory ( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages, -+ IN BOOLEAN Dec -+) -+{ -+} -+ -+VOID -+EFIAPI -+CsvResetMemory ( -+ VOID -+) -+{ -+} -+ -+VOID -+EFIAPI -+CsvUpdateMapLowerMemory ( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages -+) -+{ -+} -+ -+VOID -+EFIAPI -+CsvUpdateMapUpperMemory ( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages -+) -+{ -+} -diff --git a/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c b/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c -new file mode 100644 -index 0000000..13d06d7 ---- /dev/null -+++ b/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c -@@ -0,0 +1,238 @@ -+/** @file -+ -+ CSV library helper function -+ -+ Copyright (c) 2022, HYGON. All rights reserved.
-+ -+ This program and the accompanying materials are licensed and made available -+ under the terms and conditions of the BSD License which accompanies this -+ distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ -+**/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define SECURE_CALL_ENTRY_MAX (254) -+ -+ -+typedef struct { -+ union { -+ UINT8 Guid[16]; -+ UINT64 Guid64[2]; -+ }; -+ UINT32 CmdType; -+ UINT32 Nums; -+ UINT64 Unused; -+ struct { -+ UINT64 BaseAddress; -+ UINT64 Size; -+ } Entry[SECURE_CALL_ENTRY_MAX]; -+} CSV_SECURE_CALL_CMD; -+ -+STATIC UINT32 SecureCallPageIdx = 0; -+ -+STATIC UINTN MemorySizeBelow4G = (UINTN)-1; -+STATIC UINTN MemorySizeAbove4G = (UINTN)-1; -+ -+STATIC -+VOID -+EFIAPI -+CsvSecureCall( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages, -+ IN CSV_SECURE_COMMAND_TYPE CmdType -+) -+{ -+ volatile CSV_SECURE_COMMAND_TYPE CmdAck = 0; -+ -+ CSV_SECURE_CALL_CMD *SecureCallPageRead; -+ CSV_SECURE_CALL_CMD *SecureCallPageWrite; -+ UINTN SecureCallBase = 0; -+ -+ if (CsvIsEnabled () == FALSE) { -+ return ; -+ } -+ -+ SecureCallBase = FixedPcdGet32 (PcdCsvDefaultSecureCallBase); -+ -+ SecureCallPageRead = -+ (CSV_SECURE_CALL_CMD *)(UINT64) -+ (EFI_PAGE_SIZE * SecureCallPageIdx + SecureCallBase); -+ -+ SecureCallPageWrite = -+ (CSV_SECURE_CALL_CMD *) -+ (UINT64)(EFI_PAGE_SIZE * (1 - SecureCallPageIdx) + SecureCallBase); -+ -+ while(1) { -+ SecureCallPageWrite->CmdType = (UINT32)CmdType; -+ SecureCallPageWrite->Nums = 1; -+ SecureCallPageWrite->Entry[0].BaseAddress = (UINT64)BaseAddress; -+ SecureCallPageWrite->Entry[0].Size = (UINT64)NumPages << EFI_PAGE_SHIFT; -+ -+ MemoryFence (); -+ -+ CmdAck = SecureCallPageRead->CmdType; -+ if (CmdAck != CmdType) -+ break; -+ } -+ SecureCallPageIdx = 1 - SecureCallPageIdx; -+} -+ -+STATIC -+UINT8 -+CmosRead8 ( -+ IN UINTN Index -+ ) -+{ -+ IoWrite8 (0x70, (UINT8) Index); -+ return IoRead8 (0x71); -+} -+ -+ -+STATIC -+VOID -+EFIAPI -+CsvGetSystemMemory( -+ VOID -+ ) -+{ -+ UINT8 Cmos0x34; -+ UINT8 Cmos0x35; -+ UINT32 Size; -+ UINTN CmosIndex; -+ -+ // -+ // system memory below 4GB MB -+ // -+ -+ Cmos0x34 = (UINT8) CmosRead8 (0x34); -+ Cmos0x35 = (UINT8) CmosRead8 (0x35); -+ -+ MemorySizeBelow4G = -+ (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB); -+ -+ // -+ // system memory above 4GB MB -+ // -+ -+ Size = 0; -+ for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) { -+ Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex); -+ } -+ -+ MemorySizeAbove4G = LShiftU64 (Size, 16); -+} -+ -+STATIC -+BOOLEAN -+EFIAPI -+CsvIsDRAM( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages -+ ) -+{ -+ UINTN Size = EFI_PAGES_TO_SIZE (NumPages); -+ PHYSICAL_ADDRESS EndAddress; -+ -+ Size = EFI_PAGES_TO_SIZE (NumPages); -+ EndAddress = BaseAddress + Size; -+ -+ if (MemorySizeBelow4G == (UINTN)-1 || -+ MemorySizeAbove4G == (UINTN)-1) { -+ CsvGetSystemMemory (); -+ } -+ -+ if (BaseAddress < MemorySizeBelow4G) { -+ return TRUE; -+ } else if (BaseAddress >= BASE_4GB && -+ BaseAddress < (BASE_4GB + MemorySizeAbove4G)) { -+ return TRUE; -+ } else if (EndAddress > BASE_4GB && -+ EndAddress <= (BASE_4GB + MemorySizeAbove4G)) { -+ return TRUE; -+ } else { -+ return FALSE; -+ } -+} -+ -+STATIC -+VOID -+EFIAPI -+CsvUpdateEncryptMemory ( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages -+) -+{ -+ PHYSICAL_ADDRESS PageAddress = BaseAddress & ~EFI_PAGE_MASK; -+ -+ if (CsvIsDRAM (PageAddress, NumPages)) { -+ CsvSecureCall (PageAddress, NumPages, CsvSecureCmdEnc); -+ } -+} -+ -+STATIC -+VOID -+EFIAPI -+CsvUpdateDecryptMemory ( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages -+) -+{ -+ PHYSICAL_ADDRESS PageAddress = BaseAddress & ~EFI_PAGE_MASK; -+ -+ if (CsvIsDRAM (PageAddress, NumPages)) { -+ CsvSecureCall (PageAddress, NumPages, CsvSecureCmdDec); -+ } -+} -+ -+VOID -+EFIAPI -+CsvUpdateMemory ( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages, -+ IN BOOLEAN Dec -+ ) -+{ -+ if (Dec) -+ CsvUpdateDecryptMemory (BaseAddress, NumPages); -+ else -+ CsvUpdateEncryptMemory (BaseAddress, NumPages); -+} -+ -+VOID -+EFIAPI -+CsvResetMemory ( -+ VOID -+) -+{ -+ CsvSecureCall (0, 0, CsvSecureCmdReset); -+} -+ -+VOID -+EFIAPI -+CsvUpdateMapLowerMemory ( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages -+) -+{ -+ CsvSecureCall (BaseAddress, NumPages, CsvSecureCmdMapLowerMemory); -+} -+ -+VOID -+EFIAPI -+CsvUpdateMapUpperMemory ( -+ IN PHYSICAL_ADDRESS BaseAddress, -+ IN UINTN NumPages -+) -+{ -+ CsvSecureCall (BaseAddress, NumPages, CsvSecureCmdMapUpperMemory); -+} -diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec -index 340d83f..6f4afb8 100644 ---- a/OvmfPkg/OvmfPkg.dec -+++ b/OvmfPkg/OvmfPkg.dec -@@ -109,6 +109,10 @@ - # - XenPlatformLib|Include/Library/XenPlatformLib.h - -+ ## @libraryclass CSV Library -+ # -+ CsvLib|Include/Library/CsvLib.h -+ - [Guids] - gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}} - gEfiXenInfoGuid = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}} -@@ -350,6 +354,10 @@ - gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataOffset|0|UINT32|0x56 - gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataSize|0|UINT32|0x57 - -+ ## the base address of the secure call pages used by CSV. -+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|0|UINT32|0x58 -+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize|0|UINT32|0x59 -+ - [PcdsDynamic, PcdsDynamicEx] - gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 -diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc -index a066693..d623ed3 100644 ---- a/OvmfPkg/OvmfPkgIa32.dsc -+++ b/OvmfPkg/OvmfPkgIa32.dsc -@@ -176,6 +176,7 @@ - VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf - LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf - MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -+ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf - !if $(SMM_REQUIRE) == FALSE - LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf - !endif -diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc -index 5efeb42..9e4dcce 100644 ---- a/OvmfPkg/OvmfPkgIa32X64.dsc -+++ b/OvmfPkg/OvmfPkgIa32X64.dsc -@@ -180,6 +180,7 @@ - VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf - LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf - MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -+ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf - !if $(SMM_REQUIRE) == FALSE - LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf - !endif -diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc -index 10fb7d7..e62b533 100644 ---- a/OvmfPkg/OvmfPkgX64.dsc -+++ b/OvmfPkg/OvmfPkgX64.dsc -@@ -180,6 +180,7 @@ - VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf - LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf - MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -+ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf - !if $(SMM_REQUIRE) == FALSE - LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf - !endif -diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf -index 85b4b23..a3634dd 100644 ---- a/OvmfPkg/OvmfPkgX64.fdf -+++ b/OvmfPkg/OvmfPkgX64.fdf -@@ -88,6 +88,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvm - 0x00C000|0x001000 - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize - -+0x00D000|0x002000 -+gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize -+ - 0x010000|0x010000 - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize - --- -2.17.1 - diff --git a/0032-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch b/0032-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch deleted file mode 100644 index c00ebcd..0000000 --- a/0032-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 40c0763c88a6a895d4fc58158f3c0f9a17798049 Mon Sep 17 00:00:00 2001 -From: Xin Jiang -Date: Fri, 18 Aug 2023 16:48:03 +0800 -Subject: [PATCH 32/46] anolis: OvmfPkg/Tcg: Add CsvLib for - TpmMmioSevDecryptPei - -Signed-off-by: Xin Jiang -Change-Id: I4a11065abcc679538aabcb7602185f785df60496 ---- - OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf -index 51ad6d0..402e4c9 100644 ---- a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf -+++ b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf -@@ -29,6 +29,7 @@ - PcdLib - PeimEntryPoint - PeiServicesLib -+ CsvLib - - [Ppis] - gOvmfTpmMmioAccessiblePpiGuid ## PRODUCES --- -2.17.1 - diff --git a/0033-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch b/0033-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch deleted file mode 100644 index b30e7df..0000000 --- a/0033-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch +++ /dev/null @@ -1,222 +0,0 @@ -From b08f9e4b2d4aa1f1baec02ecda6ae481ed58c64f Mon Sep 17 00:00:00 2001 -From: Liu Zixing -Date: Fri, 25 Feb 2022 15:55:44 +0800 -Subject: [PATCH 33/46] anolis: OvmfPkg/ResetVector: Support CSV in ResetVector - phase - -- A GUID is written along with the first secure call page address, -by which the Secure Processor can locate the first secure call page -address. - -- Check whether the VM is a CSV VM when setting the first page table - -- CSV VM will update first shared GHCB page address to Secure Processor -by secure call page - -Signed-off-by: Xin Jiang -Change-Id: I422bff00dc88d6738d1dae2d9f6c5c49ec601e95 ---- - OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 15 +++ - OvmfPkg/ResetVector/Ia32/AmdSev.asm | 10 ++ - OvmfPkg/ResetVector/Ia32/CsvInit.asm | 107 +++++++++++++++++++ - OvmfPkg/ResetVector/ResetVector.inf | 2 + - OvmfPkg/ResetVector/ResetVector.nasmb | 4 + - 5 files changed, 138 insertions(+) - create mode 100644 OvmfPkg/ResetVector/Ia32/CsvInit.asm - -diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm -index dee2e3f..c32b608 100644 ---- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm -+++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm -@@ -48,6 +48,21 @@ TIMES (15 - ((guidedStructureEnd - guidedStructureStart + 15) % 16)) DB 0 - guidedStructureStart: - - %ifdef ARCH_X64 -+; -+; CSV secure call table -+; -+; Provide secure call pages when boot up for CSV guest. -+; -+; GUID : 9a5d926f-2fa5-ceba-ab21-6b275d5556a5 -+; -+csvSecureCallBase: -+ DD CSV_DEFAULT_SECURE_CALL_SIZE -+ DD CSV_DEFAULT_SECURE_CALL_BASE -+ DW csvSecureCallEnd - csvSecureCallBase -+ DB 0x6F, 0x92, 0x5D, 0x9A, 0xA5, 0x2F, 0xBA, 0xCE -+ DB 0xAB, 0x21, 0x6B, 0x27, 0x5D, 0x55, 0x56, 0xA5 -+csvSecureCallEnd: -+ - ; - ; TDX Metadata offset block - ; -diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm -index 250ac8d..8ce5eb0 100644 ---- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm -+++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm -@@ -177,6 +177,16 @@ pageTableEntries4kLoop: - mov ecx, (GHCB_BASE & 0x1F_FFFF) >> 12 - mov [ecx * 8 + GHCB_PT_ADDR + 4], strict dword 0 - -+ OneTimeCall CheckCsvFeature -+ test eax, eax -+ jz clearGhcbStart -+ -+ OneTimeCall CsvInit -+ mov eax, 1 -+ test ecx, ecx -+ jz SevEsUnexpectedRespTerminate -+ -+clearGhcbStart: - mov ecx, GHCB_SIZE / 4 - xor eax, eax - clearGhcbMemoryLoop: -diff --git a/OvmfPkg/ResetVector/Ia32/CsvInit.asm b/OvmfPkg/ResetVector/Ia32/CsvInit.asm -new file mode 100644 -index 0000000..0744a35 ---- /dev/null -+++ b/OvmfPkg/ResetVector/Ia32/CsvInit.asm -@@ -0,0 +1,107 @@ -+;------------------------------------------------------------------------------ -+; @file -+; Provide the functions to check whether CSV is enabled. -+; -+; Copyright (c) 2022, HYGON. All rights reserved.
-+; SPDX-License-Identifier: BSD-2-Clause-Patent -+; -+;------------------------------------------------------------------------------ -+ -+BITS 32 -+ -+; If Secure Command returns ok then ECX will be non-zero. -+; If Secure Command returns error then ECX will be zero. -+CsvInit: -+ mov esp, SEV_ES_VC_TOP_OF_STACK -+ push esi -+ push edi -+ -+ ; copy SECURE_CALL_GUID to CSV_DEFAULT_SECURE_CALL_BASE + 4096 -+ cld -+ mov esi, ADDR_OF(SECURE_CALL_GUID) -+ mov edi, CSV_DEFAULT_SECURE_CALL_BASE -+ add edi, 4096 -+ mov ecx, 4 -+ rep movsd -+ -+ ; secure call begin -+ mov esi, CSV_DEFAULT_SECURE_CALL_BASE -+ ; write secure cmd to page B -+ ; 16 bytes of page A/B is GUID, just ignore -+ mov [esi + 4096 + 16], DWORD 2 ; dec command -+ mov [esi + 4096 + 20], DWORD 1 ; 1 entry -+ ; 8 bytes is unused -+ mov [esi + 4096 + 32], DWORD GHCB_BASE; lower address -+ mov [esi + 4096 + 36], DWORD 0 ; upper address -+ mov [esi + 4096 + 40], DWORD 4096 ; lower 32 bit of page size -+ mov [esi + 4096 + 44], DWORD 0 ; upper 32 bit of page size -+ mfence -+ ; read from page A -+ mov ecx, [esi + 16] -+ ; check if the response comes -+ cmp ecx, 2 -+ jne SecureCommandDone -+ ; no secure command response, clean ecx -+ xor ecx, ecx -+ ; secure call end -+ -+SecureCommandDone: -+ pop edi -+ pop esi -+ mov esp, 0 -+ -+ OneTimeCallRet CsvInit -+ -+; Check if CSV feature is enabled. -+; -+; Modified: EAX, EBX, ECX, EDX -+; -+; If CSV is enabled then EAX will be non-zero. -+; If CSV is disabled then EAX will be zero. -+; -+CheckCsvFeature: -+ mov esp, SEV_ES_VC_TOP_OF_STACK -+ mov eax, ADDR_OF(Idtr) -+ lidt [cs:eax] -+ -+ ; Check if vendor Hygon CPUID_SIGNATURE(0x0) -+ ; CPUID raises a #VC exception if running as an SEV-ES guest -+ mov eax, 0 -+ cpuid -+ -+ cmp ebx, 0x6f677948 -+ jne NoCsv -+ cmp ecx, 0x656e6975 -+ jne NoCsv -+ cmp edx, 0x6e65476e -+ jne NoCsv -+ -+ ; Check if CSV is enabled -+ ; MSR_0xC0010131 - Bit 30 (CSV enabled) -+ mov ecx, 0xc0010131 -+ rdmsr -+ and eax, 0x40000000 -+ jmp CsvExit -+ -+NoCsv: -+ xor eax, eax -+ -+CsvExit: -+ ; -+ ; Clear exception handlers and stack -+ ; -+ push eax -+ mov eax, ADDR_OF(IdtrClear) -+ lidt [cs:eax] -+ pop eax -+ mov esp, 0 -+ -+ OneTimeCallRet CheckCsvFeature -+ -+SECURE_CALL_GUID: -+; low 0xceba2fa59a5d926f -+; high 0xa556555d276b21ab -+ dd 0x9a5d926f -+ dd 0xceba2fa5 -+ dd 0x276b21ab -+ dd 0xa556555d -diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf -index 320e5f2..38c1720 100644 ---- a/OvmfPkg/ResetVector/ResetVector.inf -+++ b/OvmfPkg/ResetVector/ResetVector.inf -@@ -35,6 +35,8 @@ - - [Pcd] - gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase -+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase -+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase -diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb -index 87effed..ca00f64 100644 ---- a/OvmfPkg/ResetVector/ResetVector.nasmb -+++ b/OvmfPkg/ResetVector/ResetVector.nasmb -@@ -104,11 +104,15 @@ - %define SEV_ES_WORK_AREA_ENC_MASK (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 16) - %define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize)) - -+ %define CSV_DEFAULT_SECURE_CALL_BASE FixedPcdGet32 (PcdCsvDefaultSecureCallBase) -+ %define CSV_DEFAULT_SECURE_CALL_SIZE FixedPcdGet32 (PcdCsvDefaultSecureCallSize) -+ - %include "X64/IntelTdxMetadata.asm" - %include "Ia32/Flat32ToFlat64.asm" - %include "Ia32/AmdSev.asm" - %include "Ia32/PageTables64.asm" - %include "Ia32/IntelTdx.asm" -+%include "Ia32/CsvInit.asm" - %endif - - %include "Ia16/Real16ToFlat32.asm" --- -2.17.1 - diff --git a/0034-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch b/0034-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch deleted file mode 100644 index 3a55e93..0000000 --- a/0034-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch +++ /dev/null @@ -1,202 +0,0 @@ -From 9c52c4e45c2fc51308628c8118edb3740bbfae47 Mon Sep 17 00:00:00 2001 -From: Liu Zixing -Date: Fri, 25 Feb 2022 16:12:38 +0800 -Subject: [PATCH 34/46] anolis: OvmfPkg/PlatformPei: Initialize CSV VM's memory - -For CSV VM, the Secure Processor builds a temporary nested -page table to help the guest to run into the PEI phase. - -In PEI phase, CSV VM detects the start address and size of the -guest physical memory. - -The CSV VM sends the memory information to the Secure Processor -to build the permanent nested page table. - -Signed-off-by: Xin Jiang -Change-Id: I853d17ffa4146037038018d934f224fcbf79be1a ---- - OvmfPkg/PlatformPei/Csv.c | 81 +++++++++++++++++++++++++++++ - OvmfPkg/PlatformPei/MemDetect.c | 2 - - OvmfPkg/PlatformPei/Platform.c | 2 + - OvmfPkg/PlatformPei/Platform.h | 14 +++++ - OvmfPkg/PlatformPei/PlatformPei.inf | 4 ++ - 5 files changed, 101 insertions(+), 2 deletions(-) - create mode 100644 OvmfPkg/PlatformPei/Csv.c - -diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c -new file mode 100644 -index 0000000..44e81e1 ---- /dev/null -+++ b/OvmfPkg/PlatformPei/Csv.c -@@ -0,0 +1,81 @@ -+/** @file -+ -+ CSV initialization in PEI -+ -+ Copyright (c) 2022, HYGON. All rights reserved.
-+ -+ This program and the accompanying materials are licensed and made available -+ under the terms and conditions of the BSD License which accompanies this -+ distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ -+**/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "Platform.h" -+ -+VOID -+CsvInitializeMemInfo ( -+ VOID -+ ) -+{ -+ UINT64 LowerMemorySize; -+ UINT64 UpperMemorySize; -+ -+ if (!CsvIsEnabled ()) { -+ return ; -+ } -+ -+ LowerMemorySize = GetSystemMemorySizeBelow4gb (); -+ UpperMemorySize = GetSystemMemorySizeAbove4gb (); -+ -+ CsvUpdateMapLowerMemory ( -+ 0, -+ LowerMemorySize >> EFI_PAGE_SHIFT -+ ); -+ -+ if (UpperMemorySize > 0) { -+ CsvUpdateMapUpperMemory ( -+ BASE_4GB, -+ UpperMemorySize >> EFI_PAGE_SHIFT -+ ); -+ } -+ -+ BuildMemoryAllocationHob ( -+ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallBase), -+ (UINT64)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallSize), -+ EfiReservedMemoryType -+ ); -+} -+ -+VOID -+CsvInitializeGhcb ( -+ VOID -+ ) -+{ -+ RETURN_STATUS EncryptStatus; -+ -+ if (!CsvIsEnabled ()) { -+ return ; -+ } -+ -+ // -+ // Encrypt the SecGhcb as it's not a Ghcb any more -+ // -+ EncryptStatus = MemEncryptSevSetPageEncMask( -+ 0, -+ PcdGet32 (PcdOvmfSecGhcbBase), -+ 1 -+ ); -+ ASSERT_RETURN_ERROR (EncryptStatus); -+} -diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c -index d736b85..c2c3cf7 100644 ---- a/OvmfPkg/PlatformPei/MemDetect.c -+++ b/OvmfPkg/PlatformPei/MemDetect.c -@@ -301,8 +301,6 @@ GetSystemMemorySizeBelow4gb ( - return (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB); - } - -- --STATIC - UINT64 - GetSystemMemorySizeAbove4gb ( - ) -diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c -index d0e2c08..79bf4e7 100644 ---- a/OvmfPkg/PlatformPei/Platform.c -+++ b/OvmfPkg/PlatformPei/Platform.c -@@ -743,6 +743,7 @@ InitializePlatform ( - QemuUc32BaseInitialization (); - - InitializeRamRegions (); -+ CsvInitializeMemInfo (); - - if (mBootMode != BOOT_ON_S3_RESUME) { - if (!FeaturePcdGet (PcdSmmSmramRequire)) { -@@ -757,6 +758,7 @@ InitializePlatform ( - - InstallClearCacheCallback (); - AmdSevInitialize (); -+ CsvInitializeGhcb (); - MiscInitialization (); - InstallFeatureControlCallback (); - -diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h -index 8b1d270..89c3bd8 100644 ---- a/OvmfPkg/PlatformPei/Platform.h -+++ b/OvmfPkg/PlatformPei/Platform.h -@@ -102,6 +102,20 @@ AmdSevInitialize ( - VOID - ); - -+VOID -+CsvInitializeMemInfo ( -+ VOID -+); -+ -+VOID -+CsvInitializeGhcb ( -+ VOID -+); -+ -+UINT64 -+GetSystemMemorySizeAbove4gb ( -+); -+ - extern EFI_BOOT_MODE mBootMode; - - extern BOOLEAN mS3Supported; -diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf -index 69eb3ed..cb0582c 100644 ---- a/OvmfPkg/PlatformPei/PlatformPei.inf -+++ b/OvmfPkg/PlatformPei/PlatformPei.inf -@@ -33,6 +33,7 @@ - MemTypeInfo.c - Platform.c - Platform.h -+ Csv.c - - [Packages] - EmbeddedPkg/EmbeddedPkg.dec -@@ -62,6 +63,7 @@ - MtrrLib - MemEncryptSevLib - PcdLib -+ CsvLib - - [Pcd] - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase -@@ -119,6 +121,8 @@ - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize -+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase -+ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize - - [FeaturePcd] - gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable --- -2.17.1 - diff --git a/0035-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch b/0035-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch deleted file mode 100644 index 1938b99..0000000 --- a/0035-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 16936ea22fc052576844dfdad6987531aa27a8ec Mon Sep 17 00:00:00 2001 -From: Liu Zixing -Date: Sat, 26 Feb 2022 14:39:06 +0800 -Subject: [PATCH 35/46] anolis: OvmfPkg/BaseMemcryptSevLib: update page status - to Secure Processor for CSV - -For CSV VM, when encrypting/decrypting a shared/private memory region, -guest needs to - - set/clear the c-bit in guest page table - - the Secure Processor should be updated accordingly - -The BaseMemcryptSevLib has done the first step. -Calling the secure call library for second step. - -Signed-off-by: Xin Jiang -Change-Id: Icab502ee201d887d6056bcb0116b2e5a1b9eb6b9 ---- - .../BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf | 1 + - .../BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 14 ++++++++++++++ - 2 files changed, 15 insertions(+) - -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -index f2e162d..dc32929 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -@@ -49,6 +49,7 @@ - DebugLib - MemoryAllocationLib - PcdLib -+ CsvLib - - [FeaturePcd] - gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c -index c696745..6726010 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c -@@ -18,6 +18,8 @@ - - #include "VirtualMemory.h" - -+#include -+ - STATIC BOOLEAN mAddressEncMaskChecked = FALSE; - STATIC UINT64 mAddressEncMask; - STATIC PAGE_TABLE_POOL *mPageTablePool = NULL; -@@ -585,6 +587,11 @@ SetMemoryEncDec ( - UINT64 AddressEncMask; - BOOLEAN IsWpEnabled; - RETURN_STATUS Status; -+ PHYSICAL_ADDRESS PageAddress; -+ UINTN PageNum; -+ -+ PageAddress = PhysicalAddress; -+ PageNum = EFI_SIZE_TO_PAGES (Length); - - // - // Set PageMapLevel4Entry to suppress incorrect compiler/analyzer warnings. -@@ -816,6 +823,13 @@ Done: - EnableReadOnlyPageWriteProtect (); - } - -+ if (CsvIsEnabled () && Status == EFI_SUCCESS) { -+ if (Mode == ClearCBit) -+ CsvUpdateMemory (PageAddress, PageNum, TRUE); -+ else -+ CsvUpdateMemory (PageAddress, PageNum, FALSE); -+ } -+ - return Status; - } - --- -2.17.1 - diff --git a/0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch b/0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch deleted file mode 100644 index 0bf6d40..0000000 --- a/0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch +++ /dev/null @@ -1,616 +0,0 @@ -From 4569ddd201843a1fd1e9b0431e971cd4edefff5d Mon Sep 17 00:00:00 2001 -From: Liu Zixing -Date: Fri, 25 Feb 2022 16:34:25 +0800 -Subject: [PATCH 36/46] anolis: OvmfPkg: Add CsvDxe driver - -CsvDxe creates and installs the CsvSharedMemory protocol. - -CSV VM needs the shared memory to exchange data with external devices. - -To improve the performance, CsvSharedMemory protocol pre-allocates -huge shared memory chunk as a pool. - -When reqeusted, it allocates small pieces of shared memory from the -pool and records the allocated memory in a list. - -When finished, the shared memory pieces are returned to the pool and -removed from the record list. - -Signed-off-by: Xin Jiang -Change-Id: I6b41c6e1af34b4f8ad58a61cce2e7fd8e8b5795b ---- - OvmfPkg/CsvDxe/CsvDxe.c | 104 +++++++++++ - OvmfPkg/CsvDxe/CsvDxe.inf | 45 +++++ - OvmfPkg/CsvDxe/CsvSharedMemory.c | 208 +++++++++++++++++++++ - OvmfPkg/CsvDxe/CsvSharedMemory.h | 29 +++ - OvmfPkg/Include/Protocol/CsvSharedMemory.h | 99 ++++++++++ - OvmfPkg/OvmfPkg.dec | 1 + - OvmfPkg/OvmfPkgIa32X64.dsc | 1 + - OvmfPkg/OvmfPkgIa32X64.fdf | 1 + - OvmfPkg/OvmfPkgX64.dsc | 1 + - OvmfPkg/OvmfPkgX64.fdf | 1 + - 10 files changed, 490 insertions(+) - create mode 100644 OvmfPkg/CsvDxe/CsvDxe.c - create mode 100644 OvmfPkg/CsvDxe/CsvDxe.inf - create mode 100644 OvmfPkg/CsvDxe/CsvSharedMemory.c - create mode 100644 OvmfPkg/CsvDxe/CsvSharedMemory.h - create mode 100644 OvmfPkg/Include/Protocol/CsvSharedMemory.h - -diff --git a/OvmfPkg/CsvDxe/CsvDxe.c b/OvmfPkg/CsvDxe/CsvDxe.c -new file mode 100644 -index 0000000..552f3cf ---- /dev/null -+++ b/OvmfPkg/CsvDxe/CsvDxe.c -@@ -0,0 +1,104 @@ -+/** @file -+ -+ Hygon CSV DXE. -+ -+ Copyright (c) 2022, HYGON. All rights reserved.
-+ -+ This program and the accompanying materials are licensed and made available -+ under the terms and conditions of the BSD License which accompanies this -+ distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT -+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ -+**/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "CsvSharedMemory.h" -+ -+ -+#define HUGE_PAGE_SIZE 0x200000ULL -+ -+EFI_STATUS -+EFIAPI -+CsvDxeEntryPoint ( -+ IN EFI_HANDLE ImageHandle, -+ IN EFI_SYSTEM_TABLE *SystemTable -+ ) -+{ -+ EFI_STATUS Status; -+ RETURN_STATUS DecryptStatus; -+ CSV_SHARED_MEMORY_PROTOCOL *SharedMemory; -+ EFI_PHYSICAL_ADDRESS Memory; -+ EFI_PHYSICAL_ADDRESS EndMemory; -+ EFI_ALLOCATE_TYPE AllocateType; -+ UINT64 Size; -+ -+ Status = CsvInstallSharedMemoryProtocol (); -+ -+ if (EFI_ERROR (Status)) { -+ DEBUG ((EFI_D_ERROR, "fail to install CsvSharedMemory protocol\n")); -+ return Status; -+ } -+ -+ // -+ // Do nothing more when CSV is not enabled -+ // -+ if (!CsvIsEnabled ()) { -+ return EFI_SUCCESS; -+ } -+ -+ Status = gBS->LocateProtocol ( -+ &gCsvSharedMemoryProtocolGuid, -+ NULL, -+ (VOID**)&SharedMemory -+ ); -+ -+ if (Status == EFI_SUCCESS) { -+ -+ AllocateType = AllocateMaxAddress; -+ Memory = BASE_4GB - 1; -+ -+ Status = gBS->AllocatePages ( -+ AllocateType, -+ EfiBootServicesData, -+ CSV_SHARED_MEMORY_PAGE_NUMBER, -+ &Memory -+ ); -+ -+ if (EFI_ERROR (Status)) { -+ DEBUG ((DEBUG_ERROR, "fail to allocate CsvSharedMemory\n", SharedMemory)); -+ } else { -+ //Align to huge page -+ EndMemory = (Memory + CSV_SHARED_MEMORY_SIZE) & (~(HUGE_PAGE_SIZE - 1)); -+ Memory = ALIGN_VALUE(Memory, HUGE_PAGE_SIZE); -+ Size = (EndMemory > Memory) ? EndMemory - Memory : 0; -+ DecryptStatus = MemEncryptSevClearPageEncMask ( -+ 0, -+ Memory, -+ Size >> EFI_PAGE_SHIFT -+ ); -+ ASSERT_RETURN_ERROR (DecryptStatus); -+ -+ SharedMemory->CsvInitializeSharedMemoryList ( -+ SharedMemory, -+ (UINT64)Memory, -+ Size -+ ); -+ } -+ } else { -+ DEBUG ((DEBUG_ERROR, "fail to LocateProtocol gCsvSharedMemoryProtocolGuid\n")); -+ } -+ -+ return EFI_SUCCESS; -+} -diff --git a/OvmfPkg/CsvDxe/CsvDxe.inf b/OvmfPkg/CsvDxe/CsvDxe.inf -new file mode 100644 -index 0000000..89e3703 ---- /dev/null -+++ b/OvmfPkg/CsvDxe/CsvDxe.inf -@@ -0,0 +1,45 @@ -+#/** @file -+# -+# Secure Isolated Virtualization -+# -+# Copyright (c) 2022, HYGON Inc. All rights reserved.
-+# -+# This program and the accompanying materials are licensed and made available -+# under the terms and conditions of the BSD License which accompanies this -+# distribution. The full text of the license may be found at -+# http://opensource.org/licenses/bsd-license.php -+# -+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR -+# IMPLIED. -+# -+#**/ -+ -+[Defines] -+ INF_VERSION = 1.25 -+ BASE_NAME = CsvDxe -+ FILE_GUID = 829310c0-b9c4-11e9-9e16-9b10d744f884 -+ MODULE_TYPE = DXE_DRIVER -+ VERSION_STRING = 1.0 -+ ENTRY_POINT = CsvDxeEntryPoint -+ -+[Sources] -+ CsvDxe.c -+ CsvSharedMemory.c -+ -+[Packages] -+ MdePkg/MdePkg.dec -+ OvmfPkg/OvmfPkg.dec -+ -+[LibraryClasses] -+ BaseLib -+ BaseMemoryLib -+ DebugLib -+ CsvLib -+ UefiDriverEntryPoint -+ -+[Depex] -+ TRUE -+ -+[Protocols] -+ gCsvSharedMemoryProtocolGuid -diff --git a/OvmfPkg/CsvDxe/CsvSharedMemory.c b/OvmfPkg/CsvDxe/CsvSharedMemory.c -new file mode 100644 -index 0000000..8674eaf ---- /dev/null -+++ b/OvmfPkg/CsvDxe/CsvSharedMemory.c -@@ -0,0 +1,208 @@ -+/** @file -+ -+ The protocol provides allocate, free the CSV shared memory. -+ -+ Copyright (c) 2022, HYGON. All rights reserved.
-+ -+ This program and the accompanying materials are licensed and made available -+ under the terms and conditions of the BSD License which accompanies this -+ distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ -+**/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+STATIC LIST_ENTRY CsvSharedMemoryList = INITIALIZE_LIST_HEAD_VARIABLE (CsvSharedMemoryList); -+ -+// -+// Insert the initial shared memory address and length to list. -+// -+ -+EFI_STATUS -+EFIAPI -+CsvInitializeSharedMemoryList ( -+ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol, -+ IN UINT64 Address, -+ IN UINT64 Length -+ ) -+{ -+ CsvSharedMemoryEntry *Entry; -+ -+ if (Length == 0) { -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ Entry = AllocatePool (sizeof (*Entry)); -+ if (Entry == NULL) { -+ DEBUG((DEBUG_ERROR, "CsvInitializeSharedMemoryList AllocatePool error\n")); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ Entry->Start = Address; -+ Entry->Length = Length; -+ Entry->Signature = CSV_SHARED_MEMORY_SIGNATURE; -+ -+ InsertTailList (&CsvSharedMemoryList, &Entry->Link); -+ -+ return EFI_SUCCESS; -+} -+ -+EFI_STATUS -+EFIAPI -+CsvAllocateSharedMemory ( -+ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol, -+ IN UINTN NumberOfPages, -+ OUT UINT64 *Memory -+ ) -+{ -+ LIST_ENTRY *Link; -+ CsvSharedMemoryEntry *Entry; -+ UINT64 MemoryLength; -+ -+ MemoryLength = (UINT64)NumberOfPages << EFI_PAGE_SHIFT; -+ -+ for (Link = CsvSharedMemoryList.ForwardLink; Link != &CsvSharedMemoryList; Link = Link->ForwardLink) { -+ Entry = CR (Link, CsvSharedMemoryEntry, Link, CSV_SHARED_MEMORY_SIGNATURE); -+ if (Entry->Length > MemoryLength) { -+ *Memory = (EFI_PHYSICAL_ADDRESS)Entry->Start; -+ Entry->Start = *Memory + MemoryLength; -+ Entry->Length -= MemoryLength; -+ break; -+ } else if (Entry->Length == MemoryLength) { -+ *Memory = (EFI_PHYSICAL_ADDRESS)Entry->Start; -+ RemoveEntryList (&Entry->Link); -+ FreePool (Entry); -+ break; -+ } -+ } -+ -+ -+ -+ if (Link == &CsvSharedMemoryList) { -+ DEBUG ((EFI_D_ERROR, "CsvAllocateSharedMemory fail to allocate %u pages\n", NumberOfPages)); -+ return EFI_NOT_FOUND; -+ } -+ else { -+ return EFI_SUCCESS; -+ } -+} -+ -+ -+ -+EFI_STATUS -+EFIAPI -+CsvFreeSharedMemory ( -+ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol, -+ IN UINTN Pages, -+ IN UINT64 HostAddress -+ ) -+{ -+ LIST_ENTRY *Link; -+ CsvSharedMemoryEntry *Entry; -+ CsvSharedMemoryEntry *NewEntry; -+ UINT64 Memory; -+ UINT64 MemoryLength; -+ CsvSharedMemoryEntry *Previous = NULL; -+ BOOLEAN Inserted = FALSE; -+ -+ Memory = (UINT64)HostAddress; -+ MemoryLength = (UINT64)Pages << EFI_PAGE_SHIFT; -+ -+ for (Link = CsvSharedMemoryList.ForwardLink; -+ Link != &CsvSharedMemoryList; -+ Link = Link->ForwardLink) { -+ Entry = CR (Link, CsvSharedMemoryEntry, Link, CSV_SHARED_MEMORY_SIGNATURE); -+ if (Inserted) -+ goto Merge; -+ if (Entry->Start + Entry->Length == Memory) { -+ Entry->Length += MemoryLength; -+ Inserted = TRUE; -+ goto Merge; -+ } else if (Memory + MemoryLength < Entry->Start) { -+ NewEntry = AllocatePool (sizeof *NewEntry); -+ if (NewEntry == NULL) { -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ NewEntry->Start = Memory; -+ NewEntry->Length = MemoryLength; -+ NewEntry->Signature = CSV_SHARED_MEMORY_SIGNATURE; -+ -+ InsertTailList (&Entry->Link, &NewEntry->Link); -+ break; -+ } else if (Memory + MemoryLength == Entry->Start) { -+ Entry->Start = Memory; -+ Entry->Length += MemoryLength; -+ break; -+ } else if (Link->ForwardLink == &CsvSharedMemoryList) { -+ // -+ // Insert to tail -+ // -+ NewEntry = AllocatePool (sizeof *NewEntry); -+ if (NewEntry == NULL) { -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ NewEntry->Start = Memory; -+ NewEntry->Length = MemoryLength; -+ NewEntry->Signature = CSV_SHARED_MEMORY_SIGNATURE; -+ InsertHeadList (Link, &NewEntry->Link); -+ break; -+ } -+ -+Merge: -+ if (Previous) { -+ if (Previous->Start + Previous->Length == Entry->Start) { -+ Entry->Start = Previous->Start; -+ Entry->Length += Previous->Length; -+ RemoveEntryList (&Previous->Link); -+ FreePool (Previous); -+ } -+ break; -+ } else { -+ Previous = Entry; -+ } -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+CSV_SHARED_MEMORY_PROTOCOL mCsvSharedMemory = { -+ CsvInitializeSharedMemoryList, -+ CsvAllocateSharedMemory, -+ CsvFreeSharedMemory -+}; -+ -+/** -+ Initialize CsvSharedMemory Protocol. -+ -+**/ -+EFI_STATUS -+EFIAPI -+CsvInstallSharedMemoryProtocol ( -+ VOID -+ ) -+{ -+ EFI_STATUS Status; -+ EFI_HANDLE Handle; -+ -+ Handle = NULL; -+ Status = gBS->InstallMultipleProtocolInterfaces ( -+ &Handle, -+ &gCsvSharedMemoryProtocolGuid, -+ &mCsvSharedMemory, -+ NULL -+ ); -+ return Status; -+} -diff --git a/OvmfPkg/CsvDxe/CsvSharedMemory.h b/OvmfPkg/CsvDxe/CsvSharedMemory.h -new file mode 100644 -index 0000000..8828515 ---- /dev/null -+++ b/OvmfPkg/CsvDxe/CsvSharedMemory.h -@@ -0,0 +1,29 @@ -+/** @file -+ CSV shared memory management protocol -+ -+ Copyright (C) 2022 HYGON. -+ -+ This program and the accompanying materials -+ are licensed and made available under the terms and conditions of the BSD License -+ which accompanies this distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ -+**/ -+ -+#ifndef _CSV_SHARED_MEMORY_H_ -+#define _CSV_SHARED_MEMORY_H_ -+ -+// -+// Install SHARED_MEMORY protocol . -+// -+ -+EFI_STATUS -+EFIAPI -+CsvInstallSharedMemoryProtocol ( -+ VOID -+ ); -+ -+#endif -diff --git a/OvmfPkg/Include/Protocol/CsvSharedMemory.h b/OvmfPkg/Include/Protocol/CsvSharedMemory.h -new file mode 100644 -index 0000000..0c3f23d ---- /dev/null -+++ b/OvmfPkg/Include/Protocol/CsvSharedMemory.h -@@ -0,0 +1,99 @@ -+/** @file -+ CSV shared memory management protocol -+ -+ Copyright (C) 2022 HYGON. -+ -+ This program and the accompanying materials -+ are licensed and made available under the terms and conditions of the BSD License -+ which accompanies this distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ -+**/ -+ -+#ifndef __PROTOCOL_CSV_SHARED_MEMORY_H__ -+#define __PROTOCOL_CSV_SHARED_MEMORY_H__ -+ -+#define CSV_SHARED_MEMORY_PAGE_NUMBER (16384ULL) -+#define CSV_SHARED_MEMORY_SIZE ((CSV_SHARED_MEMORY_PAGE_NUMBER)*(SIZE_4KB)) -+ -+/// -+/// Forward declaration -+/// -+typedef struct _CSV_SHARED_MEMORY_PROTOCOL CSV_SHARED_MEMORY_PROTOCOL; -+ -+ -+/// -+/// Function prototypes -+/// -+ -+/** -+ Initialize the list to manage the CSV shared memory. -+ Insert the start address and length. -+ -+ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance. -+ @param Address The start address of the shared memory. -+ @param Length The length of the shared memory. -+ -+**/ -+typedef -+EFI_STATUS -+(EFIAPI *CSV_INITIALIZE_SHARED_MEMORY_LIST)( -+ IN CSV_SHARED_MEMORY_PROTOCOL *This, -+ IN UINT64 Address, -+ IN UINT64 Length -+ ); -+ -+/** -+ Allocate buffer from the shared memory. -+ -+ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance. -+ @param NumberOfPages The length of page number. -+ @param Memory When success, allocated memory will be stored in. -+ -+ @return On success, EFI_SUCCESS. Otherwise an errno value -+ indicating the type of failure. -+**/ -+typedef -+EFI_STATUS -+(EFIAPI *CSV_ALLOCATE_SHARED_MEMORY)( -+ IN CSV_SHARED_MEMORY_PROTOCOL *This, -+ IN UINTN NumberOfPages, -+ OUT UINT64 *Memory -+ ); -+ -+/** -+ Free buffer to the shared memory. -+ -+ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance. -+ @param NumberOfPages The page number. -+ @param Memory The allocated memory to be freed. -+ -+ @return On success, EFI_SUCCESS. Otherwise an errno value -+ indicating the type of failure. -+**/ -+typedef -+EFI_STATUS -+(EFIAPI *CSV_FREE_SHARED_MEMORY)( -+ IN CSV_SHARED_MEMORY_PROTOCOL *This, -+ IN UINTN NumberOfPages, -+ IN UINT64 Memory -+ ); -+ -+/// -+/// Protocol structure -+/// -+struct _CSV_SHARED_MEMORY_PROTOCOL { -+ // -+ // Protocol data fields -+ // -+ CSV_INITIALIZE_SHARED_MEMORY_LIST CsvInitializeSharedMemoryList; -+ CSV_ALLOCATE_SHARED_MEMORY CsvAllocateSharedMemory; -+ CSV_FREE_SHARED_MEMORY CsvFreeSharedMemory; -+}; -+ -+extern EFI_GUID gCsvSharedMemoryProtocolGuid; -+ -+#endif -diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec -index 6f4afb8..d8f9be3 100644 ---- a/OvmfPkg/OvmfPkg.dec -+++ b/OvmfPkg/OvmfPkg.dec -@@ -152,6 +152,7 @@ - gEfiLegacyInterruptProtocolGuid = {0x31ce593d, 0x108a, 0x485d, {0xad, 0xb2, 0x78, 0xf2, 0x1f, 0x29, 0x66, 0xbe}} - gEfiVgaMiniPortProtocolGuid = {0xc7735a2f, 0x88f5, 0x4882, {0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3}} - gOvmfLoadedX86LinuxKernelProtocolGuid = {0xa3edc05d, 0xb618, 0x4ff6, {0x95, 0x52, 0x76, 0xd7, 0x88, 0x63, 0x43, 0xc8}} -+ gCsvSharedMemoryProtocolGuid = {0x0c795ed0, 0xbf0a, 0x11e9, {0x99, 0xbe, 0x50, 0x9a, 0x4c, 0x01, 0x1e, 0xd1}} - - [PcdsFixedAtBuild] - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0 -diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc -index 9e4dcce..edc0f0e 100644 ---- a/OvmfPkg/OvmfPkgIa32X64.dsc -+++ b/OvmfPkg/OvmfPkgIa32X64.dsc -@@ -982,6 +982,7 @@ - OvmfPkg/PlatformDxe/Platform.inf - OvmfPkg/AmdSevDxe/AmdSevDxe.inf - OvmfPkg/IoMmuDxe/IoMmuDxe.inf -+ OvmfPkg/CsvDxe/CsvDxe.inf - - !if $(SMM_REQUIRE) == TRUE - OvmfPkg/SmmAccess/SmmAccess2Dxe.inf -diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf -index e33a40c..f05405b 100644 ---- a/OvmfPkg/OvmfPkgIa32X64.fdf -+++ b/OvmfPkg/OvmfPkgIa32X64.fdf -@@ -339,6 +339,7 @@ INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf - INF OvmfPkg/PlatformDxe/Platform.inf - INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf - INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf -+INF OvmfPkg/CsvDxe/CsvDxe.inf - - !if $(SMM_REQUIRE) == TRUE - INF OvmfPkg/SmmAccess/SmmAccess2Dxe.inf -diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc -index e62b533..763214d 100644 ---- a/OvmfPkg/OvmfPkgX64.dsc -+++ b/OvmfPkg/OvmfPkgX64.dsc -@@ -980,6 +980,7 @@ - OvmfPkg/PlatformDxe/Platform.inf - OvmfPkg/AmdSevDxe/AmdSevDxe.inf - OvmfPkg/IoMmuDxe/IoMmuDxe.inf -+ OvmfPkg/CsvDxe/CsvDxe.inf - - !if $(SMM_REQUIRE) == TRUE - OvmfPkg/SmmAccess/SmmAccess2Dxe.inf -diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf -index a3634dd..0f04acb 100644 ---- a/OvmfPkg/OvmfPkgX64.fdf -+++ b/OvmfPkg/OvmfPkgX64.fdf -@@ -358,6 +358,7 @@ INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf - INF OvmfPkg/PlatformDxe/Platform.inf - INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf - INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf -+INF OvmfPkg/CsvDxe/CsvDxe.inf - - !if $(SMM_REQUIRE) == TRUE - INF OvmfPkg/SmmAccess/SmmAccess2Dxe.inf --- -2.17.1 - diff --git a/0037-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch b/0037-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch deleted file mode 100644 index 9b4b800..0000000 --- a/0037-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch +++ /dev/null @@ -1,724 +0,0 @@ -From 8f82f4b8d86ca1b10b9353b484c403c628b3b560 Mon Sep 17 00:00:00 2001 -From: Liu Zixing -Date: Fri, 25 Feb 2022 16:54:44 +0800 -Subject: [PATCH 37/46] anolis: OvmfPkg/IoMmuDxe: Add CsvIoMmu protocol - -Create the dedicated IoMmu protocol for CSV virtual machine. -And Install it during CSV VM boots up. - -It calls the CsvSharedMemoryProtocol to allocate shared memory -for DMA operations. - -- AllocateBuffer() allocates the shared memory. - -- FreeBuffer() frees the shared memory. - -- Map() does nothing when BusMasterCommonBuffer[64] is requested - Otherwise, Map() allocates shared memory. - -- Unmap() does nothing when cleaning up a BusMasterCommonBuffer[64] - operation. Otherwise, Unmap() frees the shared memory. - -Signed-off-by: Xin Jiang -Change-Id: If49857f45c639341a96605722b06babfa1553874 ---- - OvmfPkg/IoMmuDxe/CsvIoMmu.c | 592 ++++++++++++++++++++++++++++++++++ - OvmfPkg/IoMmuDxe/CsvIoMmu.h | 29 ++ - OvmfPkg/IoMmuDxe/IoMmuDxe.c | 10 + - OvmfPkg/IoMmuDxe/IoMmuDxe.inf | 6 +- - 4 files changed, 636 insertions(+), 1 deletion(-) - create mode 100644 OvmfPkg/IoMmuDxe/CsvIoMmu.c - create mode 100644 OvmfPkg/IoMmuDxe/CsvIoMmu.h - -diff --git a/OvmfPkg/IoMmuDxe/CsvIoMmu.c b/OvmfPkg/IoMmuDxe/CsvIoMmu.c -new file mode 100644 -index 0000000..c5df6b9 ---- /dev/null -+++ b/OvmfPkg/IoMmuDxe/CsvIoMmu.c -@@ -0,0 +1,592 @@ -+/** @file -+ -+ The protocol provides support to allocate, free, map and umap a DMA buffer -+ for bus master (e.g PciHostBridge). When CSV is enabled, the DMA operations -+ must be performed on non-secure memory so we have to allocate the DMA buffer -+ from non-secure memory. -+ -+ Copyright (c) 2022, HYGON. All rights reserved.
-+ -+ This program and the accompanying materials are licensed and made available -+ under the terms and conditions of the BSD License which accompanies this -+ distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ -+**/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "CsvIoMmu.h" -+ -+#define MAP_INFO_SIG SIGNATURE_64 ('M', 'A', 'P', '_', 'I', 'N', 'F', 'O') -+ -+typedef struct { -+ UINT64 Signature; -+ LIST_ENTRY Link; -+ EDKII_IOMMU_OPERATION Operation; -+ UINTN NumberOfBytes; -+ UINTN NumberOfPages; -+ EFI_PHYSICAL_ADDRESS SecureAddress; -+ EFI_PHYSICAL_ADDRESS UnSecureAddress; -+} MAP_INFO; -+ -+// -+// List of the MAP_INFO structures that have been set up by IoMmuMap() and not -+// yet torn down by IoMmuUnmap(). The list represents the full set of mappings -+// currently in effect. -+// -+STATIC LIST_ENTRY mMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (mMapInfos); -+ -+// -+// ASCII names for EDKII_IOMMU_OPERATION constants, for debug logging. -+// -+STATIC CONST CHAR8 * CONST -+mBusMasterOperationName[EdkiiIoMmuOperationMaximum] = { -+ "Read", -+ "Write", -+ "CommonBuffer", -+ "Read64", -+ "Write64", -+ "CommonBuffer64" -+}; -+ -+STATIC CSV_SHARED_MEMORY_PROTOCOL *SharedMemory; -+STATIC -+EFI_STATUS -+EFIAPI -+CsvAllocSharedPage( -+ IN UINTN Pages, -+ OUT EFI_PHYSICAL_ADDRESS *Address -+ ) -+{ -+ EFI_STATUS Status; -+ -+ Status = SharedMemory->CsvAllocateSharedMemory ( -+ SharedMemory, -+ Pages, -+ (UINT64*)Address -+ ); -+ -+ return Status; -+} -+ -+STATIC -+EFI_STATUS -+EFIAPI -+CsvFreeSharedPage( -+ IN UINTN Pages, -+ IN VOID *HostAddress -+ ) -+{ -+ EFI_STATUS Status; -+ -+ Status = SharedMemory->CsvFreeSharedMemory ( -+ SharedMemory, -+ Pages, -+ (UINTN)HostAddress -+ ); -+ -+ return Status; -+} -+ -+/** -+ Provides the controller-specific addresses required to access system memory -+ from a DMA bus master. -+ On CSV guest, the DMA openerations must be done on non-secure memory which -+ is the shared memory between the guest and QEMU. -+ -+ @param This The protocol instance pointer. -+ @param Operation Indicates if the bus master is going to read or -+ write to system memory. -+ @param HostAddress The system memory address to map to the PCI -+ controller. -+ @param NumberOfBytes On input the number of bytes to map. On output -+ the number of bytes that were mapped. -+ @param DeviceAddress The resulting map address for the bus master -+ PCI controller to use to access the hosts -+ HostAddress. -+ @param Mapping A resulting value to pass to Unmap(). -+ -+ @retval EFI_SUCCESS The range was mapped for the returned -+ NumberOfBytes. -+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common -+ buffer. -+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid. -+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a -+ lack of resources. -+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested -+ address. -+ -+**/ -+EFI_STATUS -+EFIAPI -+CsvIoMmuMap ( -+ IN EDKII_IOMMU_PROTOCOL *This, -+ IN EDKII_IOMMU_OPERATION Operation, -+ IN VOID *HostAddress, -+ IN OUT UINTN *NumberOfBytes, -+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, -+ OUT VOID **Mapping -+ ) -+{ -+ EFI_STATUS Status; -+ MAP_INFO *MapInfo; -+ -+ DEBUG (( -+ DEBUG_VERBOSE, -+ "%a: Operation=%a Operation=%u Host=0x%p Bytes=0x%Lx\n", -+ __FUNCTION__, -+ ((Operation >= 0 && -+ Operation < ARRAY_SIZE (mBusMasterOperationName)) ? -+ mBusMasterOperationName[Operation] : -+ "Invalid"), -+ Operation, -+ HostAddress, -+ (UINT64)((NumberOfBytes == NULL) ? 0 : *NumberOfBytes) -+ )); -+ -+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || -+ Mapping == NULL) { -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ // -+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is -+ // called later. -+ // -+ MapInfo = AllocatePool (sizeof (MAP_INFO)); -+ if (MapInfo == NULL) { -+ Status = EFI_OUT_OF_RESOURCES; -+ goto Failed; -+ } -+ -+ ZeroMem (&MapInfo->Link, sizeof MapInfo->Link); -+ MapInfo->Operation = Operation; -+ MapInfo->NumberOfBytes = *NumberOfBytes; -+ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes); -+ MapInfo->Signature = MAP_INFO_SIG; -+ -+ switch (Operation) { -+ // -+ // For BusMasterRead[64] and BusMasterWrite[64] operations, a bounce buffer -+ // is necessary regardless of whether the original (crypted) buffer crosses -+ // the 4GB limit or not -- we have to allocate a separate plaintext buffer. -+ // The only variable is whether the plaintext buffer should be under 4GB. -+ // -+ case EdkiiIoMmuOperationBusMasterRead: -+ case EdkiiIoMmuOperationBusMasterWrite: -+ // -+ // fall through -+ // -+ case EdkiiIoMmuOperationBusMasterRead64: -+ case EdkiiIoMmuOperationBusMasterWrite64: -+ // -+ // Allocate the implicit plaintext bounce buffer. -+ // -+ Status = CsvAllocSharedPage ( -+ MapInfo->NumberOfPages, -+ &MapInfo->UnSecureAddress -+ ); -+ if (EFI_ERROR (Status)) { -+ goto FreeMapInfo; -+ } -+ MapInfo->SecureAddress = (UINTN)HostAddress; -+ if (Operation == EdkiiIoMmuOperationBusMasterRead || -+ Operation == EdkiiIoMmuOperationBusMasterRead64) { -+ CopyMem ( -+ (VOID *) (UINTN) MapInfo->UnSecureAddress, -+ (VOID *) (UINTN) MapInfo->SecureAddress, -+ MapInfo->NumberOfBytes -+ ); -+ } -+ break; -+ -+ // -+ // For BusMasterCommonBuffer[64] operations, -+ // AllocateBuffer already returns the plain-text, -+ // No need to decrypt the data. -+ // -+ case EdkiiIoMmuOperationBusMasterCommonBuffer: -+ case EdkiiIoMmuOperationBusMasterCommonBuffer64: -+ MapInfo->UnSecureAddress = (UINTN)HostAddress; -+ MapInfo->SecureAddress = (UINTN)HostAddress; -+ break; -+ -+ default: -+ // -+ // Operation is invalid -+ // -+ Status = EFI_INVALID_PARAMETER; -+ goto FreeMapInfo; -+ } -+ -+ // -+ // Track all MAP_INFO structures. -+ // -+ InsertHeadList (&mMapInfos, &MapInfo->Link); -+ // -+ // Populate output parameters. -+ // -+ *DeviceAddress = MapInfo->UnSecureAddress; -+ *Mapping = MapInfo; -+ -+ DEBUG (( -+ DEBUG_VERBOSE, -+ "%a: Mapping=0x%p Device=0x%Lx Host=0x%Lx Pages=0x%Lx\n", -+ __FUNCTION__, -+ MapInfo, -+ MapInfo->UnSecureAddress, -+ MapInfo->SecureAddress, -+ (UINT64)MapInfo->NumberOfPages -+ )); -+ -+ return EFI_SUCCESS; -+ -+FreeMapInfo: -+ FreePool (MapInfo); -+ -+Failed: -+ *NumberOfBytes = 0; -+ return Status; -+} -+ -+/** -+ Completes the Map() operation and releases any corresponding resources. -+ -+ This is an internal worker function that only extends the Map() API with -+ the MemoryMapLocked parameter. -+ -+ @param This The protocol instance pointer. -+ @param Mapping The mapping value returned from Map(). -+ @param MemoryMapLocked The function is executing on the stack of -+ gBS->ExitBootServices(); changes to the UEFI -+ memory map are forbidden. -+ -+ @retval EFI_SUCCESS The range was unmapped. -+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by -+ Map(). -+ @retval EFI_DEVICE_ERROR The data was not committed to the target system -+ memory. -+**/ -+STATIC -+EFI_STATUS -+EFIAPI -+CsvIoMmuUnmapWorker ( -+ IN EDKII_IOMMU_PROTOCOL *This, -+ IN VOID *Mapping, -+ IN BOOLEAN MemoryMapLocked -+ ) -+{ -+ MAP_INFO *MapInfo; -+ EDKII_IOMMU_OPERATION Operation; -+ -+ if (Mapping == NULL) { -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ MapInfo = (MAP_INFO *)Mapping; -+ Operation = MapInfo->Operation; -+ -+ DEBUG (( -+ DEBUG_VERBOSE, -+ "%a: Mapping=0x%p MemoryMapLocked=%d Operation %a Operation %d\n", -+ __FUNCTION__, -+ Mapping, -+ MemoryMapLocked, -+ ((Operation >= 0 && -+ Operation < ARRAY_SIZE (mBusMasterOperationName)) ? -+ mBusMasterOperationName[Operation] : -+ "Invalid"), -+ Operation -+ )); -+ -+ switch (MapInfo->Operation) { -+ case EdkiiIoMmuOperationBusMasterWrite: -+ case EdkiiIoMmuOperationBusMasterWrite64: -+ CopyMem ( -+ (VOID *) (UINTN) MapInfo->SecureAddress, -+ (VOID *) (UINTN) MapInfo->UnSecureAddress, -+ MapInfo->NumberOfBytes -+ ); -+ case EdkiiIoMmuOperationBusMasterRead: -+ case EdkiiIoMmuOperationBusMasterRead64: -+ ZeroMem ( -+ (VOID *)(UINTN)MapInfo->UnSecureAddress, -+ EFI_PAGES_TO_SIZE (MapInfo->NumberOfPages) -+ ); -+ CsvFreeSharedPage( -+ MapInfo->NumberOfPages, -+ (VOID*)(UINTN)MapInfo->UnSecureAddress -+ ); -+ -+ default: -+ break; -+ } -+ -+ // -+ // Forget the MAP_INFO structure, then free it (unless the UEFI memory map is -+ // locked). -+ // -+ RemoveEntryList (&MapInfo->Link); -+ if (!MemoryMapLocked) { -+ FreePool (MapInfo); -+ } -+ -+ return EFI_SUCCESS; -+ -+} -+ -+/** -+ Completes the Map() operation and releases any corresponding resources. -+ -+ @param This The protocol instance pointer. -+ @param Mapping The mapping value returned from Map(). -+ -+ @retval EFI_SUCCESS The range was unmapped. -+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by -+ Map(). -+ @retval EFI_DEVICE_ERROR The data was not committed to the target system -+ memory. -+**/ -+EFI_STATUS -+EFIAPI -+CsvIoMmuUnmap ( -+ IN EDKII_IOMMU_PROTOCOL *This, -+ IN VOID *Mapping -+ ) -+{ -+ return CsvIoMmuUnmapWorker ( -+ This, -+ Mapping, -+ FALSE // MemoryMapLocked -+ ); -+} -+ -+/** -+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer or -+ OperationBusMasterCommonBuffer64 mapping. -+ -+ @param This The protocol instance pointer. -+ @param Type This parameter is not used and must be ignored. -+ @param MemoryType The type of memory to allocate, -+ EfiBootServicesData or EfiRuntimeServicesData. -+ @param Pages The number of pages to allocate. -+ @param HostAddress A pointer to store the base system memory -+ address of the allocated range. -+ @param Attributes The requested bit mask of attributes for the -+ allocated range. -+ -+ @retval EFI_SUCCESS The requested memory pages were allocated. -+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal -+ attribute bits are MEMORY_WRITE_COMBINE and -+ MEMORY_CACHED. -+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid. -+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. -+ -+**/ -+EFI_STATUS -+EFIAPI -+CsvIoMmuAllocateBuffer ( -+ IN EDKII_IOMMU_PROTOCOL *This, -+ IN EFI_ALLOCATE_TYPE Type, -+ IN EFI_MEMORY_TYPE MemoryType, -+ IN UINTN Pages, -+ IN OUT VOID **HostAddress, -+ IN UINT64 Attributes -+ ) -+{ -+ EFI_STATUS Status; -+ EFI_PHYSICAL_ADDRESS PhysicalAddress; -+ -+ DEBUG (( -+ DEBUG_VERBOSE, -+ "%a: MemoryType=%u Pages=0x%Lx Attributes=0x%Lx\n", -+ __FUNCTION__, -+ (UINT32)MemoryType, -+ (UINT64)Pages, -+ Attributes -+ )); -+ -+ // -+ // Validate Attributes -+ // -+ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) { -+ return EFI_UNSUPPORTED; -+ } -+ -+ // -+ // Check for invalid inputs -+ // -+ if (HostAddress == NULL) { -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ // -+ // The only valid memory types are EfiBootServicesData and -+ // EfiRuntimeServicesData -+ // -+ if (MemoryType != EfiBootServicesData && -+ MemoryType != EfiRuntimeServicesData) { -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ // -+ // We'll need a header page for the COMMON_BUFFER_HEADER structure. -+ // -+ if (Pages > MAX_UINTN - 1) { -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ Status = CsvAllocSharedPage (Pages,&PhysicalAddress); -+ if (Status != EFI_SUCCESS){ -+ goto error; -+ } -+ -+ -+ *HostAddress = (VOID *)(UINTN)PhysicalAddress; -+ -+ return EFI_SUCCESS; -+ -+error: -+ return Status; -+} -+ -+/** -+ Frees memory that was allocated with AllocateBuffer(). -+ -+ @param This The protocol instance pointer. -+ @param Pages The number of pages to free. -+ @param HostAddress The base system memory address of the allocated -+ range. -+ -+ @retval EFI_SUCCESS The requested memory pages were freed. -+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and -+ Pages was not allocated with AllocateBuffer(). -+ -+**/ -+EFI_STATUS -+EFIAPI -+CsvIoMmuFreeBuffer ( -+ IN EDKII_IOMMU_PROTOCOL *This, -+ IN UINTN Pages, -+ IN VOID *HostAddress -+ ) -+{ -+ -+ EFI_STATUS Status; -+ -+ if (HostAddress == NULL || Pages == 0) { -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ DEBUG (( -+ DEBUG_VERBOSE, -+ "%a: Host=0x%p Pages=0x%Lx\n", -+ __FUNCTION__, -+ HostAddress, -+ (UINT64)Pages -+ )); -+ -+ Status = CsvFreeSharedPage (Pages, HostAddress); -+ -+ return Status; -+} -+ -+ -+/** -+ Set IOMMU attribute for a system memory. -+ -+ @param[in] This The protocol instance pointer. -+ @param[in] DeviceHandle The device who initiates the DMA access -+ request. -+ @param[in] Mapping The mapping value returned from Map(). -+ @param[in] IoMmuAccess The IOMMU access. -+ -+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory range -+ specified by DeviceAddress and Length. -+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle. -+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by -+ Map(). -+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination -+ of access. -+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU. -+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported -+ by the IOMMU. -+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory range -+ specified by Mapping. -+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to -+ modify the IOMMU access. -+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while -+ attempting the operation. -+ -+**/ -+EFI_STATUS -+EFIAPI -+CsvIoMmuSetAttribute ( -+ IN EDKII_IOMMU_PROTOCOL *This, -+ IN EFI_HANDLE DeviceHandle, -+ IN VOID *Mapping, -+ IN UINT64 IoMmuAccess -+ ) -+{ -+ return EFI_UNSUPPORTED; -+} -+ -+EDKII_IOMMU_PROTOCOL mCsv = { -+ EDKII_IOMMU_PROTOCOL_REVISION, -+ CsvIoMmuSetAttribute, -+ CsvIoMmuMap, -+ CsvIoMmuUnmap, -+ CsvIoMmuAllocateBuffer, -+ CsvIoMmuFreeBuffer, -+}; -+ -+/** -+ Initialize Iommu Protocol. -+ -+**/ -+EFI_STATUS -+EFIAPI -+CsvInstallIoMmuProtocol ( -+ VOID -+ ) -+{ -+ EFI_STATUS Status; -+ EFI_HANDLE Handle; -+ -+ Status = gBS->LocateProtocol ( -+ &gCsvSharedMemoryProtocolGuid, -+ NULL, -+ (VOID**)&SharedMemory -+ ); -+ -+ if (EFI_ERROR (Status)) { -+ goto error; -+ } -+ -+ Handle = NULL; -+ Status = gBS->InstallMultipleProtocolInterfaces ( -+ &Handle, -+ &gEdkiiIoMmuProtocolGuid, -+ &mCsv, -+ NULL -+ ); -+ if (EFI_ERROR (Status)) { -+ goto error; -+ } -+ -+ return EFI_SUCCESS; -+ -+error: -+ return Status; -+} -diff --git a/OvmfPkg/IoMmuDxe/CsvIoMmu.h b/OvmfPkg/IoMmuDxe/CsvIoMmu.h -new file mode 100644 -index 0000000..d48a02c ---- /dev/null -+++ b/OvmfPkg/IoMmuDxe/CsvIoMmu.h -@@ -0,0 +1,29 @@ -+/** @file -+ -+ The protocol provides support to allocate, free, map and umap a DMA buffer -+ for bus master (e.g PciHostBridge). When CSV is enabled, the DMA operations -+ must be performed on unencrypted buffer hence protocol clear the encryption -+ bit from the DMA buffer. -+ -+ Copyright (c) 2022, HYGON. All rights reserved.
-+ -+ This program and the accompanying materials are licensed and made available -+ under the terms and conditions of the BSD License which accompanies this -+ distribution. The full text of the license may be found at -+ http://opensource.org/licenses/bsd-license.php -+ -+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ -+**/ -+ -+#ifndef _CSV_IOMMU_H_ -+#define _CSV_IOMMU_H_ -+ -+EFI_STATUS -+EFIAPI -+CsvInstallIoMmuProtocol ( -+ VOID -+ ); -+ -+#endif -diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.c b/OvmfPkg/IoMmuDxe/IoMmuDxe.c -index 13df8ba..35e5df9 100644 ---- a/OvmfPkg/IoMmuDxe/IoMmuDxe.c -+++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.c -@@ -9,7 +9,9 @@ - - **/ - -+#include - #include "AmdSevIoMmu.h" -+#include "CsvIoMmu.h" - - EFI_STATUS - EFIAPI -@@ -21,6 +23,14 @@ IoMmuDxeEntryPoint ( - EFI_STATUS Status; - EFI_HANDLE Handle; - -+ if (CsvIsEnabled ()) { -+ Status = CsvInstallIoMmuProtocol (); -+ if (Status != EFI_SUCCESS) { -+ DEBUG((EFI_D_ERROR, "fail to install CSV IOMMU\n")); -+ } -+ return Status; -+ } -+ - // - // When SEV is enabled, install IoMmu protocol otherwise install the - // placeholder protocol so that other dependent module can run. -diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf -index 2ebd74e..6b89c6a 100644 ---- a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf -+++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf -@@ -21,6 +21,8 @@ - AmdSevIoMmu.c - AmdSevIoMmu.h - IoMmuDxe.c -+ CsvIoMmu.c -+ CsvIoMmu.h - - [Packages] - MdePkg/MdePkg.dec -@@ -35,10 +37,12 @@ - MemoryAllocationLib - UefiBootServicesTableLib - UefiDriverEntryPoint -+ CsvLib - - [Protocols] - gEdkiiIoMmuProtocolGuid ## SOMETIME_PRODUCES - gIoMmuAbsentProtocolGuid ## SOMETIME_PRODUCES -+ gCsvSharedMemoryProtocolGuid - - [Depex] -- TRUE -+ gCsvSharedMemoryProtocolGuid --- -2.17.1 - diff --git a/0038-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch b/0038-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch deleted file mode 100644 index 6aeeadf..0000000 --- a/0038-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 8a7ac3e25c1e8a62852a64d0a303e948b0e1499a Mon Sep 17 00:00:00 2001 -From: Xin Jiang -Date: Tue, 15 Aug 2023 17:15:53 +0800 -Subject: [PATCH 38/46] anolis: OvmfPkg: Reserve a CPUID table page for CSV - guest - -Reserve a page for CPUID table which will be initialized by firmware. -In future, A CSV guest should get CPUID value from a CPUID table -which has been validated by firmware rather than requesting them from -hypervisor via a VMGEXIT. - -Signed-off-by: Xin Jiang -Change-Id: Ic09af8667c65ac83eef5a2a4a1e69d0506cd89d7 ---- - OvmfPkg/OvmfPkg.dec | 4 ++++ - OvmfPkg/OvmfPkgX64.fdf | 3 +++ - OvmfPkg/PlatformPei/Csv.c | 6 ++++++ - OvmfPkg/PlatformPei/PlatformPei.inf | 2 ++ - OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 15 +++++++++++++++ - OvmfPkg/ResetVector/ResetVector.inf | 2 ++ - OvmfPkg/ResetVector/ResetVector.nasmb | 2 ++ - 7 files changed, 34 insertions(+) - -diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec -index d8f9be3..7e6a6a2 100644 ---- a/OvmfPkg/OvmfPkg.dec -+++ b/OvmfPkg/OvmfPkg.dec -@@ -359,6 +359,10 @@ - gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|0|UINT32|0x58 - gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize|0|UINT32|0x59 - -+ ## the base address of the cpuid table page used by CSV. -+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|0|UINT32|0x60 -+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize|0|UINT32|0x61 -+ - [PcdsDynamic, PcdsDynamicEx] - gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 -diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf -index 0f04acb..04efa62 100644 ---- a/OvmfPkg/OvmfPkgX64.fdf -+++ b/OvmfPkg/OvmfPkgX64.fdf -@@ -91,6 +91,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.P - 0x00D000|0x002000 - gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize - -+0x00F000|0x001000 -+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize -+ - 0x010000|0x010000 - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize - -diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c -index 44e81e1..f7c87ac 100644 ---- a/OvmfPkg/PlatformPei/Csv.c -+++ b/OvmfPkg/PlatformPei/Csv.c -@@ -56,6 +56,12 @@ CsvInitializeMemInfo ( - (UINT64)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallSize), - EfiReservedMemoryType - ); -+ -+ BuildMemoryAllocationHob ( -+ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdOvmfCsvCpuidBase), -+ (UINT64)(UINTN) FixedPcdGet32 (PcdOvmfCsvCpuidSize), -+ EfiReservedMemoryType -+ ); - } - - VOID -diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf -index cb0582c..bed4dcf 100644 ---- a/OvmfPkg/PlatformPei/PlatformPei.inf -+++ b/OvmfPkg/PlatformPei/PlatformPei.inf -@@ -123,6 +123,8 @@ - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize - gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase - gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize -+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase -+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize - - [FeaturePcd] - gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable -diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm -index c32b608..f282692 100644 ---- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm -+++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm -@@ -63,6 +63,21 @@ csvSecureCallBase: - DB 0xAB, 0x21, 0x6B, 0x27, 0x5D, 0x55, 0x56, 0xA5 - csvSecureCallEnd: - -+; -+; CSV cpuid table -+; -+; Provide cpuid table page when boot up for CSV guest -+; -+; GUID : 1b4c70e6-07e6-4e4e-8f28-0eaf871a0752 -+; -+csvCpuidTableBase: -+ DD CSV_CPUID_TABLE_SIZE -+ DD CSV_CPUID_TABLE_BASE -+ DW csvCpuidTableEnd - csvCpuidTableBase -+ DB 0xE6, 0x70, 0x4C, 0x1B, 0xE6, 0x07, 0x4E, 0x4E -+ DB 0x8F, 0x28, 0x0E, 0xAF, 0x87, 0x1A, 0x07, 0x52 -+csvCpuidTableEnd: -+ - ; - ; TDX Metadata offset block - ; -diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf -index 38c1720..e35c17b 100644 ---- a/OvmfPkg/ResetVector/ResetVector.inf -+++ b/OvmfPkg/ResetVector/ResetVector.inf -@@ -37,6 +37,8 @@ - gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase - gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase - gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize -+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase -+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase -diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb -index ca00f64..4e7c7ad 100644 ---- a/OvmfPkg/ResetVector/ResetVector.nasmb -+++ b/OvmfPkg/ResetVector/ResetVector.nasmb -@@ -106,6 +106,8 @@ - - %define CSV_DEFAULT_SECURE_CALL_BASE FixedPcdGet32 (PcdCsvDefaultSecureCallBase) - %define CSV_DEFAULT_SECURE_CALL_SIZE FixedPcdGet32 (PcdCsvDefaultSecureCallSize) -+ %define CSV_CPUID_TABLE_BASE FixedPcdGet32 (PcdOvmfCsvCpuidBase) -+ %define CSV_CPUID_TABLE_SIZE FixedPcdGet32 (PcdOvmfCsvCpuidSize) - - %include "X64/IntelTdxMetadata.asm" - %include "Ia32/Flat32ToFlat64.asm" --- -2.17.1 - diff --git a/0039-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch b/0039-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch deleted file mode 100644 index a8c2c34..0000000 --- a/0039-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch +++ /dev/null @@ -1,325 +0,0 @@ -From 118d8bd819dfd2300798481d8c89a9c37e54a32c Mon Sep 17 00:00:00 2001 -From: Ashish Kalra -Date: Thu, 19 Aug 2021 12:35:50 +0000 -Subject: [PATCH 39/46] OvmfPkg/BaseMemEncryptLib: Detect SEV live migration - feature. - -Add support to check if we are running inside KVM HVM and -KVM HVM supports SEV Live Migration feature. - -Cc: Jordan Justen -Cc: Ard Biesheuvel -Signed-off-by: Ashish Kalra -Change-Id: I29fa5047198c9c3c6965c36b5e221b48c277dfc9 ---- - OvmfPkg/Include/Library/MemEncryptSevLib.h | 12 ++++ - .../DxeMemEncryptSevLibInternal.c | 41 +++++++++++++ - .../PeiDxeMemEncryptSevLibInternal.c | 57 +++++++++++++++++++ - .../PeiDxeMemEncryptSevLibInternal.h | 31 ++++++++++ - .../PeiMemEncryptSevLibInternal.c | 41 +++++++++++++ - .../SecMemEncryptSevLibInternal.c | 18 ++++++ - 6 files changed, 200 insertions(+) - create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h - -diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h -index adc490e..ea251f1 100644 ---- a/OvmfPkg/Include/Library/MemEncryptSevLib.h -+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h -@@ -71,6 +71,18 @@ MemEncryptSevIsEnabled ( - VOID - ); - -+/** -+ Returns a boolean to indicate whether SEV live migration is enabled. -+ -+ @retval TRUE SEV live migration is enabled -+ @retval FALSE SEV live migration is not enabled -+**/ -+BOOLEAN -+EFIAPI -+MemEncryptSevLiveMigrationIsEnabled ( -+ VOID -+ ); -+ - /** - This function clears memory encryption bit for the memory region specified by - BaseAddress and NumPages from the current page table context. -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c -index 2816f85..df73a83 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c -@@ -17,9 +17,13 @@ - #include - #include - -+#include "PeiDxeMemEncryptSevLibInternal.h" -+ - STATIC BOOLEAN mSevStatus = FALSE; - STATIC BOOLEAN mSevEsStatus = FALSE; - STATIC BOOLEAN mSevStatusChecked = FALSE; -+STATIC BOOLEAN mSevLiveMigrationStatus = FALSE; -+STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE; - - STATIC UINT64 mSevEncryptionMask = 0; - STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE; -@@ -106,6 +110,24 @@ MemEncryptSevEsIsEnabled ( - return mSevEsStatus; - } - -+/** -+ Figures out if we are running inside KVM HVM and -+ KVM HVM supports SEV Live Migration feature. -+**/ -+STATIC -+VOID -+EFIAPI -+InternalDetectSevLiveMigrationFeature ( -+ VOID -+ ) -+{ -+ if (KvmDetectSevLiveMigrationFeature ()) { -+ mSevLiveMigrationStatus = TRUE; -+ } -+ -+ mSevLiveMigrationStatusChecked = TRUE; -+} -+ - /** - Returns a boolean to indicate whether SEV is enabled. - -@@ -125,6 +147,25 @@ MemEncryptSevIsEnabled ( - return mSevStatus; - } - -+/** -+ Returns a boolean to indicate whether SEV live migration is enabled. -+ -+ @retval TRUE SEV live migration is enabled -+ @retval FALSE SEV live migration is not enabled -+**/ -+BOOLEAN -+EFIAPI -+MemEncryptSevLiveMigrationIsEnabled ( -+ VOID -+ ) -+{ -+ if (!mSevLiveMigrationStatusChecked) { -+ InternalDetectSevLiveMigrationFeature (); -+ } -+ -+ return mSevLiveMigrationStatus; -+} -+ - /** - Returns the SEV encryption mask. - -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c -index b4a9f46..30f2d90 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c -@@ -16,6 +16,8 @@ - #include - #include - -+#include "PeiDxeMemEncryptSevLibInternal.h" -+ - /** - Locate the page range that covers the initial (pre-SMBASE-relocation) SMRAM - Save State Map. -@@ -61,3 +63,58 @@ MemEncryptSevLocateInitialSmramSaveStateMapPages ( - - return RETURN_SUCCESS; - } -+ -+/** -+ Figures out if we are running inside KVM HVM and -+ KVM HVM supports SEV Live Migration feature. -+ -+ @retval TRUE SEV live migration is supported. -+ @retval FALSE SEV live migration is not supported. -+**/ -+BOOLEAN -+EFIAPI -+KvmDetectSevLiveMigrationFeature ( -+ VOID -+ ) -+{ -+ CHAR8 Signature[13]; -+ UINT32 mKvmLeaf; -+ UINT32 RegEax; -+ UINT32 RegEbx; -+ UINT32 RegEcx; -+ UINT32 RegEdx; -+ -+ Signature[12] = '\0'; -+ for (mKvmLeaf = 0x40000000; mKvmLeaf < 0x40010000; mKvmLeaf += 0x100) { -+ AsmCpuid ( -+ mKvmLeaf, -+ NULL, -+ (UINT32 *) &Signature[0], -+ (UINT32 *) &Signature[4], -+ (UINT32 *) &Signature[8]); -+ -+ if (AsciiStrCmp (Signature, "KVMKVMKVM") == 0) { -+ DEBUG (( -+ DEBUG_INFO, -+ "%a: KVM Detected, signature = %a\n", -+ __FUNCTION__, -+ Signature -+ )); -+ -+ RegEax = mKvmLeaf + 1; -+ RegEcx = 0; -+ AsmCpuid (mKvmLeaf + 1, &RegEax, &RegEbx, &RegEcx, &RegEdx); -+ if ((RegEax & KVM_FEATURE_MIGRATION_CONTROL) != 0) { -+ DEBUG (( -+ DEBUG_INFO, -+ "%a: SEV Live Migration feature supported\n", -+ __FUNCTION__ -+ )); -+ -+ return TRUE; -+ } -+ } -+ } -+ -+ return FALSE; -+} -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h -new file mode 100644 -index 0000000..30cf5de ---- /dev/null -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h -@@ -0,0 +1,31 @@ -+/** @file -+ -+ Secure Encrypted Virtualization (SEV) library helper function -+ -+ Copyright (c) 2021, AMD Incorporated. All rights reserved.
-+ -+ SPDX-License-Identifier: BSD-2-Clause-Patent -+ -+**/ -+ -+#ifndef PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_ -+#define PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_ -+ -+#include -+ -+#define KVM_FEATURE_MIGRATION_CONTROL BIT17 -+ -+/** -+ Figures out if we are running inside KVM HVM and -+ KVM HVM supports SEV Live Migration feature. -+ -+ @retval TRUE SEV live migration is supported. -+ @retval FALSE SEV live migration is not supported. -+**/ -+BOOLEAN -+EFIAPI -+KvmDetectSevLiveMigrationFeature( -+ VOID -+ ); -+ -+#endif // PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_ -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c -index e2fd109..9293b56 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c -@@ -17,9 +17,13 @@ - #include - #include - -+#include "PeiDxeMemEncryptSevLibInternal.h" -+ - STATIC BOOLEAN mSevStatus = FALSE; - STATIC BOOLEAN mSevEsStatus = FALSE; - STATIC BOOLEAN mSevStatusChecked = FALSE; -+STATIC BOOLEAN mSevLiveMigrationStatus = FALSE; -+STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE; - - STATIC UINT64 mSevEncryptionMask = 0; - STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE; -@@ -87,6 +91,24 @@ InternalMemEncryptSevStatus ( - mSevStatusChecked = TRUE; - } - -+/** -+ Figures out if we are running inside KVM HVM and -+ KVM HVM supports SEV Live Migration feature. -+**/ -+STATIC -+VOID -+EFIAPI -+InternalDetectSevLiveMigrationFeature ( -+ VOID -+ ) -+{ -+ if (KvmDetectSevLiveMigrationFeature ()) { -+ mSevLiveMigrationStatus = TRUE; -+ } -+ -+ mSevLiveMigrationStatusChecked = TRUE; -+} -+ - /** - Returns a boolean to indicate whether SEV-ES is enabled. - -@@ -125,6 +147,25 @@ MemEncryptSevIsEnabled ( - return mSevStatus; - } - -+/** -+ Returns a boolean to indicate whether SEV live migration is enabled. -+ -+ @retval TRUE SEV live migration is enabled -+ @retval FALSE SEV live migration is not enabled -+**/ -+BOOLEAN -+EFIAPI -+MemEncryptSevLiveMigrationIsEnabled ( -+ VOID -+ ) -+{ -+ if (!mSevLiveMigrationStatusChecked) { -+ InternalDetectSevLiveMigrationFeature (); -+ } -+ -+ return mSevLiveMigrationStatus; -+} -+ - /** - Returns the SEV encryption mask. - -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c -index 56d8f3f..d9f7bef 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c -@@ -100,6 +100,24 @@ MemEncryptSevIsEnabled ( - return Msr.Bits.SevBit ? TRUE : FALSE; - } - -+/** -+ Returns a boolean to indicate whether SEV live migration is enabled. -+ -+ @retval TRUE SEV live migration is enabled -+ @retval FALSE SEV live migration is not enabled -+**/ -+BOOLEAN -+EFIAPI -+MemEncryptSevLiveMigrationIsEnabled ( -+ VOID -+ ) -+{ -+ // -+ // Not used in SEC phase. -+ // -+ return FALSE; -+} -+ - /** - Returns the SEV encryption mask. - --- -2.17.1 - diff --git a/0040-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch b/0040-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch deleted file mode 100644 index 205c5b1..0000000 --- a/0040-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch +++ /dev/null @@ -1,298 +0,0 @@ -From f622069729e0abc9b676af25a90b9e142419cf1a Mon Sep 17 00:00:00 2001 -From: Ashish Kalra -Date: Thu, 19 Aug 2021 13:03:00 +0000 -Subject: [PATCH 40/46] OvmfPkg/BaseMemEncryptLib: Hypercall API for page - encryption state change - -Add API to issue hypercall on page encryption state change. - -By default all the SEV guest memory regions are considered encrypted, -if a guest changes the encryption attribute of the page (e.g mark a -page as decrypted) then notify hypervisor. Hypervisor will need to -track the unencrypted pages. The information will be used during -guest live migration, guest page migration and guest debugging. - -This hypercall is used to notify hypervisor when the page's -encryption state changes. - -Cc: Jordan Justen -Cc: Ard Biesheuvel -Signed-off-by: Brijesh Singh -Signed-off-by: Ashish Kalra -Change-Id: Ic0dcf854947f35f633137d2bb052dc79d111971f ---- - OvmfPkg/Include/Library/MemEncryptSevLib.h | 52 +++++++++++++++ - .../DxeMemEncryptSevLib.inf | 1 + - .../Ia32/MemEncryptSevLib.c | 27 ++++++++ - .../PeiMemEncryptSevLib.inf | 1 + - .../SecMemEncryptSevLibInternal.c | 20 ++++++ - .../X64/AsmHelperStub.nasm | 33 ++++++++++ - .../X64/MemEncryptSevLib.c | 64 +++++++++++++++++++ - 7 files changed, 198 insertions(+) - create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm - -diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h -index ea251f1..8ed6242 100644 ---- a/OvmfPkg/Include/Library/MemEncryptSevLib.h -+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h -@@ -215,4 +215,56 @@ MemEncryptSevClearMmioPageEncMask ( - IN UINTN NumPages - ); - -+/** -+ This hypercall is used to notify hypervisor when the page's encryption -+ state changes. -+ -+ @param[in] PhysicalAddress The physical address that is the start address -+ of a memory region. -+ @param[in] Pages Number of pages in memory region. -+ @param[in] IsEncrypted Encrypted or Decrypted. -+ -+ @retval RETURN_SUCCESS Hypercall returned success. -+ @retval RETURN_UNSUPPORTED Hypercall not supported. -+ @retval RETURN_NO_MAPPING Hypercall returned error. -+**/ -+RETURN_STATUS -+EFIAPI -+SetMemoryEncDecHypercall3 ( -+ IN UINTN PhysicalAddress, -+ IN UINTN Pages, -+ IN BOOLEAN IsEncrypted -+ ); -+ -+#define KVM_HC_MAP_GPA_RANGE 12 -+#define KVM_MAP_GPA_RANGE_PAGE_SZ_4K 0 -+#define KVM_MAP_GPA_RANGE_PAGE_SZ_2M BIT0 -+#define KVM_MAP_GPA_RANGE_PAGE_SZ_1G BIT1 -+#define KVM_MAP_GPA_RANGE_ENC_STATE(n) ((n) << 4) -+#define KVM_MAP_GPA_RANGE_ENCRYPTED KVM_MAP_GPA_RANGE_ENC_STATE(1) -+#define KVM_MAP_GPA_RANGE_DECRYPTED KVM_MAP_GPA_RANGE_ENC_STATE(0) -+ -+/** -+ Interface exposed by the ASM implementation of the core hypercall -+ -+ @param[in] HypercallNum KVM_HC_MAP_GPA_RANGE hypercall. -+ @param[in] PhysicalAddress The physical address that is the start address -+ of a memory region. -+ @param[in] Pages Number of pages in memory region. -+ @param[in] Attributes Bits 3:0 - preferred page size encoding, -+ 0 = 4kb, 1 = 2mb, 2 = 1gb, etc... -+ Bit 4 - plaintext = 0, encrypted = 1 -+ Bits 63:5 - reserved (must be zero) -+ -+ @retval Hypercall returned status. -+**/ -+UINTN -+EFIAPI -+SetMemoryEncDecHypercall3AsmStub ( -+ IN UINTN HypercallNum, -+ IN UINTN PhysicalAddress, -+ IN UINTN Pages, -+ IN UINTN Attributes -+ ); -+ - #endif // _MEM_ENCRYPT_SEV_LIB_H_ -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -index dc32929..8ea8d3a 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -@@ -38,6 +38,7 @@ - X64/PeiDxeVirtualMemory.c - X64/VirtualMemory.c - X64/VirtualMemory.h -+ X64/AsmHelperStub.nasm - - [Sources.IA32] - Ia32/MemEncryptSevLib.c -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c -index be260e0..516d639 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c -@@ -136,3 +136,30 @@ MemEncryptSevClearMmioPageEncMask ( - // - return RETURN_UNSUPPORTED; - } -+ -+/** -+ This hyercall is used to notify hypervisor when the page's encryption -+ state changes. -+ -+ @param[in] PhysicalAddress The physical address that is the start address -+ of a memory region. -+ @param[in] Pages Number of Pages in the memory region. -+ @param[in] IsEncrypted Encrypted or Decrypted. -+ -+ @retval RETURN_SUCCESS Hypercall returned success. -+ @retval RETURN_UNSUPPORTED Hypercall not supported. -+ @retval RETURN_NO_MAPPING Hypercall returned error. -+**/ -+RETURN_STATUS -+EFIAPI -+SetMemoryEncDecHypercall3 ( -+ IN UINTN PhysicalAddress, -+ IN UINTN Pages, -+ IN BOOLEAN IsEncrypted -+ ) -+{ -+ // -+ // Memory encryption bit is not accessible in 32-bit mode -+ // -+ return RETURN_UNSUPPORTED; -+} -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf -index 03a78c3..3233ca7 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf -@@ -38,6 +38,7 @@ - X64/PeiDxeVirtualMemory.c - X64/VirtualMemory.c - X64/VirtualMemory.h -+ X64/AsmHelperStub.nasm - - [Sources.IA32] - Ia32/MemEncryptSevLib.c -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c -index d9f7bef..ebb1c39 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c -@@ -118,6 +118,26 @@ MemEncryptSevLiveMigrationIsEnabled ( - return FALSE; - } - -+/** -+ Interface exposed by the ASM implementation of the core hypercall -+ -+ @retval Hypercall returned status. -+**/ -+UINTN -+EFIAPI -+SetMemoryEncDecHypercall3AsmStub ( -+ IN UINTN HypercallNum, -+ IN UINTN PhysicalAddress, -+ IN UINTN Pages, -+ IN UINTN Attributes -+ ) -+{ -+ // -+ // Not used in SEC phase. -+ // -+ return RETURN_UNSUPPORTED; -+} -+ - /** - Returns the SEV encryption mask. - -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm -new file mode 100644 -index 0000000..0ec35dd ---- /dev/null -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm -@@ -0,0 +1,33 @@ -+/** @file -+ -+ ASM helper stub to invoke hypercall -+ -+ Copyright (c) 2021, AMD Incorporated. All rights reserved.
-+ -+ SPDX-License-Identifier: BSD-2-Clause-Patent -+ -+**/ -+ -+DEFAULT REL -+SECTION .text -+ -+; UINTN -+; EFIAPI -+; SetMemoryEncDecHypercall3AsmStub ( -+; IN UINTN HypercallNum, -+; IN UINTN Arg1, -+; IN UINTN Arg2, -+; IN UINTN Arg3 -+; ); -+global ASM_PFX(SetMemoryEncDecHypercall3AsmStub) -+ASM_PFX(SetMemoryEncDecHypercall3AsmStub): -+ ; UEFI calling conventions require RBX to -+ ; be nonvolatile/callee-saved. -+ push rbx -+ mov rax, rcx ; Copy HypercallNumber to rax -+ mov rbx, rdx ; Copy Arg1 to the register expected by KVM -+ mov rcx, r8 ; Copy Arg2 to register expected by KVM -+ mov rdx, r9 ; Copy Arg3 to register expected by KVM -+ vmmcall ; Call VMMCALL -+ pop rbx -+ ret -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c -index a57e8fd..a6246d4 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c -@@ -143,3 +143,67 @@ MemEncryptSevClearMmioPageEncMask ( - ); - - } -+ -+/** -+ This hyercall is used to notify hypervisor when the page's encryption -+ state changes. -+ -+ @param[in] PhysicalAddress The physical address that is the start address -+ of a memory region. -+ @param[in] Pages Number of Pages in the memory region. -+ @param[in] IsEncrypted Encrypted or Decrypted. -+ -+ @retval RETURN_SUCCESS Hypercall returned success. -+ @retval RETURN_UNSUPPORTED Hypercall not supported. -+ @retval RETURN_NO_MAPPING Hypercall returned error. -+**/ -+RETURN_STATUS -+EFIAPI -+SetMemoryEncDecHypercall3 ( -+ IN UINTN PhysicalAddress, -+ IN UINTN Pages, -+ IN BOOLEAN IsEncrypted -+ ) -+{ -+ RETURN_STATUS Ret; -+ UINTN Error; -+ UINTN EncryptState; -+ -+ Ret = RETURN_UNSUPPORTED; -+ -+ if (MemEncryptSevLiveMigrationIsEnabled ()) { -+ Ret = RETURN_SUCCESS; -+ // -+ // The encryption bit is set/clear on the smallest page size, hence -+ // use the 4k page size in MAP_GPA_RANGE hypercall below. -+ // -+ // Also, when the GCD map is being walked and the c-bit being cleared -+ // from MMIO and NonExistent memory spaces, the physical address -+ // range being passed may not be page-aligned and adding an assert -+ // here prevents booting. Hence, rounding it down when calling -+ // SetMemoryEncDecHypercall3AsmStub below. -+ // -+ -+ EncryptState = IsEncrypted ? KVM_MAP_GPA_RANGE_ENCRYPTED : -+ KVM_MAP_GPA_RANGE_DECRYPTED; -+ -+ Error = SetMemoryEncDecHypercall3AsmStub ( -+ KVM_HC_MAP_GPA_RANGE, -+ PhysicalAddress & ~EFI_PAGE_MASK, -+ Pages, -+ KVM_MAP_GPA_RANGE_PAGE_SZ_4K | EncryptState -+ ); -+ -+ if (Error != 0) { -+ DEBUG ((DEBUG_ERROR, -+ "SetMemoryEncDecHypercall3 failed, Phys = %x, Pages = %d, Err = %Ld\n", -+ PhysicalAddress, -+ Pages, -+ (INT64)Error)); -+ -+ Ret = RETURN_NO_MAPPING; -+ } -+ } -+ -+ return Ret; -+} --- -2.17.1 - diff --git a/0041-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch b/0041-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch deleted file mode 100644 index 1c865a3..0000000 --- a/0041-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch +++ /dev/null @@ -1,91 +0,0 @@ -From ee0ca422f17da55350c4da25ef9ca38127d79e3f Mon Sep 17 00:00:00 2001 -From: Ashish Kalra -Date: Thu, 19 Aug 2021 13:04:56 +0000 -Subject: [PATCH 41/46] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state - change hypercall - -Invoke the hypercall API to notify hypervisor when the page's -encryption state changes. - -Cc: Jordan Justen -Cc: Ard Biesheuvel -Signed-off-by: Brijesh Singh -Signed-off-by: Ashish Kalra -Change-Id: Ia61155777fe3bf66f1d059978c0e8b1d1c833ef7 ---- - .../X64/PeiDxeVirtualMemory.c | 20 +++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c -index 6726010..0b67577 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c -@@ -582,10 +582,13 @@ SetMemoryEncDec ( - PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; - PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; - PAGE_TABLE_ENTRY *PageDirectory2MEntry; -+ PHYSICAL_ADDRESS OrigPhysicalAddress; - PAGE_TABLE_4K_ENTRY *PageTableEntry; - UINT64 PgTableMask; - UINT64 AddressEncMask; - BOOLEAN IsWpEnabled; -+ BOOLEAN CBitChanged; -+ UINTN OrigLength; - RETURN_STATUS Status; - PHYSICAL_ADDRESS PageAddress; - UINTN PageNum; -@@ -642,6 +645,9 @@ SetMemoryEncDec ( - } - - Status = EFI_SUCCESS; -+ OrigLength = Length; -+ CBitChanged = FALSE; -+ OrigPhysicalAddress = PhysicalAddress; - - while (Length != 0) - { -@@ -702,6 +708,7 @@ SetMemoryEncDec ( - )); - PhysicalAddress += BIT30; - Length -= BIT30; -+ CBitChanged = TRUE; - } else { - // - // We must split the page -@@ -756,6 +763,7 @@ SetMemoryEncDec ( - SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode); - PhysicalAddress += BIT21; - Length -= BIT21; -+ CBitChanged = TRUE; - } else { - // - // We must split up this page into 4K pages -@@ -798,6 +806,7 @@ SetMemoryEncDec ( - SetOrClearCBit (&PageTableEntry->Uint64, Mode); - PhysicalAddress += EFI_PAGE_SIZE; - Length -= EFI_PAGE_SIZE; -+ CBitChanged = TRUE; - } - } - } -@@ -815,6 +824,17 @@ SetMemoryEncDec ( - // - CpuFlushTlb(); - -+ // -+ // Notify Hypervisor on C-bit status -+ // -+ if (CBitChanged) { -+ Status = SetMemoryEncDecHypercall3 ( -+ OrigPhysicalAddress, -+ EFI_SIZE_TO_PAGES (OrigLength), -+ (Mode == SetCBit) ? TRUE : FALSE -+ ); -+ } -+ - Done: - // - // Restore page table write protection, if any. --- -2.17.1 - diff --git a/0042-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch b/0042-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch deleted file mode 100644 index c37eb4a..0000000 --- a/0042-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch +++ /dev/null @@ -1,46 +0,0 @@ -From b9e68850125194c9c183a0ab2239a6c73b1d67c3 Mon Sep 17 00:00:00 2001 -From: Ashish Kalra -Date: Thu, 19 Aug 2021 13:06:40 +0000 -Subject: [PATCH 42/46] OvmfPkg/VmgExitLib: Encryption state change hypercall - support in VC handler - -Make the #VC handler aware of the page encryption state -change hypercall by adding support to check KVM_HC_MAP_GPA_RANGE -hypercall and add the additional register values used by -hypercall in the GHCB. - -Cc: Jordan Justen -Cc: Ard Biesheuvel -Signed-off-by: Ashish Kalra -Change-Id: Iaab77f063455837393f290ee80962e6f3d2f5593 ---- - OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c -index 41b0c8c..2d06343 100644 ---- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c -+++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c -@@ -1171,6 +1171,19 @@ VmmCallExit ( - Ghcb->SaveArea.Cpl = (UINT8) (Regs->Cs & 0x3); - VmgSetOffsetValid (Ghcb, GhcbCpl); - -+ if (Regs->Rax == KVM_HC_MAP_GPA_RANGE) { -+ // -+ // KVM_HC_MAP_GPA_RANGE hypercall requires these -+ // extra registers. -+ // -+ Ghcb->SaveArea.Rbx = Regs->Rbx; -+ VmgSetOffsetValid (Ghcb, GhcbRbx); -+ Ghcb->SaveArea.Rcx = Regs->Rcx; -+ VmgSetOffsetValid (Ghcb, GhcbRcx); -+ Ghcb->SaveArea.Rdx = Regs->Rdx; -+ VmgSetOffsetValid (Ghcb, GhcbRdx); -+ } -+ - Status = VmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0); - if (Status != 0) { - return Status; --- -2.17.1 - diff --git a/0043-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch b/0043-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch deleted file mode 100644 index dd2ca14..0000000 --- a/0043-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 4f2273d02335039e85d8b47b1e43715e3db86c33 Mon Sep 17 00:00:00 2001 -From: Ashish Kalra -Date: Thu, 19 Aug 2021 13:09:07 +0000 -Subject: [PATCH 43/46] OvmfPkg/PlatformPei: Mark SEC GHCB page as unencrypted - via hypercall - -Mark the SEC GHCB page (that is mapped as unencrypted in -ResetVector code) in the hypervisor's guest page encryption -state tracking. - -Cc: Jordan Justen -Cc: Ard Biesheuvel -Signed-off-by: Ashish Kalra -Change-Id: Iedcde6367e12106e44e0cb1cc07a4ed386f67c19 ---- - OvmfPkg/PlatformPei/AmdSev.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c -index a8bf610..1d38056 100644 ---- a/OvmfPkg/PlatformPei/AmdSev.c -+++ b/OvmfPkg/PlatformPei/AmdSev.c -@@ -52,6 +52,17 @@ AmdSevEsInitialize ( - PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE); - ASSERT_RETURN_ERROR (PcdStatus); - -+ // -+ // The SEC Ghcb setup during reset-vector needs to be marked as -+ // decrypted in the hypervisor's guest page encryption state -+ // tracking. -+ // -+ SetMemoryEncDecHypercall3 ( -+ FixedPcdGet32 (PcdOvmfSecGhcbBase), -+ EFI_SIZE_TO_PAGES(FixedPcdGet32 (PcdOvmfSecGhcbSize)), -+ FALSE -+ ); -+ - // - // Allocate GHCB and per-CPU variable pages. - // Since the pages must survive across the UEFI to OS transition --- -2.17.1 - diff --git a/0044-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch b/0044-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch deleted file mode 100644 index edb8b39..0000000 --- a/0044-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch +++ /dev/null @@ -1,185 +0,0 @@ -From f751df6533d370a14412fab4850ad05ce99b7b85 Mon Sep 17 00:00:00 2001 -From: Ashish Kalra -Date: Thu, 19 Aug 2021 13:14:31 +0000 -Subject: [PATCH 44/46] OvmfPkg/AmdSevDxe: Add support for SEV live migration. - -Check for SEV live migration feature support, if detected -setup a new UEFI enviroment variable to indicate OVMF -support for SEV live migration. - -This environment variable is created by UEFI but consumed -by the (guest) linux kernel. This is actually part of a -3-way negotiation of the live migration feature between -hypervisor, guest OVMF and guest kernel. Host indicates -support for live migration, which is detected by OVMF -and correspondingly OVMF sets this SetLiveMigrationEnabled -UEFI variable, which is read by the guest kernel and it -indicates to the guest kernel that both host and OVMF -support and have enabled the live migration feature. - -The new runtime UEFI environment variable is set via the -notification function registered for the -EFI_END_OF_DXE_EVENT_GROUP_GUID event in AmdSevDxe driver. - -AmdSevDxe module is an apriori driver so it gets loaded between PEI -and DXE phases and the SetVariable call will fail at the driver's -entry point as the Variable DXE module is still not loaded yet. -So we need to wait for an event notification which is signaled -after the Variable DXE module is loaded, hence, using the -EndOfDxe event notification to make this call. - -Signed-off-by: Ashish Kalra -Change-Id: Iff6eee8f56fd60d1aedf48a5253b7b09e9aa9c7e ---- - OvmfPkg/AmdSevDxe/AmdSevDxe.c | 64 ++++++++++++++++++++++ - OvmfPkg/AmdSevDxe/AmdSevDxe.inf | 4 ++ - OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h | 20 +++++++ - OvmfPkg/OvmfPkg.dec | 1 + - 4 files changed, 89 insertions(+) - create mode 100644 OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h - -diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c -index c66c4e9..0750949 100644 ---- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c -+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c -@@ -15,10 +15,47 @@ - #include - #include - #include -+#include - #include - #include -+#include -+#include -+#include - #include - -+STATIC -+VOID -+EFIAPI -+AmdSevDxeOnEndOfDxe ( -+ IN EFI_EVENT Event, -+ IN VOID *EventToSignal -+ ) -+{ -+ EFI_STATUS Status; -+ BOOLEAN SevLiveMigrationEnabled; -+ -+ SevLiveMigrationEnabled = MemEncryptSevLiveMigrationIsEnabled (); -+ -+ if (SevLiveMigrationEnabled) { -+ Status = gRT->SetVariable ( -+ L"SevLiveMigrationEnabled", -+ &gAmdSevMemEncryptGuid, -+ EFI_VARIABLE_NON_VOLATILE | -+ EFI_VARIABLE_BOOTSERVICE_ACCESS | -+ EFI_VARIABLE_RUNTIME_ACCESS, -+ sizeof SevLiveMigrationEnabled, -+ &SevLiveMigrationEnabled -+ ); -+ -+ DEBUG (( -+ DEBUG_INFO, -+ "%a: Setting SevLiveMigrationEnabled variable, status = %lx\n", -+ __FUNCTION__, -+ Status -+ )); -+ } -+} -+ - EFI_STATUS - EFIAPI - AmdSevDxeEntryPoint ( -@@ -30,6 +67,7 @@ AmdSevDxeEntryPoint ( - EFI_GCD_MEMORY_SPACE_DESCRIPTOR *AllDescMap; - UINTN NumEntries; - UINTN Index; -+ EFI_EVENT Event; - - // - // Do nothing when SEV is not enabled -@@ -130,5 +168,31 @@ AmdSevDxeEntryPoint ( - } - } - -+ // -+ // AmdSevDxe module is an apriori driver so it gets loaded between PEI -+ // and DXE phases and the SetVariable call will fail at the driver's -+ // entry point as the Variable DXE module is still not loaded yet. -+ // So we need to wait for an event notification which is signaled -+ // after the Variable DXE module is loaded, hence, using the -+ // EndOfDxe event notification to make this call. -+ // -+ // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event. -+ // The notification function sets the runtime variable indicating OVMF -+ // support for SEV live migration. -+ // -+ Status = gBS->CreateEventEx ( -+ EVT_NOTIFY_SIGNAL, -+ TPL_CALLBACK, -+ AmdSevDxeOnEndOfDxe, -+ NULL, -+ &gEfiEndOfDxeEventGroupGuid, -+ &Event -+ ); -+ -+ if (EFI_ERROR (Status)) { -+ DEBUG ((DEBUG_ERROR, "%a: CreateEventEx(): %r\n", -+ __FUNCTION__, Status)); -+ } -+ - return EFI_SUCCESS; - } -diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.inf b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf -index 0676fcc..2ad1fb8 100644 ---- a/OvmfPkg/AmdSevDxe/AmdSevDxe.inf -+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf -@@ -45,3 +45,7 @@ - - [Pcd] - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId -+ -+[Guids] -+ gAmdSevMemEncryptGuid -+ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event -diff --git a/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h b/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h -new file mode 100644 -index 0000000..1c948fb ---- /dev/null -+++ b/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h -@@ -0,0 +1,20 @@ -+/** @file -+ -+ AMD Memory Encryption GUID, define a new GUID for defining -+ new UEFI environment variables assocaiated with SEV Memory Encryption. -+ -+ Copyright (c) 2021, AMD Inc. All rights reserved.
-+ -+ SPDX-License-Identifier: BSD-2-Clause-Patent -+ -+**/ -+ -+#ifndef __AMD_SEV_MEMENCRYPT_LIB_H__ -+#define __AMD_SEV_MEMENCRYPT_LIB_H__ -+ -+#define AMD_SEV_MEMENCRYPT_GUID \ -+{0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}} -+ -+extern EFI_GUID gAmdSevMemEncryptGuid; -+ -+#endif -diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec -index 7e6a6a2..b6f88e0 100644 ---- a/OvmfPkg/OvmfPkg.dec -+++ b/OvmfPkg/OvmfPkg.dec -@@ -128,6 +128,7 @@ - gQemuKernelLoaderFsMediaGuid = {0x1428f772, 0xb64a, 0x441e, {0xb8, 0xc3, 0x9e, 0xbd, 0xd7, 0xf8, 0x93, 0xc7}} - gGrubFileGuid = {0xb5ae312c, 0xbc8a, 0x43b1, {0x9c, 0x62, 0xeb, 0xb8, 0x26, 0xdd, 0x5d, 0x07}} - gConfidentialComputingSecretGuid = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}} -+ gAmdSevMemEncryptGuid = {0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}} - - [Ppis] - # PPI whose presence in the PPI database signals that the TPM base address --- -2.17.1 - diff --git a/0045-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch b/0045-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch deleted file mode 100644 index d152d63..0000000 --- a/0045-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 1f244d5fec68cbd76fd902819d906c5222577a69 Mon Sep 17 00:00:00 2001 -From: hanliyang -Date: Mon, 17 Jan 2022 01:19:21 -0500 -Subject: [PATCH 45/46] anolis: OvmfPkg/BaseMemcryptSevLib: Correct the - calculation of page range that notified to hypervisor - -Correct the calculation of page range that notified to hypervisor. - -Change-Id: Ie2ac4a4e894095ea9ae3b1d44afed04681b9d491 ---- - .../Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c -index 0b67577..4dbf829 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c -@@ -828,9 +828,13 @@ SetMemoryEncDec ( - // Notify Hypervisor on C-bit status - // - if (CBitChanged) { -+ UINTN StartPfn = OrigPhysicalAddress >> EFI_PAGE_SHIFT; -+ UINTN EndPfn = (OrigPhysicalAddress + OrigLength + -+ ((1 << EFI_PAGE_SHIFT) - 1)) >> EFI_PAGE_SHIFT; -+ - Status = SetMemoryEncDecHypercall3 ( - OrigPhysicalAddress, -- EFI_SIZE_TO_PAGES (OrigLength), -+ (EndPfn - StartPfn), - (Mode == SetCBit) ? TRUE : FALSE - ); - } --- -2.17.1 - diff --git a/0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch b/0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch deleted file mode 100644 index 5da0f2b..0000000 --- a/0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 901330a9161de852bf99ad7b2c629bae00af2b7a Mon Sep 17 00:00:00 2001 -From: hanliyang -Date: Sun, 19 Jun 2022 18:12:35 +0800 -Subject: [PATCH 46/46] anolis: OvmfPkg/BaseMemEncryptLib: Return SUCCESS if - not support SEV live migration - -Add this change to avoid trigger 'ASSERT_EFI_ERROR (Status = Unsupported)' -when QEMU doesn't support SEV live migration. - -Change-Id: I48066d6cf1b4357c984496bcb6450be4d35b7e16 ---- - OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c -index a6246d4..e50231c 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c -@@ -169,10 +169,12 @@ SetMemoryEncDecHypercall3 ( - UINTN Error; - UINTN EncryptState; - -- Ret = RETURN_UNSUPPORTED; -+ // -+ // Return success if not support migration. -+ // -+ Ret = RETURN_SUCCESS; - - if (MemEncryptSevLiveMigrationIsEnabled ()) { -- Ret = RETURN_SUCCESS; - // - // The encryption bit is set/clear on the smallest page size, hence - // use the 4k page size in MAP_GPA_RANGE hypercall below. --- -2.17.1 - diff --git a/0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch b/0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch deleted file mode 100644 index 00380bc..0000000 --- a/0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 644748015685d9a13e43d7e689f1e7379adcc959 Mon Sep 17 00:00:00 2001 -From: Xin Jiang -Date: Fri, 12 Jan 2024 10:39:28 +0800 -Subject: [PATCH] anolis: OvmfPkg/BaseMemEncryptLib: Save memory encrypt status - in reserved memory - -The MMIO routine of VC handler will get memory encrypt status to -validate MMIO address. MemEncryptSevGetEncryptionMask() will enable -interrupt while interrupt must be disabled during VC. - -During DXE stage, VC routine as below: -CcExitHandleVc->MemEncryptSevGetAddressRangeState-> -MemEncryptSevGetEncryptionMask->PcdGet64(PcdPteMemoryEncryptionAddressOrMask) - -Unfortunately, PcdGet64() will enable interrupt in VC context. - -Change-Id: I89aedeac4a90ec79f9acb35daf638b7fb507f24c -Signed-off-by: Xin Jiang ---- - .../BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf | 4 ++++ - .../BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c | 10 ++-------- - OvmfPkg/OvmfPkg.dec | 4 ++++ - OvmfPkg/OvmfPkgX64.fdf | 5 ++++- - OvmfPkg/PlatformPei/AmdSev.c | 2 ++ - OvmfPkg/PlatformPei/Csv.c | 6 ++++++ - OvmfPkg/PlatformPei/PlatformPei.inf | 2 ++ - 7 files changed, 24 insertions(+), 9 deletions(-) - -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -index 8ea8d3a..55e75ef 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf -@@ -57,3 +57,7 @@ - - [Pcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask -+ -+[FixedPcd] -+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase -+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize -diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c -index df73a83..44d9ad1 100644 ---- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c -+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c -@@ -25,9 +25,6 @@ STATIC BOOLEAN mSevStatusChecked = FALSE; - STATIC BOOLEAN mSevLiveMigrationStatus = FALSE; - STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE; - --STATIC UINT64 mSevEncryptionMask = 0; --STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE; -- - /** - Reads and sets the status of SEV features. - -@@ -177,10 +174,7 @@ MemEncryptSevGetEncryptionMask ( - VOID - ) - { -- if (!mSevEncryptionMaskSaved) { -- mSevEncryptionMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask); -- mSevEncryptionMaskSaved = TRUE; -- } -+ UINT64 *MemEncryptStatus = (UINT64 *)(UINT64)FixedPcdGet32 (PcdMemEncrpytStatusBase); - -- return mSevEncryptionMask; -+ return *MemEncryptStatus; - } -diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec -index b6f88e0..2c09ad4 100644 ---- a/OvmfPkg/OvmfPkg.dec -+++ b/OvmfPkg/OvmfPkg.dec -@@ -364,6 +364,10 @@ - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|0|UINT32|0x60 - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize|0|UINT32|0x61 - -+ ## the base address of memory encryption status.^M -+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase|0|UINT32|0x62 -+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize|0|UINT32|0x63 -+ - [PcdsDynamic, PcdsDynamicEx] - gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 -diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf -index 04efa62..0cc12b8 100644 ---- a/OvmfPkg/OvmfPkgX64.fdf -+++ b/OvmfPkg/OvmfPkgX64.fdf -@@ -94,7 +94,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGui - 0x00F000|0x001000 - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize - --0x010000|0x010000 -+0x010000|0x001000 -+gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase|gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize -+ -+0x011000|0x00F000 - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize - - 0x020000|0x0E0000 -diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c -index 1d38056..33fc83a 100644 ---- a/OvmfPkg/PlatformPei/AmdSev.c -+++ b/OvmfPkg/PlatformPei/AmdSev.c -@@ -167,6 +167,8 @@ AmdSevInitialize ( - PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask); - ASSERT_RETURN_ERROR (PcdStatus); - -+ *(UINT64 *)(UINT64)FixedPcdGet32 (PcdMemEncrpytStatusBase) = EncryptionMask; -+ - DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask)); - - // -diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c -index f7c87ac..f8293ab 100644 ---- a/OvmfPkg/PlatformPei/Csv.c -+++ b/OvmfPkg/PlatformPei/Csv.c -@@ -32,6 +32,12 @@ CsvInitializeMemInfo ( - UINT64 LowerMemorySize; - UINT64 UpperMemorySize; - -+ BuildMemoryAllocationHob ( -+ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdMemEncrpytStatusBase), -+ (UINT64)(UINTN) FixedPcdGet32 (PcdMemEncrpytStatusSize), -+ EfiReservedMemoryType -+ ); -+ - if (!CsvIsEnabled ()) { - return ; - } -diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf -index bed4dcf..7bf667c 100644 ---- a/OvmfPkg/PlatformPei/PlatformPei.inf -+++ b/OvmfPkg/PlatformPei/PlatformPei.inf -@@ -125,6 +125,8 @@ - gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize -+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase -+ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize - - [FeaturePcd] - gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable --- -2.17.1 - diff --git a/0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch b/0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch deleted file mode 100644 index e80d369..0000000 --- a/0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 02916fa2f7b92b060bbdc70b2083d0fcf6139624 Mon Sep 17 00:00:00 2001 -From: Dov Murik -Date: Thu, 15 Dec 2022 13:11:51 +0000 -Subject: [PATCH] OvmfPkg/AmdSev/SecretDxe: Allocate secret location as - EfiACPIReclaimMemory - -BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4186 - -Commit 079a58276b98 ("OvmfPkg/AmdSev/SecretPei: Mark SEV launch secret -area as reserved") marked the launch secret area itself (1 page) as -reserved so the guest OS can use it during the lifetime of the OS. -However, the address and size of the secret area held in the -CONFIDENTIAL_COMPUTING_SECRET_LOCATION struct are declared as STATIC in -OVMF (in AmdSev/SecretDxe); therefore there's no guarantee that it will -not be written over by OS data. - -Fix this by allocating the memory for the -CONFIDENTIAL_COMPUTING_SECRET_LOCATION struct with the -EfiACPIReclaimMemory memory type to ensure the guest OS will not reuse -this memory. - -Fixes: 079a58276b98 ("OvmfPkg/AmdSev/SecretPei: Mark SEV launch secret ...") -Signed-off-by: Dov Murik -Reviewed-by: Tom Lendacky -Reviewed-by: Ard Biesheuvel ---- - OvmfPkg/AmdSev/SecretDxe/SecretDxe.c | 22 ++++++++++++++++------ - 1 file changed, 16 insertions(+), 6 deletions(-) - -diff --git a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c -index 934ad20..c851176 100644 ---- a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c -+++ b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c -@@ -8,11 +8,6 @@ - #include - #include - --STATIC CONFIDENTIAL_COMPUTING_SECRET_LOCATION mSecretDxeTable = { -- FixedPcdGet32 (PcdSevLaunchSecretBase), -- FixedPcdGet32 (PcdSevLaunchSecretSize), --}; -- - EFI_STATUS - EFIAPI - InitializeSecretDxe( -@@ -20,8 +15,23 @@ InitializeSecretDxe( - IN EFI_SYSTEM_TABLE *SystemTable - ) - { -+ EFI_STATUS Status; -+ CONFIDENTIAL_COMPUTING_SECRET_LOCATION *SecretDxeTable; -+ -+ Status = gBS->AllocatePool ( -+ EfiACPIReclaimMemory, -+ sizeof (CONFIDENTIAL_COMPUTING_SECRET_LOCATION), -+ (VOID **)&SecretDxeTable -+ ); -+ if (EFI_ERROR (Status)) { -+ return Status; -+ } -+ -+ SecretDxeTable->Base = FixedPcdGet32 (PcdSevLaunchSecretBase); -+ SecretDxeTable->Size = FixedPcdGet32 (PcdSevLaunchSecretSize); -+ - return gBS->InstallConfigurationTable ( - &gConfidentialComputingSecretGuid, -- &mSecretDxeTable -+ SecretDxeTable - ); - } --- -2.41.0 - diff --git a/dist b/dist new file mode 100644 index 0000000..1fe92cf --- /dev/null +++ b/dist @@ -0,0 +1 @@ +an8_10 diff --git a/download b/download index 47caf93..651968c 100644 --- a/download +++ b/download @@ -1,2 +1,2 @@ cab67318629b34c331bf8ec6436203f4 edk2-bb1bba3d77.tar.xz -c55f8ad4ab029b5d187cc3c20dfe12f0 openssl-rhel-d00c3c5b8a9d6d3ea3dabfcafdf36afd61ba8bcc.tar.xz +b13d00e2f3be38a58380e6b4f22bc3b5 openssl-rhel-cf317b2bb227899cb2e761b9163210f62cab1b1e.tar.xz diff --git a/edk2-Apply-uncrustify-changes-to-.c-.h-files-in-the-Netwo.patch b/edk2-Apply-uncrustify-changes-to-.c-.h-files-in-the-Netwo.patch new file mode 100644 index 0000000..0ef1750 --- /dev/null +++ b/edk2-Apply-uncrustify-changes-to-.c-.h-files-in-the-Netwo.patch @@ -0,0 +1,1735 @@ +From 0f2a885790fe3f397dee527a19ef7753a1961688 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 15 Feb 2024 11:38:46 -0500 +Subject: [PATCH 01/15] Apply uncrustify changes to .c/.h files in the + NetworkPkg package + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [1/15] 7a6f3c908d076e6497e0c8978785b679a23b83cf + +JIRA: https://issues.redhat.com/browse/RHEL-21844 +CVE: CVE-2022-45231 +Upstream: Merged +Conflicts: This commit is too intrusive to apply completely. We still save + us a lot of problems (git cherry-pick basically bails out) in + the following commits in this series if we apply it on the files + modified by those commits. + +commit d1050b9dff1cace252aff86630bfdb59dff5f507 +Author: Michael Kubacki +Date: Sun Dec 5 14:54:07 2021 -0800 + + NetworkPkg: Apply uncrustify changes + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 + + Apply uncrustify changes to .c/.h files in the NetworkPkg package + + Cc: Andrew Fish + Cc: Leif Lindholm + Cc: Michael D Kinney + Signed-off-by: Michael Kubacki + Reviewed-by: Maciej Rabeda + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Ip6Dxe/Ip6Nd.h | 312 ++++++------- + NetworkPkg/Ip6Dxe/Ip6Option.c | 805 +++++++++++++++++----------------- + NetworkPkg/Ip6Dxe/Ip6Option.h | 88 ++-- + 3 files changed, 605 insertions(+), 600 deletions(-) + +diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.h b/NetworkPkg/Ip6Dxe/Ip6Nd.h +index 5f1bd6fb92..860934a167 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Nd.h ++++ b/NetworkPkg/Ip6Dxe/Ip6Nd.h +@@ -13,82 +13,82 @@ + #define IP6_GET_TICKS(Ms) (((Ms) + IP6_TIMER_INTERVAL_IN_MS - 1) / IP6_TIMER_INTERVAL_IN_MS) + + enum { +- IP6_INF_ROUTER_LIFETIME = 0xFFFF, ++ IP6_INF_ROUTER_LIFETIME = 0xFFFF, + + IP6_MAX_RTR_SOLICITATION_DELAY = 1000, ///< 1000 milliseconds + IP6_MAX_RTR_SOLICITATIONS = 3, + IP6_RTR_SOLICITATION_INTERVAL = 4000, + +- IP6_MIN_RANDOM_FACTOR_SCALED = 1, +- IP6_MAX_RANDOM_FACTOR_SCALED = 3, +- IP6_RANDOM_FACTOR_SCALE = 2, ++ IP6_MIN_RANDOM_FACTOR_SCALED = 1, ++ IP6_MAX_RANDOM_FACTOR_SCALED = 3, ++ IP6_RANDOM_FACTOR_SCALE = 2, + +- IP6_MAX_MULTICAST_SOLICIT = 3, +- IP6_MAX_UNICAST_SOLICIT = 3, +- IP6_MAX_ANYCAST_DELAY_TIME = 1, +- IP6_MAX_NEIGHBOR_ADV = 3, +- IP6_REACHABLE_TIME = 30000, +- IP6_RETRANS_TIMER = 1000, +- IP6_DELAY_FIRST_PROBE_TIME = 5000, ++ IP6_MAX_MULTICAST_SOLICIT = 3, ++ IP6_MAX_UNICAST_SOLICIT = 3, ++ IP6_MAX_ANYCAST_DELAY_TIME = 1, ++ IP6_MAX_NEIGHBOR_ADV = 3, ++ IP6_REACHABLE_TIME = 30000, ++ IP6_RETRANS_TIMER = 1000, ++ IP6_DELAY_FIRST_PROBE_TIME = 5000, + +- IP6_MIN_LINK_MTU = 1280, +- IP6_MAX_LINK_MTU = 1500, ++ IP6_MIN_LINK_MTU = 1280, ++ IP6_MAX_LINK_MTU = 1500, + +- IP6_IS_ROUTER_FLAG = 0x80, +- IP6_SOLICITED_FLAG = 0x40, +- IP6_OVERRIDE_FLAG = 0x20, ++ IP6_IS_ROUTER_FLAG = 0x80, ++ IP6_SOLICITED_FLAG = 0x40, ++ IP6_OVERRIDE_FLAG = 0x20, + +- IP6_M_ADDR_CONFIG_FLAG = 0x80, +- IP6_O_CONFIG_FLAG = 0x40, ++ IP6_M_ADDR_CONFIG_FLAG = 0x80, ++ IP6_O_CONFIG_FLAG = 0x40, + +- IP6_ON_LINK_FLAG = 0x80, +- IP6_AUTO_CONFIG_FLAG = 0x40, ++ IP6_ON_LINK_FLAG = 0x80, ++ IP6_AUTO_CONFIG_FLAG = 0x40, + +- IP6_ND_LENGTH = 24, +- IP6_RA_LENGTH = 16, +- IP6_REDITECT_LENGTH = 40, +- IP6_DAD_ENTRY_SIGNATURE = SIGNATURE_32 ('I', 'P', 'D', 'E') ++ IP6_ND_LENGTH = 24, ++ IP6_RA_LENGTH = 16, ++ IP6_REDITECT_LENGTH = 40, ++ IP6_DAD_ENTRY_SIGNATURE = SIGNATURE_32 ('I', 'P', 'D', 'E') + }; + + typedef + VOID + (*IP6_ARP_CALLBACK) ( +- VOID *Context ++ VOID *Context + ); + + typedef struct _IP6_OPTION_HEADER { +- UINT8 Type; +- UINT8 Length; ++ UINT8 Type; ++ UINT8 Length; + } IP6_OPTION_HEADER; + + STATIC_ASSERT (sizeof (IP6_OPTION_HEADER) == 2, "IP6_OPTION_HEADER is expected to be exactly 2 bytes long."); + + typedef struct _IP6_ETHE_ADDR_OPTION { +- UINT8 Type; +- UINT8 Length; +- UINT8 EtherAddr[6]; ++ UINT8 Type; ++ UINT8 Length; ++ UINT8 EtherAddr[6]; + } IP6_ETHER_ADDR_OPTION; + + STATIC_ASSERT (sizeof (IP6_ETHER_ADDR_OPTION) == 8, "IP6_ETHER_ADDR_OPTION is expected to be exactly 8 bytes long."); + + typedef struct _IP6_MTU_OPTION { +- UINT8 Type; +- UINT8 Length; +- UINT16 Reserved; +- UINT32 Mtu; ++ UINT8 Type; ++ UINT8 Length; ++ UINT16 Reserved; ++ UINT32 Mtu; + } IP6_MTU_OPTION; + + STATIC_ASSERT (sizeof (IP6_MTU_OPTION) == 8, "IP6_MTU_OPTION is expected to be exactly 8 bytes long."); + + typedef struct _IP6_PREFIX_INFO_OPTION { +- UINT8 Type; +- UINT8 Length; +- UINT8 PrefixLength; +- UINT8 Reserved1; +- UINT32 ValidLifetime; +- UINT32 PreferredLifetime; +- UINT32 Reserved2; +- EFI_IPv6_ADDRESS Prefix; ++ UINT8 Type; ++ UINT8 Length; ++ UINT8 PrefixLength; ++ UINT8 Reserved1; ++ UINT32 ValidLifetime; ++ UINT32 PreferredLifetime; ++ UINT32 Reserved2; ++ EFI_IPv6_ADDRESS Prefix; + } IP6_PREFIX_INFO_OPTION; + + STATIC_ASSERT (sizeof (IP6_PREFIX_INFO_OPTION) == 32, "IP6_PREFIX_INFO_OPTION is expected to be exactly 32 bytes long."); +@@ -102,25 +102,25 @@ VOID + ); + + typedef struct _IP6_DAD_ENTRY { +- UINT32 Signature; +- LIST_ENTRY Link; +- UINT32 MaxTransmit; +- UINT32 Transmit; +- UINT32 Receive; +- UINT32 RetransTick; +- IP6_ADDRESS_INFO *AddressInfo; +- EFI_IPv6_ADDRESS Destination; +- IP6_DAD_CALLBACK Callback; +- VOID *Context; ++ UINT32 Signature; ++ LIST_ENTRY Link; ++ UINT32 MaxTransmit; ++ UINT32 Transmit; ++ UINT32 Receive; ++ UINT32 RetransTick; ++ IP6_ADDRESS_INFO *AddressInfo; ++ EFI_IPv6_ADDRESS Destination; ++ IP6_DAD_CALLBACK Callback; ++ VOID *Context; + } IP6_DAD_ENTRY; + + typedef struct _IP6_DELAY_JOIN_LIST { +- LIST_ENTRY Link; +- UINT32 DelayTime; ///< in tick per 50 milliseconds +- IP6_INTERFACE *Interface; +- IP6_ADDRESS_INFO *AddressInfo; +- IP6_DAD_CALLBACK DadCallback; +- VOID *Context; ++ LIST_ENTRY Link; ++ UINT32 DelayTime; ///< in tick per 50 milliseconds ++ IP6_INTERFACE *Interface; ++ IP6_ADDRESS_INFO *AddressInfo; ++ IP6_DAD_CALLBACK DadCallback; ++ VOID *Context; + } IP6_DELAY_JOIN_LIST; + + typedef struct _IP6_NEIGHBOR_ENTRY { +@@ -142,20 +142,20 @@ typedef struct _IP6_NEIGHBOR_ENTRY { + } IP6_NEIGHBOR_ENTRY; + + typedef struct _IP6_DEFAULT_ROUTER { +- LIST_ENTRY Link; +- INTN RefCnt; +- UINT16 Lifetime; +- EFI_IPv6_ADDRESS Router; +- IP6_NEIGHBOR_ENTRY *NeighborCache; ++ LIST_ENTRY Link; ++ INTN RefCnt; ++ UINT16 Lifetime; ++ EFI_IPv6_ADDRESS Router; ++ IP6_NEIGHBOR_ENTRY *NeighborCache; + } IP6_DEFAULT_ROUTER; + + typedef struct _IP6_PREFIX_LIST_ENTRY { +- LIST_ENTRY Link; +- INTN RefCnt; +- UINT32 ValidLifetime; +- UINT32 PreferredLifetime; +- UINT8 PrefixLength; +- EFI_IPv6_ADDRESS Prefix; ++ LIST_ENTRY Link; ++ INTN RefCnt; ++ UINT32 ValidLifetime; ++ UINT32 PreferredLifetime; ++ UINT8 PrefixLength; ++ EFI_IPv6_ADDRESS Prefix; + } IP6_PREFIX_LIST_ENTRY; + + /** +@@ -172,9 +172,9 @@ typedef struct _IP6_PREFIX_LIST_ENTRY { + **/ + EFI_STATUS + Ip6BuildEfiNeighborCache ( +- IN IP6_PROTOCOL *IpInstance, +- OUT UINT32 *NeighborCount, +- OUT EFI_IP6_NEIGHBOR_CACHE **NeighborCache ++ IN IP6_PROTOCOL *IpInstance, ++ OUT UINT32 *NeighborCount, ++ OUT EFI_IP6_NEIGHBOR_CACHE **NeighborCache + ); + + /** +@@ -210,9 +210,9 @@ Ip6BuildPrefixTable ( + **/ + IP6_DEFAULT_ROUTER * + Ip6CreateDefaultRouter ( +- IN IP6_SERVICE *IpSb, +- IN EFI_IPv6_ADDRESS *Ip6Address, +- IN UINT16 RouterLifetime ++ IN IP6_SERVICE *IpSb, ++ IN EFI_IPv6_ADDRESS *Ip6Address, ++ IN UINT16 RouterLifetime + ); + + /** +@@ -224,8 +224,8 @@ Ip6CreateDefaultRouter ( + **/ + VOID + Ip6DestroyDefaultRouter ( +- IN IP6_SERVICE *IpSb, +- IN IP6_DEFAULT_ROUTER *DefaultRouter ++ IN IP6_SERVICE *IpSb, ++ IN IP6_DEFAULT_ROUTER *DefaultRouter + ); + + /** +@@ -236,7 +236,7 @@ Ip6DestroyDefaultRouter ( + **/ + VOID + Ip6CleanDefaultRouterList ( +- IN IP6_SERVICE *IpSb ++ IN IP6_SERVICE *IpSb + ); + + /** +@@ -251,8 +251,8 @@ Ip6CleanDefaultRouterList ( + **/ + IP6_DEFAULT_ROUTER * + Ip6FindDefaultRouter ( +- IN IP6_SERVICE *IpSb, +- IN EFI_IPv6_ADDRESS *Ip6Address ++ IN IP6_SERVICE *IpSb, ++ IN EFI_IPv6_ADDRESS *Ip6Address + ); + + /** +@@ -289,10 +289,10 @@ Ip6OnDADFinished ( + **/ + EFI_STATUS + Ip6InitDADProcess ( +- IN IP6_INTERFACE *IpIf, +- IN IP6_ADDRESS_INFO *AddressInfo, +- IN IP6_DAD_CALLBACK Callback OPTIONAL, +- IN VOID *Context OPTIONAL ++ IN IP6_INTERFACE *IpIf, ++ IN IP6_ADDRESS_INFO *AddressInfo, ++ IN IP6_DAD_CALLBACK Callback OPTIONAL, ++ IN VOID *Context OPTIONAL + ); + + /** +@@ -309,9 +309,9 @@ Ip6InitDADProcess ( + **/ + IP6_DAD_ENTRY * + Ip6FindDADEntry ( +- IN IP6_SERVICE *IpSb, +- IN EFI_IPv6_ADDRESS *Target, +- OUT IP6_INTERFACE **Interface OPTIONAL ++ IN IP6_SERVICE *IpSb, ++ IN EFI_IPv6_ADDRESS *Target, ++ OUT IP6_INTERFACE **Interface OPTIONAL + ); + + /** +@@ -334,12 +334,12 @@ Ip6FindDADEntry ( + **/ + IP6_PREFIX_LIST_ENTRY * + Ip6CreatePrefixListEntry ( +- IN IP6_SERVICE *IpSb, +- IN BOOLEAN OnLinkOrAuto, +- IN UINT32 ValidLifetime, +- IN UINT32 PreferredLifetime, +- IN UINT8 PrefixLength, +- IN EFI_IPv6_ADDRESS *Prefix ++ IN IP6_SERVICE *IpSb, ++ IN BOOLEAN OnLinkOrAuto, ++ IN UINT32 ValidLifetime, ++ IN UINT32 PreferredLifetime, ++ IN UINT8 PrefixLength, ++ IN EFI_IPv6_ADDRESS *Prefix + ); + + /** +@@ -377,10 +377,10 @@ Ip6DestroyPrefixListEntry ( + **/ + IP6_PREFIX_LIST_ENTRY * + Ip6FindPrefixListEntry ( +- IN IP6_SERVICE *IpSb, +- IN BOOLEAN OnLinkOrAuto, +- IN UINT8 PrefixLength, +- IN EFI_IPv6_ADDRESS *Prefix ++ IN IP6_SERVICE *IpSb, ++ IN BOOLEAN OnLinkOrAuto, ++ IN UINT8 PrefixLength, ++ IN EFI_IPv6_ADDRESS *Prefix + ); + + /** +@@ -393,8 +393,8 @@ Ip6FindPrefixListEntry ( + **/ + VOID + Ip6CleanPrefixListTable ( +- IN IP6_SERVICE *IpSb, +- IN LIST_ENTRY *ListHead ++ IN IP6_SERVICE *IpSb, ++ IN LIST_ENTRY *ListHead + ); + + /** +@@ -413,10 +413,10 @@ Ip6CleanPrefixListTable ( + **/ + IP6_NEIGHBOR_ENTRY * + Ip6CreateNeighborEntry ( +- IN IP6_SERVICE *IpSb, +- IN IP6_ARP_CALLBACK CallBack, +- IN EFI_IPv6_ADDRESS *Ip6Address, +- IN EFI_MAC_ADDRESS *LinkAddress OPTIONAL ++ IN IP6_SERVICE *IpSb, ++ IN IP6_ARP_CALLBACK CallBack, ++ IN EFI_IPv6_ADDRESS *Ip6Address, ++ IN EFI_MAC_ADDRESS *LinkAddress OPTIONAL + ); + + /** +@@ -431,8 +431,8 @@ Ip6CreateNeighborEntry ( + **/ + IP6_NEIGHBOR_ENTRY * + Ip6FindNeighborEntry ( +- IN IP6_SERVICE *IpSb, +- IN EFI_IPv6_ADDRESS *Ip6Address ++ IN IP6_SERVICE *IpSb, ++ IN EFI_IPv6_ADDRESS *Ip6Address + ); + + /** +@@ -458,13 +458,13 @@ Ip6FindNeighborEntry ( + **/ + EFI_STATUS + Ip6FreeNeighborEntry ( +- IN IP6_SERVICE *IpSb, +- IN IP6_NEIGHBOR_ENTRY *NeighborCache, +- IN BOOLEAN SendIcmpError, +- IN BOOLEAN FullFree, +- IN EFI_STATUS IoStatus, +- IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL, +- IN VOID *Context OPTIONAL ++ IN IP6_SERVICE *IpSb, ++ IN IP6_NEIGHBOR_ENTRY *NeighborCache, ++ IN BOOLEAN SendIcmpError, ++ IN BOOLEAN FullFree, ++ IN EFI_STATUS IoStatus, ++ IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL, ++ IN VOID *Context OPTIONAL + ); + + /** +@@ -493,11 +493,11 @@ Ip6FreeNeighborEntry ( + **/ + EFI_STATUS + Ip6AddNeighbor ( +- IN IP6_SERVICE *IpSb, +- IN EFI_IPv6_ADDRESS *TargetIp6Address, +- IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL, +- IN UINT32 Timeout, +- IN BOOLEAN Override ++ IN IP6_SERVICE *IpSb, ++ IN EFI_IPv6_ADDRESS *TargetIp6Address, ++ IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL, ++ IN UINT32 Timeout, ++ IN BOOLEAN Override + ); + + /** +@@ -521,11 +521,11 @@ Ip6AddNeighbor ( + **/ + EFI_STATUS + Ip6DelNeighbor ( +- IN IP6_SERVICE *IpSb, +- IN EFI_IPv6_ADDRESS *TargetIp6Address, +- IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL, +- IN UINT32 Timeout, +- IN BOOLEAN Override ++ IN IP6_SERVICE *IpSb, ++ IN EFI_IPv6_ADDRESS *TargetIp6Address, ++ IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL, ++ IN UINT32 Timeout, ++ IN BOOLEAN Override + ); + + /** +@@ -544,9 +544,9 @@ Ip6DelNeighbor ( + **/ + EFI_STATUS + Ip6ProcessNeighborSolicit ( +- IN IP6_SERVICE *IpSb, +- IN EFI_IP6_HEADER *Head, +- IN NET_BUF *Packet ++ IN IP6_SERVICE *IpSb, ++ IN EFI_IP6_HEADER *Head, ++ IN NET_BUF *Packet + ); + + /** +@@ -564,9 +564,9 @@ Ip6ProcessNeighborSolicit ( + **/ + EFI_STATUS + Ip6ProcessNeighborAdvertise ( +- IN IP6_SERVICE *IpSb, +- IN EFI_IP6_HEADER *Head, +- IN NET_BUF *Packet ++ IN IP6_SERVICE *IpSb, ++ IN EFI_IP6_HEADER *Head, ++ IN NET_BUF *Packet + ); + + /** +@@ -584,9 +584,9 @@ Ip6ProcessNeighborAdvertise ( + **/ + EFI_STATUS + Ip6ProcessRouterAdvertise ( +- IN IP6_SERVICE *IpSb, +- IN EFI_IP6_HEADER *Head, +- IN NET_BUF *Packet ++ IN IP6_SERVICE *IpSb, ++ IN EFI_IP6_HEADER *Head, ++ IN NET_BUF *Packet + ); + + /** +@@ -607,9 +607,9 @@ Ip6ProcessRouterAdvertise ( + **/ + EFI_STATUS + Ip6ProcessRedirect ( +- IN IP6_SERVICE *IpSb, +- IN EFI_IP6_HEADER *Head, +- IN NET_BUF *Packet ++ IN IP6_SERVICE *IpSb, ++ IN EFI_IP6_HEADER *Head, ++ IN NET_BUF *Packet + ); + + /** +@@ -631,11 +631,11 @@ Ip6ProcessRedirect ( + **/ + EFI_STATUS + Ip6SendRouterSolicit ( +- IN IP6_SERVICE *IpSb, +- IN IP6_INTERFACE *Interface OPTIONAL, +- IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL, +- IN EFI_IPv6_ADDRESS *DestinationAddress OPTIONAL, +- IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL ++ IN IP6_SERVICE *IpSb, ++ IN IP6_INTERFACE *Interface OPTIONAL, ++ IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL, ++ IN EFI_IPv6_ADDRESS *DestinationAddress OPTIONAL, ++ IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL + ); + + /** +@@ -658,11 +658,11 @@ Ip6SendRouterSolicit ( + **/ + EFI_STATUS + Ip6SendNeighborSolicit ( +- IN IP6_SERVICE *IpSb, +- IN EFI_IPv6_ADDRESS *SourceAddress, +- IN EFI_IPv6_ADDRESS *DestinationAddress, +- IN EFI_IPv6_ADDRESS *TargetIp6Address, +- IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL ++ IN IP6_SERVICE *IpSb, ++ IN EFI_IPv6_ADDRESS *SourceAddress, ++ IN EFI_IPv6_ADDRESS *DestinationAddress, ++ IN EFI_IPv6_ADDRESS *TargetIp6Address, ++ IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL + ); + + /** +@@ -690,14 +690,14 @@ Ip6SendNeighborSolicit ( + **/ + EFI_STATUS + Ip6SetAddress ( +- IN IP6_INTERFACE *Interface, +- IN EFI_IPv6_ADDRESS *Ip6Addr, +- IN BOOLEAN IsAnycast, +- IN UINT8 PrefixLength, +- IN UINT32 ValidLifetime, +- IN UINT32 PreferredLifetime, +- IN IP6_DAD_CALLBACK DadCallback OPTIONAL, +- IN VOID *Context OPTIONAL ++ IN IP6_INTERFACE *Interface, ++ IN EFI_IPv6_ADDRESS *Ip6Addr, ++ IN BOOLEAN IsAnycast, ++ IN UINT8 PrefixLength, ++ IN UINT32 ValidLifetime, ++ IN UINT32 PreferredLifetime, ++ IN IP6_DAD_CALLBACK DadCallback OPTIONAL, ++ IN VOID *Context OPTIONAL + ); + + /** +@@ -712,8 +712,8 @@ Ip6SetAddress ( + VOID + EFIAPI + Ip6NdFasterTimerTicking ( +- IN EFI_EVENT Event, +- IN VOID *Context ++ IN EFI_EVENT Event, ++ IN VOID *Context + ); + + /** +@@ -726,7 +726,7 @@ Ip6NdFasterTimerTicking ( + **/ + VOID + Ip6NdTimerTicking ( +- IN IP6_SERVICE *IpSb ++ IN IP6_SERVICE *IpSb + ); + + /** +@@ -739,7 +739,7 @@ Ip6NdTimerTicking ( + **/ + VOID + Ip6OnArpResolved ( +- IN VOID *Context ++ IN VOID *Context + ); + + /** +diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c +index 6b4b029d14..199eea124d 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Option.c ++++ b/NetworkPkg/Ip6Dxe/Ip6Option.c +@@ -28,15 +28,15 @@ + **/ + BOOLEAN + Ip6IsOptionValid ( +- IN IP6_SERVICE *IpSb, +- IN NET_BUF *Packet, +- IN UINT8 *Option, +- IN UINT8 OptionLen, +- IN UINT32 Pointer ++ IN IP6_SERVICE *IpSb, ++ IN NET_BUF *Packet, ++ IN UINT8 *Option, ++ IN UINT8 OptionLen, ++ IN UINT32 Pointer + ) + { +- UINT8 Offset; +- UINT8 OptionType; ++ UINT8 Offset; ++ UINT8 OptionType; + + Offset = 0; + +@@ -44,68 +44,67 @@ Ip6IsOptionValid ( + OptionType = *(Option + Offset); + + switch (OptionType) { +- case Ip6OptionPad1: +- // +- // It is a Pad1 option +- // +- Offset++; +- break; +- case Ip6OptionPadN: +- // +- // It is a PadN option +- // +- Offset = (UINT8) (Offset + *(Option + Offset + 1) + 2); +- break; +- case Ip6OptionRouterAlert: +- // +- // It is a Router Alert Option +- // +- Offset += 4; +- break; +- default: +- // +- // The highest-order two bits specify the action must be taken if +- // the processing IPv6 node does not recognize the option type. +- // +- switch (OptionType & Ip6OptionMask) { +- case Ip6OptionSkip: +- Offset = (UINT8) (Offset + *(Option + Offset + 1)); ++ case Ip6OptionPad1: ++ // ++ // It is a Pad1 option ++ // ++ Offset++; + break; +- case Ip6OptionDiscard: +- return FALSE; +- case Ip6OptionParameterProblem: +- Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER); +- Ip6SendIcmpError ( +- IpSb, +- Packet, +- NULL, +- &Packet->Ip.Ip6->SourceAddress, +- ICMP_V6_PARAMETER_PROBLEM, +- 2, +- &Pointer +- ); +- return FALSE; +- case Ip6OptionMask: +- if (!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) { +- Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER); +- Ip6SendIcmpError ( +- IpSb, +- Packet, +- NULL, +- &Packet->Ip.Ip6->SourceAddress, +- ICMP_V6_PARAMETER_PROBLEM, +- 2, +- &Pointer +- ); ++ case Ip6OptionPadN: ++ // ++ // It is a PadN option ++ // ++ Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2); ++ break; ++ case Ip6OptionRouterAlert: ++ // ++ // It is a Router Alert Option ++ // ++ Offset += 4; ++ break; ++ default: ++ // ++ // The highest-order two bits specify the action must be taken if ++ // the processing IPv6 node does not recognize the option type. ++ // ++ switch (OptionType & Ip6OptionMask) { ++ case Ip6OptionSkip: ++ Offset = (UINT8)(Offset + *(Option + Offset + 1)); ++ break; ++ case Ip6OptionDiscard: ++ return FALSE; ++ case Ip6OptionParameterProblem: ++ Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER); ++ Ip6SendIcmpError ( ++ IpSb, ++ Packet, ++ NULL, ++ &Packet->Ip.Ip6->SourceAddress, ++ ICMP_V6_PARAMETER_PROBLEM, ++ 2, ++ &Pointer ++ ); ++ return FALSE; ++ case Ip6OptionMask: ++ if (!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) { ++ Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER); ++ Ip6SendIcmpError ( ++ IpSb, ++ Packet, ++ NULL, ++ &Packet->Ip.Ip6->SourceAddress, ++ ICMP_V6_PARAMETER_PROBLEM, ++ 2, ++ &Pointer ++ ); ++ } ++ ++ return FALSE; ++ break; + } + +- return FALSE; + break; +- } +- +- break; + } +- + } + + return TRUE; +@@ -125,13 +124,13 @@ Ip6IsOptionValid ( + **/ + BOOLEAN + Ip6IsNDOptionValid ( +- IN UINT8 *Option, +- IN UINT16 OptionLen ++ IN UINT8 *Option, ++ IN UINT16 OptionLen + ) + { +- UINT32 Offset; +- UINT16 Length; +- IP6_OPTION_HEADER *OptionHeader; ++ UINT32 Offset; ++ UINT16 Length; ++ IP6_OPTION_HEADER *OptionHeader; + + if (Option == NULL) { + ASSERT (Option != NULL); +@@ -146,50 +145,54 @@ Ip6IsNDOptionValid ( + // fit within the input buffer. + // + while (Offset + sizeof (IP6_OPTION_HEADER) - 1 < OptionLen) { +- OptionHeader = (IP6_OPTION_HEADER*) (Option + Offset); +- Length = (UINT16) OptionHeader->Length * 8; ++ OptionHeader = (IP6_OPTION_HEADER *)(Option + Offset); ++ Length = (UINT16)OptionHeader->Length * 8; + + switch (OptionHeader->Type) { +- case Ip6OptionPrefixInfo: +- if (Length != 32) { +- return FALSE; +- } +- break; ++ case Ip6OptionPrefixInfo: ++ if (Length != 32) { ++ return FALSE; ++ } + +- case Ip6OptionMtu: +- if (Length != 8) { +- return FALSE; +- } +- break; ++ break; + +- default: +- // RFC 4861 states that Length field cannot be 0. +- if (Length == 0) { +- return FALSE; +- } +- break; ++ case Ip6OptionMtu: ++ if (Length != 8) { ++ return FALSE; ++ } ++ ++ break; ++ ++ default: ++ // RFC 4861 states that Length field cannot be 0. ++ if (Length == 0) { ++ return FALSE; ++ } ++ ++ break; + } + + // + // Check whether recognized options are within the input buffer's scope. + // + switch (OptionHeader->Type) { +- case Ip6OptionEtherSource: +- case Ip6OptionEtherTarget: +- case Ip6OptionPrefixInfo: +- case Ip6OptionRedirected: +- case Ip6OptionMtu: +- if (Offset + Length > (UINT32) OptionLen) { +- return FALSE; +- } +- break; ++ case Ip6OptionEtherSource: ++ case Ip6OptionEtherTarget: ++ case Ip6OptionPrefixInfo: ++ case Ip6OptionRedirected: ++ case Ip6OptionMtu: ++ if (Offset + Length > (UINT32)OptionLen) { ++ return FALSE; ++ } + +- default: +- // +- // Unrecognized options can be either valid (but unused) or invalid +- // (garbage in between or right after valid options). Silently ignore. +- // +- break; ++ break; ++ ++ default: ++ // ++ // Unrecognized options can be either valid (but unused) or invalid ++ // (garbage in between or right after valid options). Silently ignore. ++ // ++ break; + } + + // +@@ -202,7 +205,6 @@ Ip6IsNDOptionValid ( + return TRUE; + } + +- + /** + Validate whether the NextHeader is a known valid protocol or one of the user configured + protocols from the upper layer. +@@ -216,18 +218,19 @@ Ip6IsNDOptionValid ( + **/ + BOOLEAN + Ip6IsValidProtocol ( +- IN IP6_SERVICE *IpSb, +- IN UINT8 NextHeader ++ IN IP6_SERVICE *IpSb, ++ IN UINT8 NextHeader + ) + { +- LIST_ENTRY *Entry; +- IP6_PROTOCOL *IpInstance; +- +- if (NextHeader == EFI_IP_PROTO_TCP || +- NextHeader == EFI_IP_PROTO_UDP || +- NextHeader == IP6_ICMP || +- NextHeader == IP6_ESP +- ) { ++ LIST_ENTRY *Entry; ++ IP6_PROTOCOL *IpInstance; ++ ++ if ((NextHeader == EFI_IP_PROTO_TCP) || ++ (NextHeader == EFI_IP_PROTO_UDP) || ++ (NextHeader == IP6_ICMP) || ++ (NextHeader == IP6_ESP) ++ ) ++ { + return TRUE; + } + +@@ -281,29 +284,29 @@ Ip6IsValidProtocol ( + **/ + BOOLEAN + Ip6IsExtsValid ( +- IN IP6_SERVICE *IpSb OPTIONAL, +- IN NET_BUF *Packet OPTIONAL, +- IN UINT8 *NextHeader, +- IN UINT8 *ExtHdrs, +- IN UINT32 ExtHdrsLen, +- IN BOOLEAN Rcvd, +- OUT UINT32 *FormerHeader OPTIONAL, +- OUT UINT8 **LastHeader, +- OUT UINT32 *RealExtsLen OPTIONAL, +- OUT UINT32 *UnFragmentLen OPTIONAL, +- OUT BOOLEAN *Fragmented OPTIONAL ++ IN IP6_SERVICE *IpSb OPTIONAL, ++ IN NET_BUF *Packet OPTIONAL, ++ IN UINT8 *NextHeader, ++ IN UINT8 *ExtHdrs, ++ IN UINT32 ExtHdrsLen, ++ IN BOOLEAN Rcvd, ++ OUT UINT32 *FormerHeader OPTIONAL, ++ OUT UINT8 **LastHeader, ++ OUT UINT32 *RealExtsLen OPTIONAL, ++ OUT UINT32 *UnFragmentLen OPTIONAL, ++ OUT BOOLEAN *Fragmented OPTIONAL + ) + { +- UINT32 Pointer; +- UINT32 Offset; +- UINT8 *Option; +- UINT8 OptionLen; +- BOOLEAN Flag; +- UINT8 CountD; +- UINT8 CountA; +- IP6_FRAGMENT_HEADER *FragmentHead; +- UINT16 FragmentOffset; +- IP6_ROUTING_HEADER *RoutingHead; ++ UINT32 Pointer; ++ UINT32 Offset; ++ UINT8 *Option; ++ UINT8 OptionLen; ++ BOOLEAN Flag; ++ UINT8 CountD; ++ UINT8 CountA; ++ IP6_FRAGMENT_HEADER *FragmentHead; ++ UINT16 FragmentOffset; ++ IP6_ROUTING_HEADER *RoutingHead; + + if (RealExtsLen != NULL) { + *RealExtsLen = 0; +@@ -319,11 +322,11 @@ Ip6IsExtsValid ( + + *LastHeader = NextHeader; + +- if (ExtHdrs == NULL && ExtHdrsLen == 0) { ++ if ((ExtHdrs == NULL) && (ExtHdrsLen == 0)) { + return TRUE; + } + +- if ((ExtHdrs == NULL && ExtHdrsLen != 0) || (ExtHdrs != NULL && ExtHdrsLen == 0)) { ++ if (((ExtHdrs == NULL) && (ExtHdrsLen != 0)) || ((ExtHdrs != NULL) && (ExtHdrsLen == 0))) { + return FALSE; + } + +@@ -334,236 +337,240 @@ Ip6IsExtsValid ( + CountA = 0; + + while (Offset <= ExtHdrsLen) { +- + switch (*NextHeader) { +- case IP6_HOP_BY_HOP: +- if (Offset != 0) { +- if (!Rcvd) { ++ case IP6_HOP_BY_HOP: ++ if (Offset != 0) { ++ if (!Rcvd) { ++ return FALSE; ++ } ++ ++ // ++ // Hop-by-Hop Options header is restricted to appear immediately after an IPv6 header only. ++ // If not, generate a ICMP parameter problem message with code value of 1. ++ // ++ if (Pointer == 0) { ++ Pointer = sizeof (EFI_IP6_HEADER); ++ } else { ++ Pointer = Offset + sizeof (EFI_IP6_HEADER); ++ } ++ ++ if ((IpSb != NULL) && (Packet != NULL) && ++ !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) ++ { ++ Ip6SendIcmpError ( ++ IpSb, ++ Packet, ++ NULL, ++ &Packet->Ip.Ip6->SourceAddress, ++ ICMP_V6_PARAMETER_PROBLEM, ++ 1, ++ &Pointer ++ ); ++ } ++ + return FALSE; + } +- // +- // Hop-by-Hop Options header is restricted to appear immediately after an IPv6 header only. +- // If not, generate a ICMP parameter problem message with code value of 1. +- // +- if (Pointer == 0) { +- Pointer = sizeof (EFI_IP6_HEADER); +- } else { +- Pointer = Offset + sizeof (EFI_IP6_HEADER); ++ ++ Flag = TRUE; ++ ++ // ++ // Fall through ++ // ++ case IP6_DESTINATION: ++ if (*NextHeader == IP6_DESTINATION) { ++ CountD++; + } + +- if ((IpSb != NULL) && (Packet != NULL) && +- !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) { +- Ip6SendIcmpError ( +- IpSb, +- Packet, +- NULL, +- &Packet->Ip.Ip6->SourceAddress, +- ICMP_V6_PARAMETER_PROBLEM, +- 1, +- &Pointer +- ); ++ if (CountD > 2) { ++ return FALSE; + } +- return FALSE; +- } + +- Flag = TRUE; ++ NextHeader = ExtHdrs + Offset; ++ Pointer = Offset; + +- // +- // Fall through +- // +- case IP6_DESTINATION: +- if (*NextHeader == IP6_DESTINATION) { +- CountD++; +- } ++ Offset++; ++ Option = ExtHdrs + Offset; ++ OptionLen = (UINT8)((*Option + 1) * 8 - 2); ++ Option++; ++ Offset++; + +- if (CountD > 2) { +- return FALSE; +- } ++ if ((IpSb != NULL) && (Packet != NULL) && !Ip6IsOptionValid (IpSb, Packet, Option, OptionLen, Offset)) { ++ return FALSE; ++ } + +- NextHeader = ExtHdrs + Offset; +- Pointer = Offset; ++ Offset = Offset + OptionLen; + +- Offset++; +- Option = ExtHdrs + Offset; +- OptionLen = (UINT8) ((*Option + 1) * 8 - 2); +- Option++; +- Offset++; ++ if (Flag) { ++ if (UnFragmentLen != NULL) { ++ *UnFragmentLen = Offset; ++ } + +- if (IpSb != NULL && Packet != NULL && !Ip6IsOptionValid (IpSb, Packet, Option, OptionLen, Offset)) { +- return FALSE; +- } ++ Flag = FALSE; ++ } ++ ++ break; + +- Offset = Offset + OptionLen; ++ case IP6_ROUTING: ++ NextHeader = ExtHdrs + Offset; ++ RoutingHead = (IP6_ROUTING_HEADER *)NextHeader; + +- if (Flag) { +- if (UnFragmentLen != NULL) { +- *UnFragmentLen = Offset; ++ // ++ // Type 0 routing header is defined in RFC2460 and deprecated in RFC5095. ++ // Thus all routing types are processed as unrecognized. ++ // ++ if (RoutingHead->SegmentsLeft == 0) { ++ // ++ // Ignore the routing header and proceed to process the next header. ++ // ++ Offset = Offset + (RoutingHead->HeaderLen + 1) * 8; ++ ++ if (UnFragmentLen != NULL) { ++ *UnFragmentLen = Offset; ++ } ++ } else { ++ // ++ // Discard the packet and send an ICMP Parameter Problem, Code 0, message ++ // to the packet's source address, pointing to the unrecognized routing ++ // type. ++ // ++ Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER); ++ if ((IpSb != NULL) && (Packet != NULL) && ++ !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) ++ { ++ Ip6SendIcmpError ( ++ IpSb, ++ Packet, ++ NULL, ++ &Packet->Ip.Ip6->SourceAddress, ++ ICMP_V6_PARAMETER_PROBLEM, ++ 0, ++ &Pointer ++ ); ++ } ++ ++ return FALSE; + } + +- Flag = FALSE; +- } ++ break; + +- break; ++ case IP6_FRAGMENT: + +- case IP6_ROUTING: +- NextHeader = ExtHdrs + Offset; +- RoutingHead = (IP6_ROUTING_HEADER *) NextHeader; ++ // ++ // RFC2402, AH header should after fragment header. ++ // ++ if (CountA > 1) { ++ return FALSE; ++ } + +- // +- // Type 0 routing header is defined in RFC2460 and deprecated in RFC5095. +- // Thus all routing types are processed as unrecognized. +- // +- if (RoutingHead->SegmentsLeft == 0) { + // +- // Ignore the routing header and proceed to process the next header. ++ // RFC2460, ICMP Parameter Problem message with code 0 should be sent ++ // if the length of a fragment is not a multiple of 8 octets and the M ++ // flag of that fragment is 1, pointing to the Payload length field of the ++ // fragment packet. + // +- Offset = Offset + (RoutingHead->HeaderLen + 1) * 8; ++ if ((IpSb != NULL) && (Packet != NULL) && ((ExtHdrsLen % 8) != 0)) { ++ // ++ // Check whether it is the last fragment. ++ // ++ FragmentHead = (IP6_FRAGMENT_HEADER *)(ExtHdrs + Offset); ++ if (FragmentHead == NULL) { ++ return FALSE; ++ } ++ ++ FragmentOffset = NTOHS (FragmentHead->FragmentOffset); ++ ++ if (((FragmentOffset & 0x1) == 0x1) && ++ !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) ++ { ++ Pointer = sizeof (UINT32); ++ Ip6SendIcmpError ( ++ IpSb, ++ Packet, ++ NULL, ++ &Packet->Ip.Ip6->SourceAddress, ++ ICMP_V6_PARAMETER_PROBLEM, ++ 0, ++ &Pointer ++ ); ++ return FALSE; ++ } ++ } ++ ++ if (Fragmented != NULL) { ++ *Fragmented = TRUE; ++ } ++ ++ if (Rcvd && (FormerHeader != NULL)) { ++ *FormerHeader = (UINT32)(NextHeader - ExtHdrs); ++ } ++ ++ NextHeader = ExtHdrs + Offset; ++ Offset = Offset + 8; ++ break; + +- if (UnFragmentLen != NULL) { +- *UnFragmentLen = Offset; ++ case IP6_AH: ++ if (++CountA > 1) { ++ return FALSE; + } + +- } else { ++ Option = ExtHdrs + Offset; ++ NextHeader = Option; ++ Option++; + // +- // Discard the packet and send an ICMP Parameter Problem, Code 0, message +- // to the packet's source address, pointing to the unrecognized routing +- // type. ++ // RFC2402, Payload length is specified in 32-bit words, minus "2". + // +- Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER); +- if ((IpSb != NULL) && (Packet != NULL) && +- !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) { +- Ip6SendIcmpError ( +- IpSb, +- Packet, +- NULL, +- &Packet->Ip.Ip6->SourceAddress, +- ICMP_V6_PARAMETER_PROBLEM, +- 0, +- &Pointer +- ); +- } ++ OptionLen = (UINT8)((*Option + 2) * 4); ++ Offset = Offset + OptionLen; ++ break; + ++ case IP6_NO_NEXT_HEADER: ++ *LastHeader = NextHeader; + return FALSE; +- } ++ break; + +- break; ++ default: ++ if (Ip6IsValidProtocol (IpSb, *NextHeader)) { ++ *LastHeader = NextHeader; + +- case IP6_FRAGMENT: ++ if (RealExtsLen != NULL) { ++ *RealExtsLen = Offset; ++ } + +- // +- // RFC2402, AH header should after fragment header. +- // +- if (CountA > 1) { +- return FALSE; +- } ++ return TRUE; ++ } + +- // +- // RFC2460, ICMP Parameter Problem message with code 0 should be sent +- // if the length of a fragment is not a multiple of 8 octets and the M +- // flag of that fragment is 1, pointing to the Payload length field of the +- // fragment packet. +- // +- if (IpSb != NULL && Packet != NULL && (ExtHdrsLen % 8) != 0) { + // +- // Check whether it is the last fragment. ++ // The Next Header value is unrecognized by the node, discard the packet and ++ // send an ICMP parameter problem message with code value of 1. + // +- FragmentHead = (IP6_FRAGMENT_HEADER *) (ExtHdrs + Offset); +- if (FragmentHead == NULL) { +- return FALSE; ++ if (Offset == 0) { ++ // ++ // The Next Header directly follows IPv6 basic header. ++ // ++ Pointer = 6; ++ } else { ++ if (Pointer == 0) { ++ Pointer = sizeof (EFI_IP6_HEADER); ++ } else { ++ Pointer = Offset + sizeof (EFI_IP6_HEADER); ++ } + } + +- FragmentOffset = NTOHS (FragmentHead->FragmentOffset); +- +- if (((FragmentOffset & 0x1) == 0x1) && +- !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) { +- Pointer = sizeof (UINT32); ++ if ((IpSb != NULL) && (Packet != NULL) && ++ !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) ++ { + Ip6SendIcmpError ( + IpSb, + Packet, + NULL, + &Packet->Ip.Ip6->SourceAddress, + ICMP_V6_PARAMETER_PROBLEM, +- 0, ++ 1, + &Pointer + ); +- return FALSE; + } +- } +- +- if (Fragmented != NULL) { +- *Fragmented = TRUE; +- } + +- if (Rcvd && FormerHeader != NULL) { +- *FormerHeader = (UINT32) (NextHeader - ExtHdrs); +- } +- +- NextHeader = ExtHdrs + Offset; +- Offset = Offset + 8; +- break; +- +- case IP6_AH: +- if (++CountA > 1) { + return FALSE; +- } +- +- Option = ExtHdrs + Offset; +- NextHeader = Option; +- Option++; +- // +- // RFC2402, Payload length is specified in 32-bit words, minus "2". +- // +- OptionLen = (UINT8) ((*Option + 2) * 4); +- Offset = Offset + OptionLen; +- break; +- +- case IP6_NO_NEXT_HEADER: +- *LastHeader = NextHeader; +- return FALSE; +- break; +- +- default: +- if (Ip6IsValidProtocol (IpSb, *NextHeader)) { +- +- *LastHeader = NextHeader; +- +- if (RealExtsLen != NULL) { +- *RealExtsLen = Offset; +- } +- +- return TRUE; +- } +- +- // +- // The Next Header value is unrecognized by the node, discard the packet and +- // send an ICMP parameter problem message with code value of 1. +- // +- if (Offset == 0) { +- // +- // The Next Header directly follows IPv6 basic header. +- // +- Pointer = 6; +- } else { +- if (Pointer == 0) { +- Pointer = sizeof (EFI_IP6_HEADER); +- } else { +- Pointer = Offset + sizeof (EFI_IP6_HEADER); +- } +- } +- +- if ((IpSb != NULL) && (Packet != NULL) && +- !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) { +- Ip6SendIcmpError ( +- IpSb, +- Packet, +- NULL, +- &Packet->Ip.Ip6->SourceAddress, +- ICMP_V6_PARAMETER_PROBLEM, +- 1, +- &Pointer +- ); +- } +- return FALSE; + } + } + +@@ -592,12 +599,12 @@ Ip6IsExtsValid ( + **/ + EFI_STATUS + Ip6FillHopByHop ( +- OUT UINT8 *Buffer, +- IN OUT UINTN *BufferLen, +- IN UINT8 NextHeader ++ OUT UINT8 *Buffer, ++ IN OUT UINTN *BufferLen, ++ IN UINT8 NextHeader + ) + { +- UINT8 BufferArray[8]; ++ UINT8 BufferArray[8]; + + if (*BufferLen < 8) { + *BufferLen = 8; +@@ -640,23 +647,23 @@ Ip6FillHopByHop ( + **/ + EFI_STATUS + Ip6FillFragmentHeader ( +- IN IP6_SERVICE *IpSb, +- IN UINT8 NextHeader, +- IN UINT8 LastHeader, +- IN UINT8 *ExtHdrs, +- IN UINT32 ExtHdrsLen, +- IN UINT16 FragmentOffset, +- OUT UINT8 **UpdatedExtHdrs ++ IN IP6_SERVICE *IpSb, ++ IN UINT8 NextHeader, ++ IN UINT8 LastHeader, ++ IN UINT8 *ExtHdrs, ++ IN UINT32 ExtHdrsLen, ++ IN UINT16 FragmentOffset, ++ OUT UINT8 **UpdatedExtHdrs + ) + { +- UINT32 Length; +- UINT8 *Buffer; +- UINT32 FormerHeader; +- UINT32 Offset; +- UINT32 Part1Len; +- UINT32 HeaderLen; +- UINT8 Current; +- IP6_FRAGMENT_HEADER FragmentHead; ++ UINT32 Length; ++ UINT8 *Buffer; ++ UINT32 FormerHeader; ++ UINT32 Offset; ++ UINT32 Part1Len; ++ UINT32 HeaderLen; ++ UINT8 Current; ++ IP6_FRAGMENT_HEADER FragmentHead; + + if (UpdatedExtHdrs == NULL) { + return EFI_INVALID_PARAMETER; +@@ -668,82 +675,81 @@ Ip6FillFragmentHeader ( + return EFI_OUT_OF_RESOURCES; + } + +- Offset = 0; +- Part1Len = 0; +- FormerHeader = 0; +- Current = NextHeader; ++ Offset = 0; ++ Part1Len = 0; ++ FormerHeader = 0; ++ Current = NextHeader; + + while ((ExtHdrs != NULL) && (Offset <= ExtHdrsLen)) { + switch (NextHeader) { +- case IP6_ROUTING: +- case IP6_HOP_BY_HOP: +- case IP6_DESTINATION: +- Current = NextHeader; +- NextHeader = *(ExtHdrs + Offset); ++ case IP6_ROUTING: ++ case IP6_HOP_BY_HOP: ++ case IP6_DESTINATION: ++ Current = NextHeader; ++ NextHeader = *(ExtHdrs + Offset); ++ ++ if ((Current == IP6_DESTINATION) && (NextHeader != IP6_ROUTING)) { ++ // ++ // Destination Options header should occur at most twice, once before ++ // a Routing header and once before the upper-layer header. Here we ++ // find the one before the upper-layer header. Insert the Fragment ++ // Header before it. ++ // ++ CopyMem (Buffer, ExtHdrs, Part1Len); ++ *(Buffer + FormerHeader) = IP6_FRAGMENT; ++ // ++ // Exit the loop. ++ // ++ Offset = ExtHdrsLen + 1; ++ break; ++ } + +- if ((Current == IP6_DESTINATION) && (NextHeader != IP6_ROUTING)) { +- // +- // Destination Options header should occur at most twice, once before +- // a Routing header and once before the upper-layer header. Here we +- // find the one before the upper-layer header. Insert the Fragment +- // Header before it. +- // +- CopyMem (Buffer, ExtHdrs, Part1Len); +- *(Buffer + FormerHeader) = IP6_FRAGMENT; +- // +- // Exit the loop. +- // +- Offset = ExtHdrsLen + 1; ++ FormerHeader = Offset; ++ HeaderLen = (*(ExtHdrs + Offset + 1) + 1) * 8; ++ Part1Len = Part1Len + HeaderLen; ++ Offset = Offset + HeaderLen; + break; +- } +- + +- FormerHeader = Offset; +- HeaderLen = (*(ExtHdrs + Offset + 1) + 1) * 8; +- Part1Len = Part1Len + HeaderLen; +- Offset = Offset + HeaderLen; +- break; +- +- case IP6_FRAGMENT: +- Current = NextHeader; +- +- if (Part1Len != 0) { +- CopyMem (Buffer, ExtHdrs, Part1Len); +- } +- +- *(Buffer + FormerHeader) = IP6_FRAGMENT; +- +- // +- // Exit the loop. +- // +- Offset = ExtHdrsLen + 1; +- break; ++ case IP6_FRAGMENT: ++ Current = NextHeader; + +- case IP6_AH: +- Current = NextHeader; +- NextHeader = *(ExtHdrs + Offset); +- // +- // RFC2402, Payload length is specified in 32-bit words, minus "2". +- // +- HeaderLen = (*(ExtHdrs + Offset + 1) + 2) * 4; +- Part1Len = Part1Len + HeaderLen; +- Offset = Offset + HeaderLen; +- break; ++ if (Part1Len != 0) { ++ CopyMem (Buffer, ExtHdrs, Part1Len); ++ } + +- default: +- if (Ip6IsValidProtocol (IpSb, NextHeader)) { +- Current = NextHeader; +- CopyMem (Buffer, ExtHdrs, Part1Len); + *(Buffer + FormerHeader) = IP6_FRAGMENT; ++ + // + // Exit the loop. + // + Offset = ExtHdrsLen + 1; + break; +- } + +- FreePool (Buffer); +- return EFI_UNSUPPORTED; ++ case IP6_AH: ++ Current = NextHeader; ++ NextHeader = *(ExtHdrs + Offset); ++ // ++ // RFC2402, Payload length is specified in 32-bit words, minus "2". ++ // ++ HeaderLen = (*(ExtHdrs + Offset + 1) + 2) * 4; ++ Part1Len = Part1Len + HeaderLen; ++ Offset = Offset + HeaderLen; ++ break; ++ ++ default: ++ if (Ip6IsValidProtocol (IpSb, NextHeader)) { ++ Current = NextHeader; ++ CopyMem (Buffer, ExtHdrs, Part1Len); ++ *(Buffer + FormerHeader) = IP6_FRAGMENT; ++ // ++ // Exit the loop. ++ // ++ Offset = ExtHdrsLen + 1; ++ break; ++ } ++ ++ FreePool (Buffer); ++ return EFI_UNSUPPORTED; + } + } + +@@ -778,4 +784,3 @@ Ip6FillFragmentHeader ( + + return EFI_SUCCESS; + } +- +diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.h b/NetworkPkg/Ip6Dxe/Ip6Option.h +index c81b3fda2f..bd8e223c8a 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Option.h ++++ b/NetworkPkg/Ip6Dxe/Ip6Option.h +@@ -10,20 +10,20 @@ + #ifndef __EFI_IP6_OPTION_H__ + #define __EFI_IP6_OPTION_H__ + +-#define IP6_FRAGMENT_OFFSET_MASK (~0x3) ++#define IP6_FRAGMENT_OFFSET_MASK (~0x3) + + typedef struct _IP6_FRAGMENT_HEADER { +- UINT8 NextHeader; +- UINT8 Reserved; +- UINT16 FragmentOffset; +- UINT32 Identification; ++ UINT8 NextHeader; ++ UINT8 Reserved; ++ UINT16 FragmentOffset; ++ UINT32 Identification; + } IP6_FRAGMENT_HEADER; + + typedef struct _IP6_ROUTING_HEADER { +- UINT8 NextHeader; +- UINT8 HeaderLen; +- UINT8 RoutingType; +- UINT8 SegmentsLeft; ++ UINT8 NextHeader; ++ UINT8 HeaderLen; ++ UINT8 RoutingType; ++ UINT8 SegmentsLeft; + } IP6_ROUTING_HEADER; + + typedef enum { +@@ -35,11 +35,11 @@ typedef enum { + Ip6OptionParameterProblem = 0x80, + Ip6OptionMask = 0xc0, + +- Ip6OptionEtherSource = 1, +- Ip6OptionEtherTarget = 2, +- Ip6OptionPrefixInfo = 3, +- Ip6OptionRedirected = 4, +- Ip6OptionMtu = 5 ++ Ip6OptionEtherSource = 1, ++ Ip6OptionEtherTarget = 2, ++ Ip6OptionPrefixInfo = 3, ++ Ip6OptionRedirected = 4, ++ Ip6OptionMtu = 5 + } IP6_OPTION_TYPE; + + /** +@@ -72,17 +72,17 @@ typedef enum { + **/ + BOOLEAN + Ip6IsExtsValid ( +- IN IP6_SERVICE *IpSb OPTIONAL, +- IN NET_BUF *Packet OPTIONAL, +- IN UINT8 *NextHeader, +- IN UINT8 *ExtHdrs, +- IN UINT32 ExtHdrsLen, +- IN BOOLEAN Rcvd, +- OUT UINT32 *FormerHeader OPTIONAL, +- OUT UINT8 **LastHeader, +- OUT UINT32 *RealExtsLen OPTIONAL, +- OUT UINT32 *UnFragmentLen OPTIONAL, +- OUT BOOLEAN *Fragmented OPTIONAL ++ IN IP6_SERVICE *IpSb OPTIONAL, ++ IN NET_BUF *Packet OPTIONAL, ++ IN UINT8 *NextHeader, ++ IN UINT8 *ExtHdrs, ++ IN UINT32 ExtHdrsLen, ++ IN BOOLEAN Rcvd, ++ OUT UINT32 *FormerHeader OPTIONAL, ++ OUT UINT8 **LastHeader, ++ OUT UINT32 *RealExtsLen OPTIONAL, ++ OUT UINT32 *UnFragmentLen OPTIONAL, ++ OUT BOOLEAN *Fragmented OPTIONAL + ); + + /** +@@ -101,9 +101,9 @@ Ip6IsExtsValid ( + **/ + EFI_STATUS + Ip6FillHopByHop ( +- OUT UINT8 *Buffer, +- IN OUT UINTN *BufferLen, +- IN UINT8 NextHeader ++ OUT UINT8 *Buffer, ++ IN OUT UINTN *BufferLen, ++ IN UINT8 NextHeader + ); + + /** +@@ -127,13 +127,13 @@ Ip6FillHopByHop ( + **/ + EFI_STATUS + Ip6FillFragmentHeader ( +- IN IP6_SERVICE *IpSb, +- IN UINT8 NextHeader, +- IN UINT8 LastHeader, +- IN UINT8 *ExtHdrs, +- IN UINT32 ExtHdrsLen, +- IN UINT16 FragmentOffset, +- OUT UINT8 **UpdatedExtHdrs ++ IN IP6_SERVICE *IpSb, ++ IN UINT8 NextHeader, ++ IN UINT8 LastHeader, ++ IN UINT8 *ExtHdrs, ++ IN UINT32 ExtHdrsLen, ++ IN UINT16 FragmentOffset, ++ OUT UINT8 **UpdatedExtHdrs + ); + + /** +@@ -155,13 +155,13 @@ Ip6FillFragmentHeader ( + **/ + EFI_STATUS + Ip6CopyExts ( +- IN UINT8 NextHeader, +- IN UINT8 *ExtHdrs, +- IN UINT8 *LastHeader, +- IN UINT16 FragmentOffset, +- IN UINT32 UnFragmentHdrLen, +- IN OUT UINT8 *Buf, +- IN OUT UINT32 *BufLen ++ IN UINT8 NextHeader, ++ IN UINT8 *ExtHdrs, ++ IN UINT8 *LastHeader, ++ IN UINT16 FragmentOffset, ++ IN UINT32 UnFragmentHdrLen, ++ IN OUT UINT8 *Buf, ++ IN OUT UINT32 *BufLen + ); + + /** +@@ -178,8 +178,8 @@ Ip6CopyExts ( + **/ + BOOLEAN + Ip6IsNDOptionValid ( +- IN UINT8 *Option, +- IN UINT16 OptionLen ++ IN UINT8 *Option, ++ IN UINT16 OptionLen + ); + + #endif +-- +2.39.3 + diff --git a/edk2-ArmVirtPkg-ArmVirtQemu-migrate-to-OVMF-s-VirtNorFlas.patch b/edk2-ArmVirtPkg-ArmVirtQemu-migrate-to-OVMF-s-VirtNorFlas.patch new file mode 100644 index 0000000..43848d5 --- /dev/null +++ b/edk2-ArmVirtPkg-ArmVirtQemu-migrate-to-OVMF-s-VirtNorFlas.patch @@ -0,0 +1,149 @@ +From 9ef10bbe9a03f22aa5c5ff659012794d37ef9839 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 24 Oct 2022 18:41:22 +0200 +Subject: [PATCH 17/18] ArmVirtPkg/ArmVirtQemu: migrate to OVMF's + VirtNorFlashDxe + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [19/20] 2160140b0ea566451ab723e941d2ab91e1ad874e + +Switch to the virt specific NorFlashDxe driver implementation that was +added recently. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Sunil V L +(cherry picked from commit b92298af8218dd074c231947bc95f2be94af663c) +--- + ArmVirtPkg/ArmVirtQemu.dsc | 4 ++-- + ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc | 2 +- + ArmVirtPkg/ArmVirtQemuKernel.dsc | 4 ++-- + ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c | 12 ++++++------ + .../Library/NorFlashQemuLib/NorFlashQemuLib.inf | 4 ++-- + 5 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc +index e6fad9f066..2b23becf30 100644 +--- a/ArmVirtPkg/ArmVirtQemu.dsc ++++ b/ArmVirtPkg/ArmVirtQemu.dsc +@@ -67,7 +67,7 @@ + ArmPlatformLib|ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.inf + + TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf +- NorFlashPlatformLib|ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf ++ VirtNorFlashPlatformLib|ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf + + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf +@@ -400,7 +400,7 @@ + + NULL|ArmVirtPkg/Library/ArmVirtTimerFdtClientLib/ArmVirtTimerFdtClientLib.inf + } +- ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf ++ OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + + # +diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc +index f6a538df72..7c655d384d 100644 +--- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc ++++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc +@@ -73,7 +73,7 @@ READ_LOCK_STATUS = TRUE + + INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf + INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf +- INF ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf ++ INF OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf + INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + + # +diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc +index 656c9d99a3..344e2c4ed9 100644 +--- a/ArmVirtPkg/ArmVirtQemuKernel.dsc ++++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc +@@ -65,7 +65,7 @@ + ArmVirtMemInfoLib|ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoLib.inf + + TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf +- NorFlashPlatformLib|ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf ++ VirtNorFlashPlatformLib|ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf + + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf +@@ -329,7 +329,7 @@ + + NULL|ArmVirtPkg/Library/ArmVirtTimerFdtClientLib/ArmVirtTimerFdtClientLib.inf + } +- ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf ++ OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + + # +diff --git a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c +index 271d7f0efb..93a2fed40f 100644 +--- a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c ++++ b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c +@@ -8,8 +8,8 @@ + + #include + #include +-#include + #include ++#include + + #include + +@@ -18,19 +18,19 @@ + #define MAX_FLASH_BANKS 4 + + EFI_STATUS +-NorFlashPlatformInitialization ( ++VirtNorFlashPlatformInitialization ( + VOID + ) + { + return EFI_SUCCESS; + } + +-NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS]; ++STATIC VIRT_NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS]; + + EFI_STATUS +-NorFlashPlatformGetDevices ( +- OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions, +- OUT UINT32 *Count ++VirtNorFlashPlatformGetDevices ( ++ OUT VIRT_NOR_FLASH_DESCRIPTION **NorFlashDescriptions, ++ OUT UINT32 *Count + ) + { + FDT_CLIENT_PROTOCOL *FdtClient; +diff --git a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf +index 4c3683bf5d..a6b5865be9 100644 +--- a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf ++++ b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf +@@ -14,17 +14,17 @@ + FILE_GUID = 339B7829-4C5F-4EFC-B2DD-5050E530DECE + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 +- LIBRARY_CLASS = NorFlashPlatformLib ++ LIBRARY_CLASS = VirtNorFlashPlatformLib + + [Sources.common] + NorFlashQemuLib.c + + [Packages] + MdePkg/MdePkg.dec +- ArmPlatformPkg/ArmPlatformPkg.dec + ArmPkg/ArmPkg.dec + ArmVirtPkg/ArmVirtPkg.dec + EmbeddedPkg/EmbeddedPkg.dec ++ OvmfPkg/OvmfPkg.dec + + [LibraryClasses] + BaseLib +-- +2.41.0 + diff --git a/edk2-EmbeddedPkg-Hob-Integer-Overflow-in-CreateHob.patch b/edk2-EmbeddedPkg-Hob-Integer-Overflow-in-CreateHob.patch new file mode 100644 index 0000000..8a5d148 --- /dev/null +++ b/edk2-EmbeddedPkg-Hob-Integer-Overflow-in-CreateHob.patch @@ -0,0 +1,174 @@ +From f8691984227809170b702f6fd087add1f95ee8fe Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 5 Mar 2024 16:38:49 -0500 +Subject: [PATCH 1/2] EmbeddedPkg/Hob: Integer Overflow in CreateHob() + +RH-Author: Jon Maloy +RH-MergeRequest: 66: EmbeddedPkg/Hob: Integer Overflow in CreateHob() +RH-Jira: RHEL-21158 +RH-Acked-by: Oliver Steffen +RH-Acked-by: Gerd Hoffmann +RH-Commit: [1/2] 301d3bfe82c39179fb85d510788831aa340212d9 + +JIRA: https://issues.redhat.com/browse/RHEL-21158 +CVE: CVE-2022-36765 +Upstream: Merged + +commit aeaee8944f0eaacbf4cdf39279785b9ba4836bb6 +Author: Gua Guo +Date: Thu Jan 11 13:07:50 2024 +0800 + + EmbeddedPkg/Hob: Integer Overflow in CreateHob() + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4166 + + Fix integer overflow in various CreateHob instances. + Fixes: CVE-2022-36765 + + The CreateHob() function aligns the requested size to 8 + performing the following operation: + ``` + HobLength = (UINT16)((HobLength + 0x7) & (~0x7)); + ``` + + No checks are performed to ensure this value doesn't + overflow, and could lead to CreateHob() returning a smaller + HOB than requested, which could lead to OOB HOB accesses. + + Reported-by: Marc Beatove + Cc: Leif Lindholm + Reviewed-by: Ard Biesheuvel + Cc: Abner Chang + Cc: John Mathew + Authored-by: Gerd Hoffmann + Signed-off-by: Gua Guo + +Signed-off-by: Jon Maloy +--- + EmbeddedPkg/Library/PrePiHobLib/Hob.c | 47 +++++++++++++++++++++++++-- + 1 file changed, 45 insertions(+), 2 deletions(-) + +diff --git a/EmbeddedPkg/Library/PrePiHobLib/Hob.c b/EmbeddedPkg/Library/PrePiHobLib/Hob.c +index b5cc6c5d8f..f4c99369c6 100644 +--- a/EmbeddedPkg/Library/PrePiHobLib/Hob.c ++++ b/EmbeddedPkg/Library/PrePiHobLib/Hob.c +@@ -112,6 +112,13 @@ CreateHob ( + + HandOffHob = GetHobList (); + ++ // ++ // Check Length to avoid data overflow. ++ // ++ if (HobLength > MAX_UINT16 - 0x7) { ++ return NULL; ++ } ++ + HobLength = (UINT16)((HobLength + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom; +@@ -161,7 +168,10 @@ BuildResourceDescriptorHob ( + EFI_HOB_RESOURCE_DESCRIPTOR *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); +- ASSERT(Hob != NULL); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; +@@ -403,6 +413,10 @@ BuildModuleHob ( + ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid); + Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; +@@ -450,7 +464,12 @@ BuildGuidHob ( + // + ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE))); + +- Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength)); ++ Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16)(sizeof (EFI_HOB_GUID_TYPE) + DataLength)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return NULL; ++ } ++ + CopyGuid (&Hob->Name, Guid); + return Hob + 1; + } +@@ -516,6 +535,10 @@ BuildFvHob ( + EFI_HOB_FIRMWARE_VOLUME *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +@@ -548,6 +571,10 @@ BuildFv2Hob ( + EFI_HOB_FIRMWARE_VOLUME2 *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +@@ -589,6 +616,10 @@ BuildFv3Hob ( + EFI_HOB_FIRMWARE_VOLUME3 *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV3, sizeof (EFI_HOB_FIRMWARE_VOLUME3)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +@@ -645,6 +676,10 @@ BuildCpuHob ( + EFI_HOB_CPU *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + Hob->SizeOfMemorySpace = SizeOfMemorySpace; + Hob->SizeOfIoSpace = SizeOfIoSpace; +@@ -681,6 +716,10 @@ BuildStackHob ( + ((Length & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocStackGuid); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; +@@ -761,6 +800,10 @@ BuildMemoryAllocationHob ( + ((Length & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID)); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; +-- +2.39.3 + diff --git a/edk2-MdePkg-Introduce-CcMeasurementProtocol-for-CC-Guest-.patch b/edk2-MdePkg-Introduce-CcMeasurementProtocol-for-CC-Guest-.patch new file mode 100644 index 0000000..df008db --- /dev/null +++ b/edk2-MdePkg-Introduce-CcMeasurementProtocol-for-CC-Guest-.patch @@ -0,0 +1,390 @@ +From b8261ac422ba284249cd4f341d78d058e79960f5 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 7 Feb 2024 11:56:37 -0500 +Subject: [PATCH 03/17] MdePkg: Introduce CcMeasurementProtocol for CC Guest + firmware + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [3/13] 6bf304f8e3bc875024c8fb0a4cd5d2c944f69480 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21154 +CVE: CVE-2022-36763 +Upstream: Merged + +commit e193584da60550008722498442c62ddb77bf27d5 +Author: Min Xu +Date: Sat Dec 11 21:08:40 2021 +0800 + + MdePkg: Introduce CcMeasurementProtocol for CC Guest firmware + + BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3625 + + CC guest is a Confidential Computing guest. If CC Guest firmware + supports measurement and an event is created, CC Guest firmware + is designed to report the event log with the same data structure + in TCG-Platform-Firmware-Profile specification with + EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 format. + + The CC Guest firmware supports measurement. It is designed to + produce EFI_CC_MEASUREMENT_PROTOCOL with new GUID + EFI_CC_MEASUREMENT_PROTOCOL_GUID to report event log and provides + hash capability. + + Cc: Michael D Kinney + Cc: Liming Gao + Cc: Zhiguang Liu + Cc: Jiewen Yao + Cc: Jian J Wang + Cc: Ken Lu + Cc: Sami Mujawar + Cc: Gerd Hoffmann + Reviewed-by: Liming Gao + Reviewed-by: Sami Mujawar + Reviewed-by: Jiewen Yao + Signed-off-by: Min Xu + +Signed-off-by: Jon Maloy +--- + MdePkg/Include/Protocol/CcMeasurement.h | 302 ++++++++++++++++++++++++ + MdePkg/MdePkg.dec | 6 + + 2 files changed, 308 insertions(+) + create mode 100644 MdePkg/Include/Protocol/CcMeasurement.h + +diff --git a/MdePkg/Include/Protocol/CcMeasurement.h b/MdePkg/Include/Protocol/CcMeasurement.h +new file mode 100644 +index 0000000000..68029e977f +--- /dev/null ++++ b/MdePkg/Include/Protocol/CcMeasurement.h +@@ -0,0 +1,302 @@ ++/** @file ++ If CC Guest firmware supports measurement and an event is created, ++ CC Guest firmware is designed to report the event log with the same ++ data structure in TCG-Platform-Firmware-Profile specification with ++ EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 format. ++ ++ The CC Guest firmware supports measurement, the CC Guest Firmware is ++ designed to produce EFI_CC_MEASUREMENT_PROTOCOL with new GUID ++ EFI_CC_MEASUREMENT_PROTOCOL_GUID to report event log and provides hash ++ capability. ++ ++Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
++SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#ifndef CC_MEASUREMENT_PROTOCOL_H_ ++#define CC_MEASUREMENT_PROTOCOL_H_ ++ ++#include ++ ++#define EFI_CC_MEASUREMENT_PROTOCOL_GUID \ ++ { 0x96751a3d, 0x72f4, 0x41a6, { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b }} ++extern EFI_GUID gEfiCcMeasurementProtocolGuid; ++ ++typedef struct _EFI_CC_MEASUREMENT_PROTOCOL EFI_CC_MEASUREMENT_PROTOCOL; ++ ++typedef struct { ++ UINT8 Major; ++ UINT8 Minor; ++} EFI_CC_VERSION; ++ ++// ++// EFI_CC Type/SubType definition ++// ++#define EFI_CC_TYPE_NONE 0 ++#define EFI_CC_TYPE_SEV 1 ++#define EFI_CC_TYPE_TDX 2 ++ ++typedef struct { ++ UINT8 Type; ++ UINT8 SubType; ++} EFI_CC_TYPE; ++ ++typedef UINT32 EFI_CC_EVENT_LOG_BITMAP; ++typedef UINT32 EFI_CC_EVENT_LOG_FORMAT; ++typedef UINT32 EFI_CC_EVENT_ALGORITHM_BITMAP; ++typedef UINT32 EFI_CC_MR_INDEX; ++ ++// ++// Intel TDX measure register index ++// ++#define TDX_MR_INDEX_MRTD 0 ++#define TDX_MR_INDEX_RTMR0 1 ++#define TDX_MR_INDEX_RTMR1 2 ++#define TDX_MR_INDEX_RTMR2 3 ++#define TDX_MR_INDEX_RTMR3 4 ++ ++#define EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002 ++#define EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004 ++ ++// ++// This bit is shall be set when an event shall be extended but not logged. ++// ++#define EFI_CC_FLAG_EXTEND_ONLY 0x0000000000000001 ++// ++// This bit shall be set when the intent is to measure a PE/COFF image. ++// ++#define EFI_CC_FLAG_PE_COFF_IMAGE 0x0000000000000010 ++ ++#pragma pack (1) ++ ++#define EFI_CC_EVENT_HEADER_VERSION 1 ++ ++typedef struct { ++ // ++ // Size of the event header itself (sizeof(EFI_CC_EVENT_HEADER)). ++ // ++ UINT32 HeaderSize; ++ // ++ // Header version. For this version of this specification, the value shall be 1. ++ // ++ UINT16 HeaderVersion; ++ // ++ // Index of the MR (measurement register) that shall be extended. ++ // ++ EFI_CC_MR_INDEX MrIndex; ++ // ++ // Type of the event that shall be extended (and optionally logged). ++ // ++ UINT32 EventType; ++} EFI_CC_EVENT_HEADER; ++ ++typedef struct { ++ // ++ // Total size of the event including the Size component, the header and the Event data. ++ // ++ UINT32 Size; ++ EFI_CC_EVENT_HEADER Header; ++ UINT8 Event[1]; ++} EFI_CC_EVENT; ++ ++#pragma pack() ++ ++typedef struct { ++ // ++ // Allocated size of the structure ++ // ++ UINT8 Size; ++ // ++ // Version of the EFI_CC_BOOT_SERVICE_CAPABILITY structure itself. ++ // For this version of the protocol, the Major version shall be set to 1 ++ // and the Minor version shall be set to 0. ++ // ++ EFI_CC_VERSION StructureVersion; ++ // ++ // Version of the EFI CC Measurement protocol. ++ // For this version of the protocol, the Major version shall be set to 1 ++ // and the Minor version shall be set to 0. ++ // ++ EFI_CC_VERSION ProtocolVersion; ++ // ++ // Supported hash algorithms ++ // ++ EFI_CC_EVENT_ALGORITHM_BITMAP HashAlgorithmBitmap; ++ // ++ // Bitmap of supported event log formats ++ // ++ EFI_CC_EVENT_LOG_BITMAP SupportedEventLogs; ++ ++ // ++ // Indicates the CC type ++ // ++ EFI_CC_TYPE CcType; ++} EFI_CC_BOOT_SERVICE_CAPABILITY; ++ ++/** ++ The EFI_CC_MEASUREMENT_PROTOCOL GetCapability function call provides protocol ++ capability information and state information. ++ ++ @param[in] This Indicates the calling context ++ @param[in, out] ProtocolCapability The caller allocates memory for a EFI_CC_BOOT_SERVICE_CAPABILITY ++ structure and sets the size field to the size of the structure allocated. ++ The callee fills in the fields with the EFI CC BOOT Service capability ++ information and the current CC information. ++ ++ @retval EFI_SUCCESS Operation completed successfully. ++ @retval EFI_DEVICE_ERROR The command was unsuccessful. ++ The ProtocolCapability variable will not be populated. ++ @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. ++ The ProtocolCapability variable will not be populated. ++ @retval EFI_BUFFER_TOO_SMALL The ProtocolCapability variable is too small to hold the full response. ++ It will be partially populated (required Size field will be set). ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_CC_GET_CAPABILITY)( ++ IN EFI_CC_MEASUREMENT_PROTOCOL *This, ++ IN OUT EFI_CC_BOOT_SERVICE_CAPABILITY *ProtocolCapability ++ ); ++ ++/** ++ The EFI_CC_MEASUREMENT_PROTOCOL Get Event Log function call allows a caller to ++ retrieve the address of a given event log and its last entry. ++ ++ @param[in] This Indicates the calling context ++ @param[in] EventLogFormat The type of the event log for which the information is requested. ++ @param[out] EventLogLocation A pointer to the memory address of the event log. ++ @param[out] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the ++ address of the start of the last entry in the event log in memory. ++ @param[out] EventLogTruncated If the Event Log is missing at least one entry because an event would ++ have exceeded the area allocated for events, this value is set to TRUE. ++ Otherwise, the value will be FALSE and the Event Log will be complete. ++ ++ @retval EFI_SUCCESS Operation completed successfully. ++ @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect ++ (e.g. asking for an event log whose format is not supported). ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_CC_GET_EVENT_LOG)( ++ IN EFI_CC_MEASUREMENT_PROTOCOL *This, ++ IN EFI_CC_EVENT_LOG_FORMAT EventLogFormat, ++ OUT EFI_PHYSICAL_ADDRESS *EventLogLocation, ++ OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry, ++ OUT BOOLEAN *EventLogTruncated ++ ); ++ ++/** ++ The EFI_CC_MEASUREMENT_PROTOCOL HashLogExtendEvent function call provides ++ callers with an opportunity to extend and optionally log events without requiring ++ knowledge of actual CC commands. ++ The extend operation will occur even if this function cannot create an event ++ log entry (e.g. due to the event log being full). ++ ++ @param[in] This Indicates the calling context ++ @param[in] Flags Bitmap providing additional information. ++ @param[in] DataToHash Physical address of the start of the data buffer to be hashed. ++ @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash. ++ @param[in] EfiCcEvent Pointer to data buffer containing information about the event. ++ ++ @retval EFI_SUCCESS Operation completed successfully. ++ @retval EFI_DEVICE_ERROR The command was unsuccessful. ++ @retval EFI_VOLUME_FULL The extend operation occurred, but the event could not be written to one or more event logs. ++ @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. ++ @retval EFI_UNSUPPORTED The PE/COFF image type is not supported. ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_CC_HASH_LOG_EXTEND_EVENT)( ++ IN EFI_CC_MEASUREMENT_PROTOCOL *This, ++ IN UINT64 Flags, ++ IN EFI_PHYSICAL_ADDRESS DataToHash, ++ IN UINT64 DataToHashLen, ++ IN EFI_CC_EVENT *EfiCcEvent ++ ); ++ ++/** ++ The EFI_CC_MEASUREMENT_PROTOCOL MapPcrToMrIndex function call provides callers ++ the info on TPM PCR <-> CC MR mapping information. ++ ++ @param[in] This Indicates the calling context ++ @param[in] PcrIndex TPM PCR index. ++ @param[out] MrIndex CC MR index. ++ ++ @retval EFI_SUCCESS The MrIndex is returned. ++ @retval EFI_INVALID_PARAMETER The MrIndex is NULL. ++ @retval EFI_UNSUPPORTED The PcrIndex is invalid. ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_CC_MAP_PCR_TO_MR_INDEX)( ++ IN EFI_CC_MEASUREMENT_PROTOCOL *This, ++ IN TCG_PCRINDEX PcrIndex, ++ OUT EFI_CC_MR_INDEX *MrIndex ++ ); ++ ++struct _EFI_CC_MEASUREMENT_PROTOCOL { ++ EFI_CC_GET_CAPABILITY GetCapability; ++ EFI_CC_GET_EVENT_LOG GetEventLog; ++ EFI_CC_HASH_LOG_EXTEND_EVENT HashLogExtendEvent; ++ EFI_CC_MAP_PCR_TO_MR_INDEX MapPcrToMrIndex; ++}; ++ ++// ++// CC event log ++// ++ ++#pragma pack(1) ++ ++// ++// Crypto Agile Log Entry Format. ++// It is similar with TCG_PCR_EVENT2 except the field of MrIndex and PCRIndex. ++// ++typedef struct { ++ EFI_CC_MR_INDEX MrIndex; ++ UINT32 EventType; ++ TPML_DIGEST_VALUES Digests; ++ UINT32 EventSize; ++ UINT8 Event[1]; ++} CC_EVENT; ++ ++// ++// EFI CC Event Header ++// It is similar with TCG_PCR_EVENT2_HDR except the field of MrIndex and PCRIndex ++// ++typedef struct { ++ EFI_CC_MR_INDEX MrIndex; ++ UINT32 EventType; ++ TPML_DIGEST_VALUES Digests; ++ UINT32 EventSize; ++} CC_EVENT_HDR; ++ ++#pragma pack() ++ ++// ++// Log entries after Get Event Log service ++// ++ ++#define EFI_CC_FINAL_EVENTS_TABLE_VERSION 1 ++ ++typedef struct { ++ // ++ // The version of this structure. It shall be set to 1. ++ // ++ UINT64 Version; ++ // ++ // Number of events recorded after invocation of GetEventLog API ++ // ++ UINT64 NumberOfEvents; ++ // ++ // List of events of type CC_EVENT. ++ // ++ // CC_EVENT Event[1]; ++} EFI_CC_FINAL_EVENTS_TABLE; ++ ++#define EFI_CC_FINAL_EVENTS_TABLE_GUID \ ++ {0xdd4a4648, 0x2de7, 0x4665, {0x96, 0x4d, 0x21, 0xd9, 0xef, 0x5f, 0xb4, 0x46}} ++ ++extern EFI_GUID gEfiCcFinalEventsTableGuid; ++ ++#endif +diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec +index 8b18415b10..6389a48338 100644 +--- a/MdePkg/MdePkg.dec ++++ b/MdePkg/MdePkg.dec +@@ -823,6 +823,9 @@ + # + gLinuxEfiInitrdMediaGuid = {0x5568e427, 0x68fc, 0x4f3d, {0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68}} + ++ ## Include/Protocol/CcMeasurement.h ++ gEfiCcFinalEventsTableGuid = { 0xdd4a4648, 0x2de7, 0x4665, { 0x96, 0x4d, 0x21, 0xd9, 0xef, 0x5f, 0xb4, 0x46 }} ++ + [Guids.IA32, Guids.X64] + ## Include/Guid/Cper.h + gEfiIa32X64ErrorTypeCacheCheckGuid = { 0xA55701F5, 0xE3EF, 0x43de, { 0xAC, 0x72, 0x24, 0x9B, 0x57, 0x3F, 0xAD, 0x2C }} +@@ -1011,6 +1014,9 @@ + ## Include/Protocol/PcdInfo.h + gGetPcdInfoProtocolGuid = { 0x5be40f57, 0xfa68, 0x4610, { 0xbb, 0xbf, 0xe9, 0xc5, 0xfc, 0xda, 0xd3, 0x65 } } + ++ ## Include/Protocol/CcMeasurement.h ++ gEfiCcMeasurementProtocolGuid = { 0x96751a3d, 0x72f4, 0x41a6, { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b }} ++ + # + # Protocols defined in PI1.0. + # +-- +2.41.0 + diff --git a/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch b/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch new file mode 100644 index 0000000..b984c70 --- /dev/null +++ b/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch @@ -0,0 +1,169 @@ +From aa66757951e9880df4e21e191142400480aa3908 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 8 Feb 2024 10:35:14 -0500 +Subject: [PATCH 15/17] NetworkPkg: : Add Unit tests to CI and create Host Test + DSC + +RH-Author: Jon Maloy +RH-MergeRequest: 50: CVE-2023-45230 and CVE-2023-45229 +RH-Jira: RHEL-21840 RHEL-21842 +RH-Acked-by: Oliver Steffen +RH-Commit: [2/4] 6669306e2dbb5aa3e7691d57f4a61685b7cd57b2 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21842 +CVE: CVE-2023-45230 +Upstream: Merged + +commit 8014ac2d7bbbc503f5562b51af46bb20ae3d22ff +Author: Doug Flick via groups.io +Date: Fri Jan 26 05:54:44 2024 +0800 + + NetworkPkg: : Add Unit tests to CI and create Host Test DSC + + Adds Host Based testing to the NetworkPkg + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/NetworkPkg.ci.yaml | 7 +- + NetworkPkg/Test/NetworkPkgHostTest.dsc | 98 ++++++++++++++++++++++++++ + 2 files changed, 104 insertions(+), 1 deletion(-) + create mode 100644 NetworkPkg/Test/NetworkPkgHostTest.dsc + +diff --git a/NetworkPkg/NetworkPkg.ci.yaml b/NetworkPkg/NetworkPkg.ci.yaml +index 07dc7abd69..076424eb60 100644 +--- a/NetworkPkg/NetworkPkg.ci.yaml ++++ b/NetworkPkg/NetworkPkg.ci.yaml +@@ -24,6 +24,9 @@ + "CompilerPlugin": { + "DscPath": "NetworkPkg.dsc" + }, ++ "HostUnitTestCompilerPlugin": { ++ "DscPath": "Test/NetworkPkgHostTest.dsc" ++ }, + "CharEncodingCheck": { + "IgnoreFiles": [] + }, +@@ -35,7 +38,9 @@ + "CryptoPkg/CryptoPkg.dec" + ], + # For host based unit tests +- "AcceptableDependencies-HOST_APPLICATION":[], ++ "AcceptableDependencies-HOST_APPLICATION":[ ++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec ++ ], + # For UEFI shell based apps + "AcceptableDependencies-UEFI_APPLICATION":[ + "ShellPkg/ShellPkg.dec" +diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc +new file mode 100644 +index 0000000000..1aeca5c5b3 +--- /dev/null ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -0,0 +1,98 @@ ++## @file ++# NetworkPkgHostTest DSC file used to build host-based unit tests. ++# ++# Copyright (c) Microsoft Corporation.
++# SPDX-License-Identifier: BSD-2-Clause-Patent ++# ++## ++[Defines] ++ PLATFORM_NAME = NetworkPkgHostTest ++ PLATFORM_GUID = 3b68324e-fc07-4d49-9520-9347ede65879 ++ PLATFORM_VERSION = 0.1 ++ DSC_SPECIFICATION = 0x00010005 ++ OUTPUT_DIRECTORY = Build/NetworkPkg/HostTest ++ SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64 ++ BUILD_TARGETS = NOOPT ++ SKUID_IDENTIFIER = DEFAULT ++ ++!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc ++[Packages] ++ MdePkg/MdePkg.dec ++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec ++ ++[Components] ++ # ++ # Build HOST_APPLICATION that tests NetworkPkg ++ # ++ ++# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests. ++[LibraryClasses] ++ NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf ++ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf ++ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf ++ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf ++ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf ++ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf ++ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf ++ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf ++ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf ++ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf ++ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf ++ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf ++ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf ++ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf ++ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf ++ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf ++ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf ++ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf ++ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf ++ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf ++ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf ++ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf ++ RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf ++ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf ++!ifdef CONTINUOUS_INTEGRATION ++ BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf ++ TlsLib|CryptoPkg/Library/TlsLibNull/TlsLibNull.inf ++!else ++ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf ++ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf ++ TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf ++!endif ++ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf ++ FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf ++ FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf ++ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf ++ IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf ++ ++!if $(TOOL_CHAIN_TAG) == VS2019 or $(TOOL_CHAIN_TAG) == VS2022 ++[LibraryClasses.X64] ++ # Provide StackCookie support lib so that we can link to /GS exports for VS builds ++ RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf ++!endif ++ ++[LibraryClasses.common.UEFI_DRIVER] ++ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf ++ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf ++ DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf ++[LibraryClasses.common.UEFI_APPLICATION] ++ DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf ++ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf ++[LibraryClasses.ARM, LibraryClasses.AARCH64] ++ # ++ # It is not possible to prevent ARM compiler calls to generic intrinsic functions. ++ # This library provides the instrinsic functions generated by a given compiler. ++ # [LibraryClasses.ARM] and NULL mean link this library into all ARM images. ++ # ++!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019 ++ NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf ++!endif ++ NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf ++[LibraryClasses.ARM] ++ RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf ++[LibraryClasses.RISCV64] ++ RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf ++ ++[PcdsFixedAtBuild] ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2 ++ gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|0x4 +-- +2.41.0 + diff --git a/edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch b/edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch new file mode 100644 index 0000000..2c0ae8b --- /dev/null +++ b/edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch @@ -0,0 +1,170 @@ +From ffa1202da2f55c1f540240e8267db9a7ec8d6a60 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 11/15] NetworkPkg: : Adds a SecurityFix.yaml file + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [11/15] 8a46b763887843d00293997bdd7d50ea120104d9 + +JIRA: https://issues.redhat.com/browse/RHEL-21852 +CVE: CVE-2022-45235 +Upstream: Merged + +commit 1d0b95f6457d225c5108302a9da74b4ed7aa5a38 +Author: Doug Flick via groups.io +Date: Fri Jan 26 05:54:57 2024 +0800 + + NetworkPkg: : Adds a SecurityFix.yaml file + + This creates / adds a security file that tracks the security fixes + found in this package and can be used to find the fixes that were + applied. + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/SecurityFixes.yaml | 123 ++++++++++++++++++++++++++++++++++ + 1 file changed, 123 insertions(+) + create mode 100644 NetworkPkg/SecurityFixes.yaml + +diff --git a/NetworkPkg/SecurityFixes.yaml b/NetworkPkg/SecurityFixes.yaml +new file mode 100644 +index 0000000000..7e900483fe +--- /dev/null ++++ b/NetworkPkg/SecurityFixes.yaml +@@ -0,0 +1,123 @@ ++## @file ++# Security Fixes for SecurityPkg ++# ++# Copyright (c) Microsoft Corporation ++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++CVE_2023_45229: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests" ++ cve: CVE-2023-45229 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 01 - edk2/NetworkPkg: Out-of-bounds read when processing IA_NA/IA_TA options in a DHCPv6 Advertise message" ++ note: ++ files_impacted: ++ - NetworkPkg\Dhcp6Dxe\Dhcp6Io.c ++ - NetworkPkg\Dhcp6Dxe\Dhcp6Impl.h ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4534 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45229 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45230: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests" ++ cve: CVE-2023-45230 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 02 - edk2/NetworkPkg: Buffer overflow in the DHCPv6 client via a long Server ID option" ++ note: ++ files_impacted: ++ - NetworkPkg\Dhcp6Dxe\Dhcp6Io.c ++ - NetworkPkg\Dhcp6Dxe\Dhcp6Impl.h ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4535 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45230 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45231: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45231 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests" ++ cve: CVE-2023-45231 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 03 - edk2/NetworkPkg: Out-of-bounds read when handling a ND Redirect message with truncated options" ++ note: ++ files_impacted: ++ - NetworkPkg/Ip6Dxe/Ip6Option.c ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4536 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45231 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45232: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests" ++ cve: CVE-2023-45232 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 04 - edk2/NetworkPkg: Infinite loop when parsing unknown options in the Destination Options header" ++ note: ++ files_impacted: ++ - NetworkPkg/Ip6Dxe/Ip6Option.c ++ - NetworkPkg/Ip6Dxe/Ip6Option.h ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4537 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45232 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45233: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests" ++ cve: CVE-2023-45233 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 05 - edk2/NetworkPkg: Infinite loop when parsing a PadN option in the Destination Options header " ++ note: This was fixed along with CVE-2023-45233 ++ files_impacted: ++ - NetworkPkg/Ip6Dxe/Ip6Option.c ++ - NetworkPkg/Ip6Dxe/Ip6Option.h ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4538 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45233 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45234: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45234 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45234 Unit Tests" ++ cve: CVE-2023-45234 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 06 - edk2/NetworkPkg: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message" ++ note: ++ files_impacted: ++ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4539 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45234 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45235: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45235 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45235 Unit Tests" ++ cve: CVE-2023-45235 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 07 - edk2/NetworkPkg: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message" ++ note: ++ files_impacted: ++ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4540 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45235 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Apply-uncrustify-changes-p2.patch b/edk2-NetworkPkg-Apply-uncrustify-changes-p2.patch new file mode 100644 index 0000000..d51d127 --- /dev/null +++ b/edk2-NetworkPkg-Apply-uncrustify-changes-p2.patch @@ -0,0 +1,2054 @@ +From f7e6d9e61173d76ab9827e1af62dc9966a21e14c Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 17:28:51 -0500 +Subject: [PATCH 12/15] NetworkPkg: Apply uncrustify changes + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [12/15] 880596c246c87181f19fcb0a7a21f4e32d234c13 + +JIRA: https://issues.redhat.com/browse/RHEL-21840 +CVE: CVE-2022-45229 +Upstream: Merged +Conflicts: There has already been added two commits after the point where + this commit was added upstream, so we cannot apply that commit, + or even parts of it, directly. Instead, we only introduce the + whitespace changes needed to make future commits touching + the file NetworkPkg/Dhcp6Dxe/Dhcp6Io.c apply cleanly. + +commit d1050b9dff1cace252aff86630bfdb59dff5f507 +Author: Michael Kubacki +Date: Sun Dec 5 14:54:07 2021 -0800 + + NetworkPkg: Apply uncrustify changes + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 + + Apply uncrustify changes to .c/.h files in the NetworkPkg package + + Cc: Andrew Fish + Cc: Leif Lindholm + Cc: Michael D Kinney + Signed-off-by: Michael Kubacki + Reviewed-by: Maciej Rabeda + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 1091 ++++++++++++++++----------------- + 1 file changed, 529 insertions(+), 562 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +index d680febbf1..3b8feb4a20 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +@@ -10,7 +10,6 @@ + + #include "Dhcp6Impl.h" + +- + /** + Enqueue the packet into the retry list in case of timeout. + +@@ -34,8 +33,8 @@ Dhcp6EnqueueRetry ( + IN EFI_DHCP6_RETRANSMISSION *RetryCtl OPTIONAL + ) + { +- DHCP6_TX_CB *TxCb; +- DHCP6_IA_CB *IaCb; ++ DHCP6_TX_CB *TxCb; ++ DHCP6_IA_CB *IaCb; + + ASSERT (Packet != NULL); + +@@ -55,156 +54,156 @@ Dhcp6EnqueueRetry ( + // + // Save pointer to elapsed-time value so we can update it on retransmits. + // +- TxCb->Elapsed = Elapsed; ++ TxCb->Elapsed = Elapsed; + + // + // Calculate the retransmission according to the message type. + // + switch (Packet->Dhcp6.Header.MessageType) { +- case Dhcp6MsgSolicit: +- // +- // Calculate the retransmission threshold value for solicit packet. +- // Use the default value by rfc-3315 if user doesn't configure. +- // +- if (RetryCtl == NULL) { +- TxCb->RetryCtl.Irt = DHCP6_SOL_IRT; +- TxCb->RetryCtl.Mrc = DHCP6_SOL_MRC; +- TxCb->RetryCtl.Mrt = DHCP6_SOL_MRT; +- TxCb->RetryCtl.Mrd = DHCP6_SOL_MRD; +- } else { +- TxCb->RetryCtl.Irt = (RetryCtl->Irt != 0) ? RetryCtl->Irt : DHCP6_SOL_IRT; +- TxCb->RetryCtl.Mrc = (RetryCtl->Mrc != 0) ? RetryCtl->Mrc : DHCP6_SOL_MRC; +- TxCb->RetryCtl.Mrt = (RetryCtl->Mrt != 0) ? RetryCtl->Mrt : DHCP6_SOL_MRT; +- TxCb->RetryCtl.Mrd = (RetryCtl->Mrd != 0) ? RetryCtl->Mrd : DHCP6_SOL_MRD; +- } ++ case Dhcp6MsgSolicit: ++ // ++ // Calculate the retransmission threshold value for solicit packet. ++ // Use the default value by rfc-3315 if user doesn't configure. ++ // ++ if (RetryCtl == NULL) { ++ TxCb->RetryCtl.Irt = DHCP6_SOL_IRT; ++ TxCb->RetryCtl.Mrc = DHCP6_SOL_MRC; ++ TxCb->RetryCtl.Mrt = DHCP6_SOL_MRT; ++ TxCb->RetryCtl.Mrd = DHCP6_SOL_MRD; ++ } else { ++ TxCb->RetryCtl.Irt = (RetryCtl->Irt != 0) ? RetryCtl->Irt : DHCP6_SOL_IRT; ++ TxCb->RetryCtl.Mrc = (RetryCtl->Mrc != 0) ? RetryCtl->Mrc : DHCP6_SOL_MRC; ++ TxCb->RetryCtl.Mrt = (RetryCtl->Mrt != 0) ? RetryCtl->Mrt : DHCP6_SOL_MRT; ++ TxCb->RetryCtl.Mrd = (RetryCtl->Mrd != 0) ? RetryCtl->Mrd : DHCP6_SOL_MRD; ++ } ++ ++ TxCb->RetryExp = Dhcp6CalculateExpireTime ( ++ TxCb->RetryCtl.Irt, ++ TRUE, ++ FALSE ++ ); ++ break; + +- TxCb->RetryExp = Dhcp6CalculateExpireTime ( ++ case Dhcp6MsgRequest: ++ // ++ // Calculate the retransmission threshold value for request packet. ++ // ++ TxCb->RetryCtl.Irt = DHCP6_REQ_IRT; ++ TxCb->RetryCtl.Mrc = DHCP6_REQ_MRC; ++ TxCb->RetryCtl.Mrt = DHCP6_REQ_MRT; ++ TxCb->RetryCtl.Mrd = DHCP6_REQ_MRD; ++ TxCb->RetryExp = Dhcp6CalculateExpireTime ( + TxCb->RetryCtl.Irt, + TRUE, +- FALSE ++ TRUE + ); +- break; +- +- case Dhcp6MsgRequest: +- // +- // Calculate the retransmission threshold value for request packet. +- // +- TxCb->RetryCtl.Irt = DHCP6_REQ_IRT; +- TxCb->RetryCtl.Mrc = DHCP6_REQ_MRC; +- TxCb->RetryCtl.Mrt = DHCP6_REQ_MRT; +- TxCb->RetryCtl.Mrd = DHCP6_REQ_MRD; +- TxCb->RetryExp = Dhcp6CalculateExpireTime ( +- TxCb->RetryCtl.Irt, +- TRUE, +- TRUE +- ); +- break; +- +- case Dhcp6MsgConfirm: +- // +- // Calculate the retransmission threshold value for confirm packet. +- // +- TxCb->RetryCtl.Irt = DHCP6_CNF_IRT; +- TxCb->RetryCtl.Mrc = DHCP6_CNF_MRC; +- TxCb->RetryCtl.Mrt = DHCP6_CNF_MRT; +- TxCb->RetryCtl.Mrd = DHCP6_CNF_MRD; +- TxCb->RetryExp = Dhcp6CalculateExpireTime ( +- TxCb->RetryCtl.Irt, +- TRUE, +- TRUE +- ); +- break; +- +- case Dhcp6MsgRenew: +- // +- // Calculate the retransmission threshold value for renew packet. +- // +- TxCb->RetryCtl.Irt = DHCP6_REB_IRT; +- TxCb->RetryCtl.Mrc = DHCP6_REB_MRC; +- TxCb->RetryCtl.Mrt = DHCP6_REB_MRT; +- TxCb->RetryCtl.Mrd = IaCb->T2 - IaCb->T1; +- TxCb->RetryExp = Dhcp6CalculateExpireTime ( +- TxCb->RetryCtl.Irt, +- TRUE, +- TRUE +- ); +- break; ++ break; + +- case Dhcp6MsgRebind: +- // +- // Calculate the retransmission threshold value for rebind packet. +- // +- TxCb->RetryCtl.Irt = DHCP6_REN_IRT; +- TxCb->RetryCtl.Mrc = DHCP6_REN_MRC; +- TxCb->RetryCtl.Mrt = DHCP6_REN_MRT; +- TxCb->RetryCtl.Mrd = IaCb->AllExpireTime - IaCb->T2; +- TxCb->RetryExp = Dhcp6CalculateExpireTime ( +- TxCb->RetryCtl.Irt, +- TRUE, +- TRUE +- ); +- break; ++ case Dhcp6MsgConfirm: ++ // ++ // Calculate the retransmission threshold value for confirm packet. ++ // ++ TxCb->RetryCtl.Irt = DHCP6_CNF_IRT; ++ TxCb->RetryCtl.Mrc = DHCP6_CNF_MRC; ++ TxCb->RetryCtl.Mrt = DHCP6_CNF_MRT; ++ TxCb->RetryCtl.Mrd = DHCP6_CNF_MRD; ++ TxCb->RetryExp = Dhcp6CalculateExpireTime ( ++ TxCb->RetryCtl.Irt, ++ TRUE, ++ TRUE ++ ); ++ break; + +- case Dhcp6MsgDecline: +- // +- // Calculate the retransmission threshold value for decline packet. +- // +- TxCb->RetryCtl.Irt = DHCP6_DEC_IRT; +- TxCb->RetryCtl.Mrc = DHCP6_DEC_MRC; +- TxCb->RetryCtl.Mrt = DHCP6_DEC_MRT; +- TxCb->RetryCtl.Mrd = DHCP6_DEC_MRD; +- TxCb->RetryExp = Dhcp6CalculateExpireTime ( +- TxCb->RetryCtl.Irt, +- TRUE, +- TRUE +- ); +- break; ++ case Dhcp6MsgRenew: ++ // ++ // Calculate the retransmission threshold value for renew packet. ++ // ++ TxCb->RetryCtl.Irt = DHCP6_REB_IRT; ++ TxCb->RetryCtl.Mrc = DHCP6_REB_MRC; ++ TxCb->RetryCtl.Mrt = DHCP6_REB_MRT; ++ TxCb->RetryCtl.Mrd = IaCb->T2 - IaCb->T1; ++ TxCb->RetryExp = Dhcp6CalculateExpireTime ( ++ TxCb->RetryCtl.Irt, ++ TRUE, ++ TRUE ++ ); ++ break; + +- case Dhcp6MsgRelease: +- // +- // Calculate the retransmission threshold value for release packet. +- // +- TxCb->RetryCtl.Irt = DHCP6_REL_IRT; +- TxCb->RetryCtl.Mrc = DHCP6_REL_MRC; +- TxCb->RetryCtl.Mrt = DHCP6_REL_MRT; +- TxCb->RetryCtl.Mrd = DHCP6_REL_MRD; +- TxCb->RetryExp = Dhcp6CalculateExpireTime ( +- TxCb->RetryCtl.Irt, +- TRUE, +- TRUE +- ); +- break; ++ case Dhcp6MsgRebind: ++ // ++ // Calculate the retransmission threshold value for rebind packet. ++ // ++ TxCb->RetryCtl.Irt = DHCP6_REN_IRT; ++ TxCb->RetryCtl.Mrc = DHCP6_REN_MRC; ++ TxCb->RetryCtl.Mrt = DHCP6_REN_MRT; ++ TxCb->RetryCtl.Mrd = IaCb->AllExpireTime - IaCb->T2; ++ TxCb->RetryExp = Dhcp6CalculateExpireTime ( ++ TxCb->RetryCtl.Irt, ++ TRUE, ++ TRUE ++ ); ++ break; + +- case Dhcp6MsgInfoRequest: +- // +- // Calculate the retransmission threshold value for info-request packet. +- // Use the default value by rfc-3315 if user doesn't configure. +- // +- if (RetryCtl == NULL) { +- TxCb->RetryCtl.Irt = DHCP6_INF_IRT; +- TxCb->RetryCtl.Mrc = DHCP6_INF_MRC; +- TxCb->RetryCtl.Mrt = DHCP6_INF_MRT; +- TxCb->RetryCtl.Mrd = DHCP6_INF_MRD; +- } else { +- TxCb->RetryCtl.Irt = (RetryCtl->Irt != 0) ? RetryCtl->Irt : DHCP6_INF_IRT; +- TxCb->RetryCtl.Mrc = (RetryCtl->Mrc != 0) ? RetryCtl->Mrc : DHCP6_INF_MRC; +- TxCb->RetryCtl.Mrt = (RetryCtl->Mrt != 0) ? RetryCtl->Mrt : DHCP6_INF_MRT; +- TxCb->RetryCtl.Mrd = (RetryCtl->Mrd != 0) ? RetryCtl->Mrd : DHCP6_INF_MRD; +- } ++ case Dhcp6MsgDecline: ++ // ++ // Calculate the retransmission threshold value for decline packet. ++ // ++ TxCb->RetryCtl.Irt = DHCP6_DEC_IRT; ++ TxCb->RetryCtl.Mrc = DHCP6_DEC_MRC; ++ TxCb->RetryCtl.Mrt = DHCP6_DEC_MRT; ++ TxCb->RetryCtl.Mrd = DHCP6_DEC_MRD; ++ TxCb->RetryExp = Dhcp6CalculateExpireTime ( ++ TxCb->RetryCtl.Irt, ++ TRUE, ++ TRUE ++ ); ++ break; + +- TxCb->RetryExp = Dhcp6CalculateExpireTime ( ++ case Dhcp6MsgRelease: ++ // ++ // Calculate the retransmission threshold value for release packet. ++ // ++ TxCb->RetryCtl.Irt = DHCP6_REL_IRT; ++ TxCb->RetryCtl.Mrc = DHCP6_REL_MRC; ++ TxCb->RetryCtl.Mrt = DHCP6_REL_MRT; ++ TxCb->RetryCtl.Mrd = DHCP6_REL_MRD; ++ TxCb->RetryExp = Dhcp6CalculateExpireTime ( + TxCb->RetryCtl.Irt, + TRUE, + TRUE + ); +- break; ++ break; + +- default: +- // +- // Unexpected message type. +- // +- FreePool(TxCb); +- return EFI_DEVICE_ERROR; ++ case Dhcp6MsgInfoRequest: ++ // ++ // Calculate the retransmission threshold value for info-request packet. ++ // Use the default value by rfc-3315 if user doesn't configure. ++ // ++ if (RetryCtl == NULL) { ++ TxCb->RetryCtl.Irt = DHCP6_INF_IRT; ++ TxCb->RetryCtl.Mrc = DHCP6_INF_MRC; ++ TxCb->RetryCtl.Mrt = DHCP6_INF_MRT; ++ TxCb->RetryCtl.Mrd = DHCP6_INF_MRD; ++ } else { ++ TxCb->RetryCtl.Irt = (RetryCtl->Irt != 0) ? RetryCtl->Irt : DHCP6_INF_IRT; ++ TxCb->RetryCtl.Mrc = (RetryCtl->Mrc != 0) ? RetryCtl->Mrc : DHCP6_INF_MRC; ++ TxCb->RetryCtl.Mrt = (RetryCtl->Mrt != 0) ? RetryCtl->Mrt : DHCP6_INF_MRT; ++ TxCb->RetryCtl.Mrd = (RetryCtl->Mrd != 0) ? RetryCtl->Mrd : DHCP6_INF_MRD; ++ } ++ ++ TxCb->RetryExp = Dhcp6CalculateExpireTime ( ++ TxCb->RetryCtl.Irt, ++ TRUE, ++ TRUE ++ ); ++ break; ++ ++ default: ++ // ++ // Unexpected message type. ++ // ++ FreePool (TxCb); ++ return EFI_DEVICE_ERROR; + } + + // +@@ -215,7 +214,6 @@ Dhcp6EnqueueRetry ( + return EFI_SUCCESS; + } + +- + /** + Dequeue the packet from retry list if reply received or timeout at last. + +@@ -230,40 +228,36 @@ Dhcp6EnqueueRetry ( + **/ + EFI_STATUS + Dhcp6DequeueRetry ( +- IN DHCP6_INSTANCE *Instance, +- IN UINT32 PacketXid, +- IN BOOLEAN NeedSignal ++ IN DHCP6_INSTANCE *Instance, ++ IN UINT32 PacketXid, ++ IN BOOLEAN NeedSignal + ) + { +- LIST_ENTRY *Entry; +- LIST_ENTRY *NextEntry; +- DHCP6_TX_CB *TxCb; +- DHCP6_INF_CB *InfCb; ++ LIST_ENTRY *Entry; ++ LIST_ENTRY *NextEntry; ++ DHCP6_TX_CB *TxCb; ++ DHCP6_INF_CB *InfCb; + + // + // Seek the retransmit node in the retransmit list by packet xid. + // + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->TxList) { +- + TxCb = NET_LIST_USER_STRUCT (Entry, DHCP6_TX_CB, Link); +- ASSERT(TxCb->TxPacket); ++ ASSERT (TxCb->TxPacket); + + if (TxCb->Xid == PacketXid) { +- + if (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest) { +- + // + // Seek the info-request node in the info-request list by packet xid. + // + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->InfList) { +- + InfCb = NET_LIST_USER_STRUCT (Entry, DHCP6_INF_CB, Link); + + if (InfCb->Xid == PacketXid) { + // + // Remove the info-request node, and signal the event if timeout. + // +- if (InfCb->TimeoutEvent != NULL && NeedSignal) { ++ if ((InfCb->TimeoutEvent != NULL) && NeedSignal) { + gBS->SignalEvent (InfCb->TimeoutEvent); + } + +@@ -272,11 +266,12 @@ Dhcp6DequeueRetry ( + } + } + } ++ + // + // Remove the retransmit node. + // + RemoveEntryList (&TxCb->Link); +- ASSERT(TxCb->TxPacket); ++ ASSERT (TxCb->TxPacket); + FreePool (TxCb->TxPacket); + FreePool (TxCb); + return EFI_SUCCESS; +@@ -286,7 +281,6 @@ Dhcp6DequeueRetry ( + return EFI_NOT_FOUND; + } + +- + /** + Clean up the specific nodes in the retry list. + +@@ -296,24 +290,22 @@ Dhcp6DequeueRetry ( + **/ + VOID + Dhcp6CleanupRetry ( +- IN DHCP6_INSTANCE *Instance, +- IN UINT32 Scope ++ IN DHCP6_INSTANCE *Instance, ++ IN UINT32 Scope + ) + { +- LIST_ENTRY *Entry; +- LIST_ENTRY *NextEntry; +- DHCP6_TX_CB *TxCb; +- DHCP6_INF_CB *InfCb; ++ LIST_ENTRY *Entry; ++ LIST_ENTRY *NextEntry; ++ DHCP6_TX_CB *TxCb; ++ DHCP6_INF_CB *InfCb; + + // + // Clean up all the stateful messages from the retransmit list. + // +- if (Scope == DHCP6_PACKET_STATEFUL || Scope == DHCP6_PACKET_ALL) { +- ++ if ((Scope == DHCP6_PACKET_STATEFUL) || (Scope == DHCP6_PACKET_ALL)) { + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->TxList) { +- + TxCb = NET_LIST_USER_STRUCT (Entry, DHCP6_TX_CB, Link); +- ASSERT(TxCb->TxPacket); ++ ASSERT (TxCb->TxPacket); + + if (TxCb->TxPacket->Dhcp6.Header.MessageType != Dhcp6MsgInfoRequest) { + RemoveEntryList (&TxCb->Link); +@@ -326,15 +318,13 @@ Dhcp6CleanupRetry ( + // + // Clean up all the stateless messages from the retransmit list. + // +- if (Scope == DHCP6_PACKET_STATELESS || Scope == DHCP6_PACKET_ALL) { +- ++ if ((Scope == DHCP6_PACKET_STATELESS) || (Scope == DHCP6_PACKET_ALL)) { + // + // Clean up all the retransmit list for stateless messages. + // + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->TxList) { +- + TxCb = NET_LIST_USER_STRUCT (Entry, DHCP6_TX_CB, Link); +- ASSERT(TxCb->TxPacket); ++ ASSERT (TxCb->TxPacket); + + if (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest) { + RemoveEntryList (&TxCb->Link); +@@ -347,12 +337,12 @@ Dhcp6CleanupRetry ( + // Clean up all the info-request messages list. + // + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->InfList) { +- + InfCb = NET_LIST_USER_STRUCT (Entry, DHCP6_INF_CB, Link); + + if (InfCb->TimeoutEvent != NULL) { + gBS->SignalEvent (InfCb->TimeoutEvent); + } ++ + RemoveEntryList (&InfCb->Link); + FreePool (InfCb); + } +@@ -371,11 +361,11 @@ Dhcp6CleanupRetry ( + **/ + BOOLEAN + Dhcp6IsValidTxCb ( +- IN DHCP6_INSTANCE *Instance, +- IN DHCP6_TX_CB *TxCb ++ IN DHCP6_INSTANCE *Instance, ++ IN DHCP6_TX_CB *TxCb + ) + { +- LIST_ENTRY *Entry; ++ LIST_ENTRY *Entry; + + NET_LIST_FOR_EACH (Entry, &Instance->TxList) { + if (TxCb == NET_LIST_USER_STRUCT (Entry, DHCP6_TX_CB, Link)) { +@@ -395,15 +385,15 @@ Dhcp6IsValidTxCb ( + **/ + VOID + Dhcp6CleanupSession ( +- IN OUT DHCP6_INSTANCE *Instance, +- IN EFI_STATUS Status ++ IN OUT DHCP6_INSTANCE *Instance, ++ IN EFI_STATUS Status + ) + { +- UINTN Index; +- EFI_DHCP6_IA *Ia; ++ UINTN Index; ++ EFI_DHCP6_IA *Ia; + +- ASSERT(Instance->Config); +- ASSERT(Instance->IaCb.Ia); ++ ASSERT (Instance->Config); ++ ASSERT (Instance->IaCb.Ia); + + // + // Clean up the retransmit list for stateful messages. +@@ -425,23 +415,23 @@ Dhcp6CleanupSession ( + // + // Reinitialize the Ia fields of the instance. + // +- Instance->UdpSts = Status; +- Instance->AdSelect = NULL; +- Instance->AdPref = 0; +- Instance->Unicast = NULL; +- Instance->IaCb.T1 = 0; +- Instance->IaCb.T2 = 0; +- Instance->IaCb.AllExpireTime = 0; +- Instance->IaCb.LeaseTime = 0; ++ Instance->UdpSts = Status; ++ Instance->AdSelect = NULL; ++ Instance->AdPref = 0; ++ Instance->Unicast = NULL; ++ Instance->IaCb.T1 = 0; ++ Instance->IaCb.T2 = 0; ++ Instance->IaCb.AllExpireTime = 0; ++ Instance->IaCb.LeaseTime = 0; + + // + // Clear start time + // +- Instance->StartTime = 0; ++ Instance->StartTime = 0; + +- Ia = Instance->IaCb.Ia; +- Ia->State = Dhcp6Init; +- Ia->ReplyPacket = NULL; ++ Ia = Instance->IaCb.Ia; ++ Ia->State = Dhcp6Init; ++ Ia->ReplyPacket = NULL; + + // + // Set the addresses as zero lifetime, and then the notify +@@ -461,7 +451,6 @@ Dhcp6CleanupSession ( + } + } + +- + /** + Callback to user when Dhcp6 transmit/receive occurs. + +@@ -477,15 +466,15 @@ Dhcp6CleanupSession ( + EFI_STATUS + EFIAPI + Dhcp6CallbackUser ( +- IN DHCP6_INSTANCE *Instance, +- IN EFI_DHCP6_EVENT Event, +- IN OUT EFI_DHCP6_PACKET **Packet ++ IN DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_EVENT Event, ++ IN OUT EFI_DHCP6_PACKET **Packet + ) + { +- EFI_STATUS Status; +- EFI_DHCP6_PACKET *NewPacket; +- EFI_DHCP6_CALLBACK Callback; +- VOID *Context; ++ EFI_STATUS Status; ++ EFI_DHCP6_PACKET *NewPacket; ++ EFI_DHCP6_CALLBACK Callback; ++ VOID *Context; + + ASSERT (Packet != NULL); + ASSERT (Instance->Config != NULL); +@@ -500,7 +489,6 @@ Dhcp6CallbackUser ( + // Callback to user with the new message if has. + // + if (Callback != NULL) { +- + Status = Callback ( + &Instance->Dhcp6, + Context, +@@ -522,7 +510,6 @@ Dhcp6CallbackUser ( + return Status; + } + +- + /** + Update Ia according to the new reply message. + +@@ -535,17 +522,17 @@ Dhcp6CallbackUser ( + **/ + EFI_STATUS + Dhcp6UpdateIaInfo ( +- IN OUT DHCP6_INSTANCE *Instance, +- IN EFI_DHCP6_PACKET *Packet ++ IN OUT DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_PACKET *Packet + ) + { +- EFI_STATUS Status; +- UINT8 *Option; +- UINT8 *IaInnerOpt; +- UINT16 IaInnerLen; +- UINT16 StsCode; +- UINT32 T1; +- UINT32 T2; ++ EFI_STATUS Status; ++ UINT8 *Option; ++ UINT8 *IaInnerOpt; ++ UINT16 IaInnerLen; ++ UINT16 StsCode; ++ UINT32 T1; ++ UINT32 T2; + + ASSERT (Instance->Config != NULL); + // +@@ -618,9 +605,10 @@ Dhcp6UpdateIaInfo ( + // and both T1 and T2 are greater than 0, the client discards the IA_NA option and processes + // the remainder of the message as though the server had not included the invalid IA_NA option. + // +- if (T1 > T2 && T2 > 0) { ++ if ((T1 > T2) && (T2 > 0)) { + return EFI_DEVICE_ERROR; + } ++ + IaInnerOpt = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option); + IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_COMBINED_IAID_T1_T2); + } else { +@@ -674,8 +662,6 @@ Dhcp6UpdateIaInfo ( + return Status; + } + +- +- + /** + Seeks the Inner Options from a DHCP6 Option + +@@ -772,9 +758,9 @@ Dhcp6SeekInnerOptionSafe ( + **/ + EFI_STATUS + Dhcp6SeekStsOption ( +- IN DHCP6_INSTANCE *Instance, +- IN EFI_DHCP6_PACKET *Packet, +- OUT UINT8 **Option ++ IN DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_PACKET *Packet, ++ OUT UINT8 **Option + ) + { + UINT8 *IaInnerOpt; +@@ -830,7 +816,7 @@ Dhcp6SeekStsOption ( + // IA option to the end of the DHCP6 option area, thus subtract the space + // up until this option + // +- OptionLen = OptionLen - (*Option - Packet->Dhcp6.Option); ++ OptionLen = OptionLen - (UINT32)(*Option - Packet->Dhcp6.Option); + + // + // Seek the inner option +@@ -867,7 +853,7 @@ Dhcp6SeekStsOption ( + // + // sizeof (option-code + option-len) = 4 + // +- *Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode); ++ *Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode); + if (*Option != NULL) { + StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE (*Option))))); + if (StsCode != Dhcp6StsSuccess) { +@@ -878,7 +864,6 @@ Dhcp6SeekStsOption ( + return EFI_SUCCESS; + } + +- + /** + Transmit Dhcp6 message by udpio. + +@@ -893,23 +878,23 @@ Dhcp6SeekStsOption ( + **/ + EFI_STATUS + Dhcp6TransmitPacket ( +- IN DHCP6_INSTANCE *Instance, +- IN EFI_DHCP6_PACKET *Packet, +- IN UINT16 *Elapsed ++ IN DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_PACKET *Packet, ++ IN UINT16 *Elapsed + ) + { +- EFI_STATUS Status; +- NET_BUF *Wrap; +- NET_FRAGMENT Frag; +- UDP_END_POINT EndPt; +- DHCP6_SERVICE *Service; ++ EFI_STATUS Status; ++ NET_BUF *Wrap; ++ NET_FRAGMENT Frag; ++ UDP_END_POINT EndPt; ++ DHCP6_SERVICE *Service; + + Service = Instance->Service; + + // + // Wrap it into a netbuf then send it. + // +- Frag.Bulk = (UINT8 *) &Packet->Dhcp6.Header; ++ Frag.Bulk = (UINT8 *)&Packet->Dhcp6.Header; + Frag.Len = Packet->Length; + + // +@@ -970,7 +955,6 @@ Dhcp6TransmitPacket ( + return EFI_SUCCESS; + } + +- + /** + Create the solicit message and send it. + +@@ -983,19 +967,19 @@ Dhcp6TransmitPacket ( + **/ + EFI_STATUS + Dhcp6SendSolicitMsg ( +- IN DHCP6_INSTANCE *Instance ++ IN DHCP6_INSTANCE *Instance + ) + { +- EFI_STATUS Status; +- EFI_DHCP6_PACKET *Packet; +- EFI_DHCP6_PACKET_OPTION *UserOpt; +- EFI_DHCP6_DUID *ClientId; +- DHCP6_SERVICE *Service; +- UINT8 *Cursor; +- UINT16 *Elapsed; +- UINT32 UserLen; +- UINTN Index; +- UINT16 Length; ++ EFI_STATUS Status; ++ EFI_DHCP6_PACKET *Packet; ++ EFI_DHCP6_PACKET_OPTION *UserOpt; ++ EFI_DHCP6_DUID *ClientId; ++ DHCP6_SERVICE *Service; ++ UINT8 *Cursor; ++ UINT16 *Elapsed; ++ UINT32 UserLen; ++ UINTN Index; ++ UINT16 Length; + + Service = Instance->Service; + ClientId = Service->ClientId; +@@ -1069,7 +1053,6 @@ Dhcp6SendSolicitMsg ( + // Append user-defined when configurate Dhcp6 service. + // + for (Index = 0; Index < Instance->Config->OptionCount; Index++) { +- + UserOpt = Instance->Config->OptionList[Index]; + Status = Dhcp6AppendOption ( + Packet, +@@ -1139,17 +1122,16 @@ ON_ERROR: + **/ + EFI_STATUS + Dhcp6InitSolicitMsg ( +- IN DHCP6_INSTANCE *Instance ++ IN DHCP6_INSTANCE *Instance + ) + { +- Instance->IaCb.T1 = 0; +- Instance->IaCb.T2 = 0; ++ Instance->IaCb.T1 = 0; ++ Instance->IaCb.T2 = 0; + Instance->IaCb.Ia->IaAddressCount = 0; + + return Dhcp6SendSolicitMsg (Instance); + } + +- + /** + Create the request message and send it. + +@@ -1163,31 +1145,31 @@ Dhcp6InitSolicitMsg ( + **/ + EFI_STATUS + Dhcp6SendRequestMsg ( +- IN DHCP6_INSTANCE *Instance ++ IN DHCP6_INSTANCE *Instance + ) + { +- EFI_STATUS Status; +- EFI_DHCP6_PACKET *Packet; +- EFI_DHCP6_PACKET_OPTION *UserOpt; +- EFI_DHCP6_DUID *ClientId; +- EFI_DHCP6_DUID *ServerId; +- DHCP6_SERVICE *Service; +- UINT8 *Option; +- UINT8 *Cursor; +- UINT16 *Elapsed; +- UINT32 UserLen; +- UINTN Index; +- UINT16 Length; +- +- ASSERT(Instance->AdSelect != NULL); +- ASSERT(Instance->Config != NULL); +- ASSERT(Instance->IaCb.Ia != NULL); +- ASSERT(Instance->Service != NULL); ++ EFI_STATUS Status; ++ EFI_DHCP6_PACKET *Packet; ++ EFI_DHCP6_PACKET_OPTION *UserOpt; ++ EFI_DHCP6_DUID *ClientId; ++ EFI_DHCP6_DUID *ServerId; ++ DHCP6_SERVICE *Service; ++ UINT8 *Option; ++ UINT8 *Cursor; ++ UINT16 *Elapsed; ++ UINT32 UserLen; ++ UINTN Index; ++ UINT16 Length; ++ ++ ASSERT (Instance->AdSelect != NULL); ++ ASSERT (Instance->Config != NULL); ++ ASSERT (Instance->IaCb.Ia != NULL); ++ ASSERT (Instance->Service != NULL); + + Service = Instance->Service; + ClientId = Service->ClientId; + +- ASSERT(ClientId != NULL); ++ ASSERT (ClientId != NULL); + + // + // Get the server Id from the selected advertisement message. +@@ -1201,7 +1183,7 @@ Dhcp6SendRequestMsg ( + return EFI_DEVICE_ERROR; + } + +- ServerId = (EFI_DHCP6_DUID *) (Option + 2); ++ ServerId = (EFI_DHCP6_DUID *)(Option + 2); + + // + // Calculate the added length of customized option list. +@@ -1279,7 +1261,6 @@ Dhcp6SendRequestMsg ( + // Append user-defined when configurate Dhcp6 service. + // + for (Index = 0; Index < Instance->Config->OptionCount; Index++) { +- + UserOpt = Instance->Config->OptionList[Index]; + Status = Dhcp6AppendOption ( + Packet, +@@ -1334,7 +1315,6 @@ ON_ERROR: + return Status; + } + +- + /** + Create the decline message and send it. + +@@ -1349,20 +1329,20 @@ ON_ERROR: + **/ + EFI_STATUS + Dhcp6SendDeclineMsg ( +- IN DHCP6_INSTANCE *Instance, +- IN EFI_DHCP6_IA *DecIa ++ IN DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_IA *DecIa + ) + { +- EFI_STATUS Status; +- EFI_DHCP6_PACKET *Packet; +- EFI_DHCP6_PACKET *LastReply; +- EFI_DHCP6_DUID *ClientId; +- EFI_DHCP6_DUID *ServerId; +- DHCP6_SERVICE *Service; +- UINT8 *Option; +- UINT8 *Cursor; +- UINT16 *Elapsed; +- UINT16 Length; ++ EFI_STATUS Status; ++ EFI_DHCP6_PACKET *Packet; ++ EFI_DHCP6_PACKET *LastReply; ++ EFI_DHCP6_DUID *ClientId; ++ EFI_DHCP6_DUID *ServerId; ++ DHCP6_SERVICE *Service; ++ UINT8 *Option; ++ UINT8 *Cursor; ++ UINT16 *Elapsed; ++ UINT16 Length; + + ASSERT (Instance->Config != NULL); + ASSERT (Instance->IaCb.Ia != NULL); +@@ -1390,7 +1370,7 @@ Dhcp6SendDeclineMsg ( + // + // EFI_DHCP6_DUID contains a length field of 2 bytes. + // +- ServerId = (EFI_DHCP6_DUID *) (Option + 2); ++ ServerId = (EFI_DHCP6_DUID *)(Option + 2); + + // + // Create the Dhcp6 packet and initialize common fields. +@@ -1495,7 +1475,6 @@ ON_ERROR: + return Status; + } + +- + /** + Create the release message and send it. + +@@ -1510,30 +1489,30 @@ ON_ERROR: + **/ + EFI_STATUS + Dhcp6SendReleaseMsg ( +- IN DHCP6_INSTANCE *Instance, +- IN EFI_DHCP6_IA *RelIa ++ IN DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_IA *RelIa + ) + { +- EFI_STATUS Status; +- EFI_DHCP6_PACKET *Packet; +- EFI_DHCP6_PACKET *LastReply; +- EFI_DHCP6_DUID *ClientId; +- EFI_DHCP6_DUID *ServerId; +- DHCP6_SERVICE *Service; +- UINT8 *Option; +- UINT8 *Cursor; +- UINT16 *Elapsed; +- UINT16 Length; +- +- ASSERT(Instance->Config); +- ASSERT(Instance->IaCb.Ia); ++ EFI_STATUS Status; ++ EFI_DHCP6_PACKET *Packet; ++ EFI_DHCP6_PACKET *LastReply; ++ EFI_DHCP6_DUID *ClientId; ++ EFI_DHCP6_DUID *ServerId; ++ DHCP6_SERVICE *Service; ++ UINT8 *Option; ++ UINT8 *Cursor; ++ UINT16 *Elapsed; ++ UINT16 Length; ++ ++ ASSERT (Instance->Config); ++ ASSERT (Instance->IaCb.Ia); + + Service = Instance->Service; + ClientId = Service->ClientId; + LastReply = Instance->IaCb.Ia->ReplyPacket; + +- ASSERT(ClientId); +- ASSERT(LastReply); ++ ASSERT (ClientId); ++ ASSERT (LastReply); + + // + // Get the server Id from the last reply message. +@@ -1547,7 +1526,7 @@ Dhcp6SendReleaseMsg ( + return EFI_DEVICE_ERROR; + } + +- ServerId = (EFI_DHCP6_DUID *) (Option + 2); ++ ServerId = (EFI_DHCP6_DUID *)(Option + 2); + + // + // Create the Dhcp6 packet and initialize common fields. +@@ -1651,7 +1630,6 @@ ON_ERROR: + return Status; + } + +- + /** + Create the renew/rebind message and send it. + +@@ -1667,33 +1645,33 @@ ON_ERROR: + **/ + EFI_STATUS + Dhcp6SendRenewRebindMsg ( +- IN DHCP6_INSTANCE *Instance, +- IN BOOLEAN RebindRequest ++ IN DHCP6_INSTANCE *Instance, ++ IN BOOLEAN RebindRequest + ) + { +- EFI_STATUS Status; +- EFI_DHCP6_PACKET *Packet; +- EFI_DHCP6_PACKET *LastReply; +- EFI_DHCP6_PACKET_OPTION *UserOpt; +- EFI_DHCP6_DUID *ClientId; +- EFI_DHCP6_DUID *ServerId; +- EFI_DHCP6_STATE State; +- EFI_DHCP6_EVENT Event; +- DHCP6_SERVICE *Service; +- UINT8 *Option; +- UINT8 *Cursor; +- UINT16 *Elapsed; +- UINT32 UserLen; +- UINTN Index; +- UINT16 Length; +- +- ASSERT(Instance->Config); +- ASSERT(Instance->IaCb.Ia); ++ EFI_STATUS Status; ++ EFI_DHCP6_PACKET *Packet; ++ EFI_DHCP6_PACKET *LastReply; ++ EFI_DHCP6_PACKET_OPTION *UserOpt; ++ EFI_DHCP6_DUID *ClientId; ++ EFI_DHCP6_DUID *ServerId; ++ EFI_DHCP6_STATE State; ++ EFI_DHCP6_EVENT Event; ++ DHCP6_SERVICE *Service; ++ UINT8 *Option; ++ UINT8 *Cursor; ++ UINT16 *Elapsed; ++ UINT32 UserLen; ++ UINTN Index; ++ UINT16 Length; + +- Service = Instance->Service; +- ClientId = Service->ClientId; ++ ASSERT (Instance->Config); ++ ASSERT (Instance->IaCb.Ia); + +- ASSERT(ClientId); ++ Service = Instance->Service; ++ ClientId = Service->ClientId; ++ ++ ASSERT (ClientId); + + // + // Calculate the added length of customized option list. +@@ -1774,7 +1752,7 @@ Dhcp6SendRenewRebindMsg ( + goto ON_ERROR; + } + +- ServerId = (EFI_DHCP6_DUID *) (Option + 2); ++ ServerId = (EFI_DHCP6_DUID *)(Option + 2); + + Status = Dhcp6AppendOption ( + Packet, +@@ -1792,7 +1770,6 @@ Dhcp6SendRenewRebindMsg ( + // Append user-defined when configurate Dhcp6 service. + // + for (Index = 0; Index < Instance->Config->OptionCount; Index++) { +- + UserOpt = Instance->Config->OptionList[Index]; + Status = Dhcp6AppendOption ( + Packet, +@@ -1811,8 +1788,8 @@ Dhcp6SendRenewRebindMsg ( + // + // Callback to user with the packet to be sent and check the user's feedback. + // +- State = (RebindRequest) ? Dhcp6Rebinding : Dhcp6Renewing; +- Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing; ++ State = (RebindRequest) ? Dhcp6Rebinding : Dhcp6Renewing; ++ Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing; + + Status = Dhcp6CallbackUser (Instance, Event, &Packet); + if (EFI_ERROR (Status)) { +@@ -1885,19 +1862,19 @@ Dhcp6StartInfoRequest ( + IN VOID *CallbackContext OPTIONAL + ) + { +- EFI_STATUS Status; +- DHCP6_INF_CB *InfCb; +- DHCP6_SERVICE *Service; +- EFI_TPL OldTpl; ++ EFI_STATUS Status; ++ DHCP6_INF_CB *InfCb; ++ DHCP6_SERVICE *Service; ++ EFI_TPL OldTpl; + +- Service = Instance->Service; ++ Service = Instance->Service; + +- OldTpl = gBS->RaiseTPL (TPL_CALLBACK); ++ OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + Instance->UdpSts = EFI_ALREADY_STARTED; + // + // Create and initialize the control block for the info-request. + // +- InfCb = AllocateZeroPool (sizeof(DHCP6_INF_CB)); ++ InfCb = AllocateZeroPool (sizeof (DHCP6_INF_CB)); + + if (InfCb == NULL) { + gBS->RestoreTPL (OldTpl); +@@ -1930,7 +1907,7 @@ Dhcp6StartInfoRequest ( + // + // Register receive callback for the stateless exchange process. + // +- Status = UdpIoRecvDatagram( ++ Status = UdpIoRecvDatagram ( + Service->UdpIo, + Dhcp6ReceivePacket, + Service, +@@ -1981,24 +1958,24 @@ Dhcp6SendInfoRequestMsg ( + IN EFI_DHCP6_RETRANSMISSION *Retransmission + ) + { +- EFI_STATUS Status; +- EFI_DHCP6_PACKET *Packet; +- EFI_DHCP6_PACKET_OPTION *UserOpt; +- EFI_DHCP6_DUID *ClientId; +- DHCP6_SERVICE *Service; +- UINT8 *Cursor; +- UINT16 *Elapsed; +- UINT32 UserLen; +- UINTN Index; +- UINT16 Length; +- +- ASSERT(OptionRequest); ++ EFI_STATUS Status; ++ EFI_DHCP6_PACKET *Packet; ++ EFI_DHCP6_PACKET_OPTION *UserOpt; ++ EFI_DHCP6_DUID *ClientId; ++ DHCP6_SERVICE *Service; ++ UINT8 *Cursor; ++ UINT16 *Elapsed; ++ UINT32 UserLen; ++ UINTN Index; ++ UINT16 Length; ++ ++ ASSERT (OptionRequest); + + Service = Instance->Service; + ClientId = Service->ClientId; + UserLen = NTOHS (OptionRequest->OpLen) + 4; + +- ASSERT(ClientId); ++ ASSERT (ClientId); + + // + // Calculate the added length of customized option list. +@@ -2021,7 +1998,7 @@ Dhcp6SendInfoRequestMsg ( + Packet->Dhcp6.Header.MessageType = Dhcp6MsgInfoRequest; + Packet->Dhcp6.Header.TransactionId = Service->Xid++; + +- InfCb->Xid = Packet->Dhcp6.Header.TransactionId; ++ InfCb->Xid = Packet->Dhcp6.Header.TransactionId; + + // + // Assembly Dhcp6 options for info-request message. +@@ -2067,7 +2044,6 @@ Dhcp6SendInfoRequestMsg ( + // Append user-defined when configurate Dhcp6 service. + // + for (Index = 0; Index < OptionCount; Index++) { +- + UserOpt = OptionList[Index]; + Status = Dhcp6AppendOption ( + Packet, +@@ -2110,7 +2086,6 @@ ON_ERROR: + return Status; + } + +- + /** + Create the Confirm message and send it. + +@@ -2124,19 +2099,19 @@ ON_ERROR: + **/ + EFI_STATUS + Dhcp6SendConfirmMsg ( +- IN DHCP6_INSTANCE *Instance ++ IN DHCP6_INSTANCE *Instance + ) + { +- UINT8 *Cursor; +- UINTN Index; +- UINT16 Length; +- UINT32 UserLen; +- EFI_STATUS Status; +- DHCP6_SERVICE *Service; +- EFI_DHCP6_DUID *ClientId; +- EFI_DHCP6_PACKET *Packet; +- EFI_DHCP6_PACKET_OPTION *UserOpt; +- UINT16 *Elapsed; ++ UINT8 *Cursor; ++ UINTN Index; ++ UINT16 Length; ++ UINT32 UserLen; ++ EFI_STATUS Status; ++ DHCP6_SERVICE *Service; ++ EFI_DHCP6_DUID *ClientId; ++ EFI_DHCP6_PACKET *Packet; ++ EFI_DHCP6_PACKET_OPTION *UserOpt; ++ UINT16 *Elapsed; + + ASSERT (Instance->Config != NULL); + ASSERT (Instance->IaCb.Ia != NULL); +@@ -2263,8 +2238,6 @@ ON_ERROR: + return Status; + } + +- +- + /** + Handle with the Dhcp6 reply message. + +@@ -2279,13 +2252,13 @@ ON_ERROR: + **/ + EFI_STATUS + Dhcp6HandleReplyMsg ( +- IN DHCP6_INSTANCE *Instance, +- IN EFI_DHCP6_PACKET *Packet ++ IN DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_PACKET *Packet + ) + { +- EFI_STATUS Status; +- UINT8 *Option; +- UINT16 StsCode; ++ EFI_STATUS Status; ++ UINT8 *Option; ++ UINT16 StsCode; + + ASSERT (Instance->Config != NULL); + ASSERT (Instance->IaCb.Ia != NULL); +@@ -2310,7 +2283,7 @@ Dhcp6HandleReplyMsg ( + Dhcp6OptRapidCommit + ); + +- if ((Option != NULL && !Instance->Config->RapidCommit) || (Option == NULL && Instance->Config->RapidCommit)) { ++ if (((Option != NULL) && !Instance->Config->RapidCommit) || ((Option == NULL) && Instance->Config->RapidCommit)) { + return EFI_DEVICE_ERROR; + } + +@@ -2318,11 +2291,11 @@ Dhcp6HandleReplyMsg ( + // As to a valid reply packet in response to a request/renew/rebind packet, + // ignore the packet if not contains the Ia option + // +- if (Instance->IaCb.Ia->State == Dhcp6Requesting || +- Instance->IaCb.Ia->State == Dhcp6Renewing || +- Instance->IaCb.Ia->State == Dhcp6Rebinding +- ) { +- ++ if ((Instance->IaCb.Ia->State == Dhcp6Requesting) || ++ (Instance->IaCb.Ia->State == Dhcp6Renewing) || ++ (Instance->IaCb.Ia->State == Dhcp6Rebinding) ++ ) ++ { + Option = Dhcp6SeekIaOption ( + Packet->Dhcp6.Option, + Packet->Length, +@@ -2347,10 +2320,9 @@ Dhcp6HandleReplyMsg ( + // the client considers the decline/release event completed regardless of the + // status code. + // +- if (Instance->IaCb.Ia->State == Dhcp6Declining || Instance->IaCb.Ia->State == Dhcp6Releasing) { +- ++ if ((Instance->IaCb.Ia->State == Dhcp6Declining) || (Instance->IaCb.Ia->State == Dhcp6Releasing)) { + if (Instance->IaCb.Ia->IaAddressCount != 0) { +- Instance->IaCb.Ia->State = Dhcp6Bound; ++ Instance->IaCb.Ia->State = Dhcp6Bound; + } else { + ASSERT (Instance->IaCb.Ia->ReplyPacket); + FreePool (Instance->IaCb.Ia->ReplyPacket); +@@ -2373,7 +2345,7 @@ Dhcp6HandleReplyMsg ( + // + // Reset start time for next exchange. + // +- Instance->StartTime = 0; ++ Instance->StartTime = 0; + + Status = EFI_SUCCESS; + goto ON_EXIT; +@@ -2400,7 +2372,7 @@ Dhcp6HandleReplyMsg ( + // + // Reset start time for next exchange. + // +- Instance->StartTime = 0; ++ Instance->StartTime = 0; + + // + // Set bound state and store the reply packet. +@@ -2423,7 +2395,7 @@ Dhcp6HandleReplyMsg ( + // + // For sync, set the success flag out of polling in start/renewrebind. + // +- Instance->UdpSts = EFI_SUCCESS; ++ Instance->UdpSts = EFI_SUCCESS; + + // + // Maybe this is a new round DHCP process due to some reason, such as NotOnLink +@@ -2449,70 +2421,72 @@ Dhcp6HandleReplyMsg ( + } + + goto ON_EXIT; +- + } else if (Option != NULL) { + // + // Any error status code option is found. + // + StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE (Option))))); + switch (StsCode) { +- case Dhcp6StsUnspecFail: +- // +- // It indicates the server is unable to process the message due to an +- // unspecified failure condition, so just retry if possible. +- // +- break; +- +- case Dhcp6StsUseMulticast: +- // +- // It indicates the server receives a message via unicast from a client +- // to which the server has not sent a unicast option, so retry it by +- // multi-cast address. +- // +- if (Instance->Unicast != NULL) { +- FreePool (Instance->Unicast); +- Instance->Unicast = NULL; +- } +- break; +- +- case Dhcp6StsNotOnLink: +- if (Instance->IaCb.Ia->State == Dhcp6Confirming) { ++ case Dhcp6StsUnspecFail: + // +- // Before initiate new round DHCP, cache the current IA. ++ // It indicates the server is unable to process the message due to an ++ // unspecified failure condition, so just retry if possible. + // +- Status = Dhcp6CacheIa (Instance); +- if (EFI_ERROR (Status)) { +- return Status; +- } ++ break; + ++ case Dhcp6StsUseMulticast: + // +- // Restart S.A.R.R process to acquire new address. ++ // It indicates the server receives a message via unicast from a client ++ // to which the server has not sent a unicast option, so retry it by ++ // multi-cast address. + // +- Status = Dhcp6InitSolicitMsg (Instance); +- if (EFI_ERROR (Status)) { +- return Status; ++ if (Instance->Unicast != NULL) { ++ FreePool (Instance->Unicast); ++ Instance->Unicast = NULL; + } +- } +- break; + +- case Dhcp6StsNoBinding: +- if (Instance->IaCb.Ia->State == Dhcp6Renewing || Instance->IaCb.Ia->State == Dhcp6Rebinding) { +- // +- // Refer to RFC3315 Chapter 18.1.8, for each IA in the original Renew or Rebind message, the client +- // sends a Request message if the IA contained a Status Code option with the NoBinding status. +- // +- Status = Dhcp6SendRequestMsg(Instance); +- if (EFI_ERROR (Status)) { +- return Status; ++ break; ++ ++ case Dhcp6StsNotOnLink: ++ if (Instance->IaCb.Ia->State == Dhcp6Confirming) { ++ // ++ // Before initiate new round DHCP, cache the current IA. ++ // ++ Status = Dhcp6CacheIa (Instance); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } ++ ++ // ++ // Restart S.A.R.R process to acquire new address. ++ // ++ Status = Dhcp6InitSolicitMsg (Instance); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } + } +- } +- break; + +- default: +- // +- // The other status code, just restart solicitation. +- // +- break; ++ break; ++ ++ case Dhcp6StsNoBinding: ++ if ((Instance->IaCb.Ia->State == Dhcp6Renewing) || (Instance->IaCb.Ia->State == Dhcp6Rebinding)) { ++ // ++ // Refer to RFC3315 Chapter 18.1.8, for each IA in the original Renew or Rebind message, the client ++ // sends a Request message if the IA contained a Status Code option with the NoBinding status. ++ // ++ Status = Dhcp6SendRequestMsg (Instance); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } ++ } ++ ++ break; ++ ++ default: ++ // ++ // The other status code, just restart solicitation. ++ // ++ break; + } + } + +@@ -2520,7 +2494,7 @@ Dhcp6HandleReplyMsg ( + + ON_EXIT: + +- if (!EFI_ERROR(Status)) { ++ if (!EFI_ERROR (Status)) { + Status = Dhcp6DequeueRetry ( + Instance, + Packet->Dhcp6.Header.TransactionId, +@@ -2531,7 +2505,6 @@ ON_EXIT: + return Status; + } + +- + /** + Select the appointed Dhcp6 advertisement message. + +@@ -2545,12 +2518,12 @@ ON_EXIT: + **/ + EFI_STATUS + Dhcp6SelectAdvertiseMsg ( +- IN DHCP6_INSTANCE *Instance, +- IN EFI_DHCP6_PACKET *AdSelect ++ IN DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_PACKET *AdSelect + ) + { +- EFI_STATUS Status; +- UINT8 *Option; ++ EFI_STATUS Status; ++ UINT8 *Option; + + ASSERT (AdSelect != NULL); + +@@ -2575,7 +2548,7 @@ Dhcp6SelectAdvertiseMsg ( + FALSE + ); + +- if (EFI_ERROR(Status)) { ++ if (EFI_ERROR (Status)) { + return Status; + } + +@@ -2583,15 +2556,14 @@ Dhcp6SelectAdvertiseMsg ( + // Check whether there is server unicast option in the selected advertise + // packet, and update it. + // +- Option = Dhcp6SeekOption( ++ Option = Dhcp6SeekOption ( + AdSelect->Dhcp6.Option, + AdSelect->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerUnicast + ); + + if (Option != NULL) { +- +- Instance->Unicast = AllocateZeroPool (sizeof(EFI_IPv6_ADDRESS)); ++ Instance->Unicast = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS)); + + if (Instance->Unicast == NULL) { + return EFI_OUT_OF_RESOURCES; +@@ -2615,7 +2587,6 @@ Dhcp6SelectAdvertiseMsg ( + return Dhcp6SendRequestMsg (Instance); + } + +- + /** + Handle with the Dhcp6 advertisement message. + +@@ -2630,16 +2601,16 @@ Dhcp6SelectAdvertiseMsg ( + **/ + EFI_STATUS + Dhcp6HandleAdvertiseMsg ( +- IN DHCP6_INSTANCE *Instance, +- IN EFI_DHCP6_PACKET *Packet ++ IN DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_PACKET *Packet + ) + { +- EFI_STATUS Status; +- UINT8 *Option; +- BOOLEAN Timeout; ++ EFI_STATUS Status; ++ UINT8 *Option; ++ BOOLEAN Timeout; + +- ASSERT(Instance->Config); +- ASSERT(Instance->IaCb.Ia); ++ ASSERT (Instance->Config); ++ ASSERT (Instance->IaCb.Ia); + + Timeout = FALSE; + +@@ -2649,14 +2620,13 @@ Dhcp6HandleAdvertiseMsg ( + // this reply message. Or else, process the advertise messages as normal. + // See details in the section-17.1.4 of rfc-3315. + // +- Option = Dhcp6SeekOption( ++ Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, + Packet->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptRapidCommit + ); + +- if (Option != NULL && Instance->Config->RapidCommit && Packet->Dhcp6.Header.MessageType == Dhcp6MsgReply) { +- ++ if ((Option != NULL) && Instance->Config->RapidCommit && (Packet->Dhcp6.Header.MessageType == Dhcp6MsgReply)) { + return Dhcp6HandleReplyMsg (Instance, Packet); + } + +@@ -2704,12 +2674,11 @@ Dhcp6HandleAdvertiseMsg ( + CopyMem (Instance->AdSelect, Packet, Packet->Size); + + Instance->AdPref = 0xff; +- + } else if (Status == EFI_NOT_READY) { + // + // Not_ready means user wants to continue to receive more advertise packets. + // +- if (Instance->AdPref == 0xff && Instance->AdSelect == NULL) { ++ if ((Instance->AdPref == 0xff) && (Instance->AdSelect == NULL)) { + // + // It's a tricky point. The timer routine set adpref as 0xff if the first + // rt timeout and no advertisement received, which means any advertisement +@@ -2722,13 +2691,13 @@ Dhcp6HandleAdvertiseMsg ( + // Check whether the current packet has a 255 preference option or not. + // Take non-preference option as 0 value. + // +- Option = Dhcp6SeekOption( ++ Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, + Packet->Length - 4, + Dhcp6OptPreference + ); + +- if (Instance->AdSelect == NULL || (Option != NULL && *(Option + 4) > Instance->AdPref)) { ++ if ((Instance->AdSelect == NULL) || ((Option != NULL) && (*(Option + 4) > Instance->AdPref))) { + // + // No advertisements received before or preference is more than other + // advertisements received before. Then store the new packet and the +@@ -2755,7 +2724,6 @@ Dhcp6HandleAdvertiseMsg ( + // preference is less than other advertisements received before. + // Leave the packet alone. + } +- + } else { + // + // Other error status means termination. +@@ -2768,14 +2736,13 @@ Dhcp6HandleAdvertiseMsg ( + // RT has elapsed, or get a highest preference 255 advertise. + // See details in the section-17.1.2 of rfc-3315. + // +- if (Instance->AdPref == 0xff || Timeout) { ++ if ((Instance->AdPref == 0xff) || Timeout) { + Status = Dhcp6SelectAdvertiseMsg (Instance, Instance->AdSelect); + } + + return Status; + } + +- + /** + The Dhcp6 stateful exchange process routine. + +@@ -2785,14 +2752,14 @@ Dhcp6HandleAdvertiseMsg ( + **/ + VOID + Dhcp6HandleStateful ( +- IN DHCP6_INSTANCE *Instance, +- IN EFI_DHCP6_PACKET *Packet ++ IN DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_PACKET *Packet + ) + { +- EFI_STATUS Status; +- EFI_DHCP6_DUID *ClientId; +- DHCP6_SERVICE *Service; +- UINT8 *Option; ++ EFI_STATUS Status; ++ EFI_DHCP6_DUID *ClientId; ++ DHCP6_SERVICE *Service; ++ UINT8 *Option; + + Service = Instance->Service; + ClientId = Service->ClientId; +@@ -2809,14 +2776,14 @@ Dhcp6HandleStateful ( + // + // Discard the packet if not advertisement or reply packet. + // +- if (Packet->Dhcp6.Header.MessageType != Dhcp6MsgAdvertise && Packet->Dhcp6.Header.MessageType != Dhcp6MsgReply) { ++ if ((Packet->Dhcp6.Header.MessageType != Dhcp6MsgAdvertise) && (Packet->Dhcp6.Header.MessageType != Dhcp6MsgReply)) { + goto ON_CONTINUE; + } + + // + // Check whether include client Id or not. + // +- Option = Dhcp6SeekOption( ++ Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, + Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN, + Dhcp6OptClientId +@@ -2829,7 +2796,7 @@ Dhcp6HandleStateful ( + // + // Check whether include server Id or not. + // +- Option = Dhcp6SeekOption( ++ Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, + Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN, + Dhcp6OptServerId +@@ -2840,35 +2807,36 @@ Dhcp6HandleStateful ( + } + + switch (Instance->IaCb.Ia->State) { +- case Dhcp6Selecting: +- // +- // Handle the advertisement message when in the Dhcp6Selecting state. +- // Do not need check return status, if failed, just continue to the next. +- // +- Dhcp6HandleAdvertiseMsg (Instance, Packet); +- break; +- +- case Dhcp6Requesting: +- case Dhcp6Confirming: +- case Dhcp6Renewing: +- case Dhcp6Rebinding: +- case Dhcp6Releasing: +- case Dhcp6Declining: +- // +- // Handle the reply message when in the Dhcp6Requesting, Dhcp6Renewing +- // Dhcp6Rebinding, Dhcp6Releasing and Dhcp6Declining state. +- // If failed here, it should reset the current session. +- // +- Status = Dhcp6HandleReplyMsg (Instance, Packet); +- if (EFI_ERROR (Status)) { +- goto ON_EXIT; +- } +- break; +- default: +- // +- // Other state has not supported yet. +- // +- break; ++ case Dhcp6Selecting: ++ // ++ // Handle the advertisement message when in the Dhcp6Selecting state. ++ // Do not need check return status, if failed, just continue to the next. ++ // ++ Dhcp6HandleAdvertiseMsg (Instance, Packet); ++ break; ++ ++ case Dhcp6Requesting: ++ case Dhcp6Confirming: ++ case Dhcp6Renewing: ++ case Dhcp6Rebinding: ++ case Dhcp6Releasing: ++ case Dhcp6Declining: ++ // ++ // Handle the reply message when in the Dhcp6Requesting, Dhcp6Renewing ++ // Dhcp6Rebinding, Dhcp6Releasing and Dhcp6Declining state. ++ // If failed here, it should reset the current session. ++ // ++ Status = Dhcp6HandleReplyMsg (Instance, Packet); ++ if (EFI_ERROR (Status)) { ++ goto ON_EXIT; ++ } ++ ++ break; ++ default: ++ // ++ // Other state has not supported yet. ++ // ++ break; + } + + ON_CONTINUE: +@@ -2887,7 +2855,6 @@ ON_EXIT: + } + } + +- + /** + The Dhcp6 stateless exchange process routine. + +@@ -2897,15 +2864,15 @@ ON_EXIT: + **/ + VOID + Dhcp6HandleStateless ( +- IN DHCP6_INSTANCE *Instance, +- IN EFI_DHCP6_PACKET *Packet ++ IN DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_PACKET *Packet + ) + { +- EFI_STATUS Status; +- DHCP6_SERVICE *Service; +- DHCP6_INF_CB *InfCb; +- UINT8 *Option; +- BOOLEAN IsMatched; ++ EFI_STATUS Status; ++ DHCP6_SERVICE *Service; ++ DHCP6_INF_CB *InfCb; ++ UINT8 *Option; ++ BOOLEAN IsMatched; + + Service = Instance->Service; + Status = EFI_SUCCESS; +@@ -2990,7 +2957,6 @@ ON_EXIT: + } + } + +- + /** + The receive callback function for Dhcp6 exchange process. + +@@ -3003,37 +2969,37 @@ ON_EXIT: + VOID + EFIAPI + Dhcp6ReceivePacket ( +- IN NET_BUF *Udp6Wrap, +- IN UDP_END_POINT *EndPoint, +- IN EFI_STATUS IoStatus, +- IN VOID *Context ++ IN NET_BUF *Udp6Wrap, ++ IN UDP_END_POINT *EndPoint, ++ IN EFI_STATUS IoStatus, ++ IN VOID *Context + ) + { +- EFI_DHCP6_HEADER *Head; +- EFI_DHCP6_PACKET *Packet; +- DHCP6_SERVICE *Service; +- DHCP6_INSTANCE *Instance; +- DHCP6_TX_CB *TxCb; +- UINT32 Size; +- BOOLEAN IsDispatched; +- BOOLEAN IsStateless; +- LIST_ENTRY *Entry1; +- LIST_ENTRY *Next1; +- LIST_ENTRY *Entry2; +- LIST_ENTRY *Next2; +- EFI_STATUS Status; ++ EFI_DHCP6_HEADER *Head; ++ EFI_DHCP6_PACKET *Packet; ++ DHCP6_SERVICE *Service; ++ DHCP6_INSTANCE *Instance; ++ DHCP6_TX_CB *TxCb; ++ UINT32 Size; ++ BOOLEAN IsDispatched; ++ BOOLEAN IsStateless; ++ LIST_ENTRY *Entry1; ++ LIST_ENTRY *Next1; ++ LIST_ENTRY *Entry2; ++ LIST_ENTRY *Next2; ++ EFI_STATUS Status; + + ASSERT (Udp6Wrap != NULL); + ASSERT (Context != NULL); + +- Service = (DHCP6_SERVICE *) Context; ++ Service = (DHCP6_SERVICE *)Context; + Instance = NULL; + Packet = NULL; + IsDispatched = FALSE; + IsStateless = FALSE; + + if (EFI_ERROR (IoStatus)) { +- return ; ++ return; + } + + if (Udp6Wrap->TotalSize < sizeof (EFI_DHCP6_HEADER)) { +@@ -3044,7 +3010,7 @@ Dhcp6ReceivePacket ( + // Copy the net buffer received from upd6 to a Dhcp6 packet. + // + Size = sizeof (EFI_DHCP6_PACKET) + Udp6Wrap->TotalSize; +- Packet = (EFI_DHCP6_PACKET *) AllocateZeroPool (Size); ++ Packet = (EFI_DHCP6_PACKET *)AllocateZeroPool (Size); + + if (Packet == NULL) { + goto ON_CONTINUE; +@@ -3052,7 +3018,7 @@ Dhcp6ReceivePacket ( + + Packet->Size = Size; + Head = &Packet->Dhcp6.Header; +- Packet->Length = NetbufCopy (Udp6Wrap, 0, Udp6Wrap->TotalSize, (UINT8 *) Head); ++ Packet->Length = NetbufCopy (Udp6Wrap, 0, Udp6Wrap->TotalSize, (UINT8 *)Head); + + if (Packet->Length == 0) { + goto ON_CONTINUE; +@@ -3062,11 +3028,9 @@ Dhcp6ReceivePacket ( + // Dispatch packet to right instance by transaction id. + // + NET_LIST_FOR_EACH_SAFE (Entry1, Next1, &Service->Child) { +- + Instance = NET_LIST_USER_STRUCT (Entry1, DHCP6_INSTANCE, Link); + + NET_LIST_FOR_EACH_SAFE (Entry2, Next2, &Instance->TxList) { +- + TxCb = NET_LIST_USER_STRUCT (Entry2, DHCP6_TX_CB, Link); + + if (Packet->Dhcp6.Header.TransactionId == TxCb->Xid) { +@@ -3077,7 +3041,8 @@ Dhcp6ReceivePacket ( + if (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest) { + IsStateless = TRUE; + } +- IsDispatched = TRUE; ++ ++ IsDispatched = TRUE; + break; + } + } +@@ -3107,11 +3072,11 @@ ON_CONTINUE: + + if (!IsDispatched) { + Status = UdpIoRecvDatagram ( +- Service->UdpIo, +- Dhcp6ReceivePacket, +- Service, +- 0 +- ); ++ Service->UdpIo, ++ Dhcp6ReceivePacket, ++ Service, ++ 0 ++ ); + if (EFI_ERROR (Status)) { + NET_LIST_FOR_EACH_SAFE (Entry1, Next1, &Service->Child) { + Instance = NET_LIST_USER_STRUCT (Entry1, DHCP6_INSTANCE, Link); +@@ -3143,7 +3108,7 @@ ON_CONTINUE: + **/ + BOOLEAN + Dhcp6LinkMovDetect ( +- IN DHCP6_INSTANCE *Instance ++ IN DHCP6_INSTANCE *Instance + ) + { + UINT32 InterruptStatus; +@@ -3152,7 +3117,7 @@ Dhcp6LinkMovDetect ( + EFI_SIMPLE_NETWORK_PROTOCOL *Snp; + + ASSERT (Instance != NULL); +- Snp = Instance->Service->Snp; ++ Snp = Instance->Service->Snp; + MediaPresent = Instance->MediaPresent; + + // +@@ -3177,10 +3142,10 @@ Dhcp6LinkMovDetect ( + if (!MediaPresent && Instance->MediaPresent) { + return TRUE; + } ++ + return FALSE; + } + +- + /** + The timer routine of the Dhcp6 instance for each second. + +@@ -3191,28 +3156,27 @@ Dhcp6LinkMovDetect ( + VOID + EFIAPI + Dhcp6OnTimerTick ( +- IN EFI_EVENT Event, +- IN VOID *Context ++ IN EFI_EVENT Event, ++ IN VOID *Context + ) + { +- LIST_ENTRY *Entry; +- LIST_ENTRY *NextEntry; +- DHCP6_INSTANCE *Instance; +- DHCP6_TX_CB *TxCb; +- DHCP6_IA_CB *IaCb; +- UINT32 LossTime; +- EFI_STATUS Status; ++ LIST_ENTRY *Entry; ++ LIST_ENTRY *NextEntry; ++ DHCP6_INSTANCE *Instance; ++ DHCP6_TX_CB *TxCb; ++ DHCP6_IA_CB *IaCb; ++ UINT32 LossTime; ++ EFI_STATUS Status; + + ASSERT (Context != NULL); + +- Instance = (DHCP6_INSTANCE *) Context; ++ Instance = (DHCP6_INSTANCE *)Context; + + // + // 1. Loop the tx list, count live time of every tx packet to check whether + // need re-transmit or not. + // + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->TxList) { +- + TxCb = NET_LIST_USER_STRUCT (Entry, DHCP6_TX_CB, Link); + + TxCb->TickTime++; +@@ -3221,7 +3185,7 @@ Dhcp6OnTimerTick ( + // + // Handle the first rt in the transmission of solicit specially. + // +- if ((TxCb->RetryCnt == 0 || TxCb->SolicitRetry) && TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgSolicit) { ++ if (((TxCb->RetryCnt == 0) || TxCb->SolicitRetry) && (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgSolicit)) { + if (Instance->AdSelect == NULL) { + // + // Set adpref as 0xff here to indicate select any advertisement +@@ -3238,9 +3202,11 @@ Dhcp6OnTimerTick ( + } else if (EFI_ERROR (Status)) { + TxCb->RetryCnt++; + } ++ + return; + } + } ++ + // + // Increase the retry count for the packet and add up the total loss time. + // +@@ -3250,7 +3216,7 @@ Dhcp6OnTimerTick ( + // + // Check whether overflow the max retry count limit for this packet + // +- if (TxCb->RetryCtl.Mrc != 0 && TxCb->RetryCtl.Mrc < TxCb->RetryCnt) { ++ if ((TxCb->RetryCtl.Mrc != 0) && (TxCb->RetryCtl.Mrc < TxCb->RetryCnt)) { + Status = EFI_NO_RESPONSE; + goto ON_CLOSE; + } +@@ -3258,7 +3224,7 @@ Dhcp6OnTimerTick ( + // + // Check whether overflow the max retry duration for this packet + // +- if (TxCb->RetryCtl.Mrd != 0 && TxCb->RetryCtl.Mrd <= TxCb->RetryLos) { ++ if ((TxCb->RetryCtl.Mrd != 0) && (TxCb->RetryCtl.Mrd <= TxCb->RetryLos)) { + Status = EFI_NO_RESPONSE; + goto ON_CLOSE; + } +@@ -3275,7 +3241,7 @@ Dhcp6OnTimerTick ( + TRUE + ); + +- if (TxCb->RetryCtl.Mrt != 0 && TxCb->RetryCtl.Mrt < TxCb->RetryExp) { ++ if ((TxCb->RetryCtl.Mrt != 0) && (TxCb->RetryCtl.Mrt < TxCb->RetryExp)) { + TxCb->RetryExp = Dhcp6CalculateExpireTime ( + TxCb->RetryCtl.Mrt, + TRUE, +@@ -3288,7 +3254,7 @@ Dhcp6OnTimerTick ( + // duration time. + // + LossTime = TxCb->RetryLos + TxCb->RetryExp; +- if (TxCb->RetryCtl.Mrd != 0 && TxCb->RetryCtl.Mrd < LossTime) { ++ if ((TxCb->RetryCtl.Mrd != 0) && (TxCb->RetryCtl.Mrd < LossTime)) { + TxCb->RetryExp = TxCb->RetryCtl.Mrd - TxCb->RetryLos; + } + +@@ -3314,22 +3280,19 @@ Dhcp6OnTimerTick ( + // + IaCb = &Instance->IaCb; + +- if (Instance->Config == NULL || IaCb->Ia == NULL) { ++ if ((Instance->Config == NULL) || (IaCb->Ia == NULL)) { + return; + } + +- if (IaCb->Ia->State == Dhcp6Bound || IaCb->Ia->State == Dhcp6Renewing || IaCb->Ia->State == Dhcp6Rebinding) { +- ++ if ((IaCb->Ia->State == Dhcp6Bound) || (IaCb->Ia->State == Dhcp6Renewing) || (IaCb->Ia->State == Dhcp6Rebinding)) { + IaCb->LeaseTime++; + +- if (IaCb->LeaseTime > IaCb->T2 && IaCb->Ia->State == Dhcp6Bound) { ++ if ((IaCb->LeaseTime > IaCb->T2) && (IaCb->Ia->State == Dhcp6Bound)) { + // + // Exceed t2, send rebind packet to extend the Ia lease. + // + Dhcp6SendRenewRebindMsg (Instance, TRUE); +- +- } else if (IaCb->LeaseTime > IaCb->T1 && IaCb->Ia->State == Dhcp6Bound) { +- ++ } else if ((IaCb->LeaseTime > IaCb->T1) && (IaCb->Ia->State == Dhcp6Bound)) { + // + // Exceed t1, send renew packet to extend the Ia lease. + // +@@ -3347,28 +3310,32 @@ Dhcp6OnTimerTick ( + + return; + +- ON_CLOSE: ++ON_CLOSE: + + if (Dhcp6IsValidTxCb (Instance, TxCb) && +- TxCb->TxPacket != NULL && +- (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest || +- TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgRenew || +- TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgConfirm) +- ) { ++ (TxCb->TxPacket != NULL) && ++ ((TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest) || ++ (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgRenew) || ++ (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgConfirm)) ++ ) ++ { + // + // The failure of renew/Confirm will still switch to the bound state. + // + if ((TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgRenew) || +- (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgConfirm)) { ++ (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgConfirm)) ++ { + ASSERT (Instance->IaCb.Ia); + Instance->IaCb.Ia->State = Dhcp6Bound; + } ++ + // + // The failure of info-request will return no response. + // + if (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest) { + Instance->UdpSts = EFI_NO_RESPONSE; + } ++ + Dhcp6DequeueRetry ( + Instance, + TxCb->Xid, +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Apply-uncrustify-changes.patch b/edk2-NetworkPkg-Apply-uncrustify-changes.patch new file mode 100644 index 0000000..2bf3ddf --- /dev/null +++ b/edk2-NetworkPkg-Apply-uncrustify-changes.patch @@ -0,0 +1,1937 @@ +From daa72dcc870f9488f2afccdaa2341f24b1269abc Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 15:22:22 -0500 +Subject: [PATCH 06/15] NetworkPkg: Apply uncrustify changes + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [6/15] 823604dd0cad46a8ae5796cde6d1683aa23f1be5 + +JIRA: https://issues.redhat.com/browse/RHEL-21850 +CVE: CVE-2022-45234 +Upstream: Merged +Conflicts: This patch is too intrusive to apply at once in its entirety, + but we can apply a subset touching only the file being + targeted in the next commit in this series. + This way, that commit applies cleanly. + +commit d1050b9dff1cace252aff86630bfdb59dff5f507 +Author: Michael Kubacki +Date: Sun Dec 5 14:54:07 2021 -0800 + + NetworkPkg: Apply uncrustify changes + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 + + Apply uncrustify changes to .c/.h files in the NetworkPkg package + + Cc: Andrew Fish + Cc: Leif Lindholm + Cc: Michael D Kinney + Signed-off-by: Michael Kubacki + Reviewed-by: Maciej Rabeda + +Signed-off-by: Jon Maloy +--- + NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 973 ++++++++++++++------------- + 1 file changed, 498 insertions(+), 475 deletions(-) + +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +index 8d71143b79..425e0cf806 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +@@ -15,7 +15,9 @@ + // + // ALL_DHCP_Relay_Agents_and_Servers address: FF02::1:2 + // +-EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = {{0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2}}; ++EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = { ++ { 0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2 } ++}; + + /** + Parse out a DHCPv6 option by OptTag, and find the position in buffer. +@@ -30,35 +32,32 @@ EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = {{0xFF, 2, 0, 0, 0, 0, 0, 0, + **/ + EFI_DHCP6_PACKET_OPTION * + PxeBcParseDhcp6Options ( +- IN UINT8 *Buffer, +- IN UINT32 Length, +- IN UINT16 OptTag ++ IN UINT8 *Buffer, ++ IN UINT32 Length, ++ IN UINT16 OptTag + ) + { +- EFI_DHCP6_PACKET_OPTION *Option; +- UINT32 Offset; ++ EFI_DHCP6_PACKET_OPTION *Option; ++ UINT32 Offset; + +- Option = (EFI_DHCP6_PACKET_OPTION *) Buffer; +- Offset = 0; ++ Option = (EFI_DHCP6_PACKET_OPTION *)Buffer; ++ Offset = 0; + + // + // OpLen and OpCode here are both stored in network order. + // + while (Offset < Length) { +- + if (NTOHS (Option->OpCode) == OptTag) { +- + return Option; + } + +- Offset += (NTOHS(Option->OpLen) + 4); +- Option = (EFI_DHCP6_PACKET_OPTION *) (Buffer + Offset); ++ Offset += (NTOHS (Option->OpLen) + 4); ++ Option = (EFI_DHCP6_PACKET_OPTION *)(Buffer + Offset); + } + + return NULL; + } + +- + /** + Build the options buffer for the DHCPv6 request packet. + +@@ -71,70 +70,70 @@ PxeBcParseDhcp6Options ( + **/ + UINT32 + PxeBcBuildDhcp6Options ( +- IN PXEBC_PRIVATE_DATA *Private, +- OUT EFI_DHCP6_PACKET_OPTION **OptList, +- IN UINT8 *Buffer ++ IN PXEBC_PRIVATE_DATA *Private, ++ OUT EFI_DHCP6_PACKET_OPTION **OptList, ++ IN UINT8 *Buffer + ) + { +- PXEBC_DHCP6_OPTION_ENTRY OptEnt; +- UINT32 Index; +- UINT16 Value; ++ PXEBC_DHCP6_OPTION_ENTRY OptEnt; ++ UINT32 Index; ++ UINT16 Value; + +- Index = 0; +- OptList[0] = (EFI_DHCP6_PACKET_OPTION *) Buffer; ++ Index = 0; ++ OptList[0] = (EFI_DHCP6_PACKET_OPTION *)Buffer; + + // + // Append client option request option + // +- OptList[Index]->OpCode = HTONS (DHCP6_OPT_ORO); +- OptList[Index]->OpLen = HTONS (8); +- OptEnt.Oro = (PXEBC_DHCP6_OPTION_ORO *) OptList[Index]->Data; +- OptEnt.Oro->OpCode[0] = HTONS(DHCP6_OPT_BOOT_FILE_URL); +- OptEnt.Oro->OpCode[1] = HTONS(DHCP6_OPT_BOOT_FILE_PARAM); +- OptEnt.Oro->OpCode[2] = HTONS(DHCP6_OPT_DNS_SERVERS); +- OptEnt.Oro->OpCode[3] = HTONS(DHCP6_OPT_VENDOR_CLASS); ++ OptList[Index]->OpCode = HTONS (DHCP6_OPT_ORO); ++ OptList[Index]->OpLen = HTONS (8); ++ OptEnt.Oro = (PXEBC_DHCP6_OPTION_ORO *)OptList[Index]->Data; ++ OptEnt.Oro->OpCode[0] = HTONS (DHCP6_OPT_BOOT_FILE_URL); ++ OptEnt.Oro->OpCode[1] = HTONS (DHCP6_OPT_BOOT_FILE_PARAM); ++ OptEnt.Oro->OpCode[2] = HTONS (DHCP6_OPT_DNS_SERVERS); ++ OptEnt.Oro->OpCode[3] = HTONS (DHCP6_OPT_VENDOR_CLASS); + Index++; +- OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); ++ OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); + + // + // Append client network device interface option + // +- OptList[Index]->OpCode = HTONS (DHCP6_OPT_UNDI); +- OptList[Index]->OpLen = HTONS ((UINT16)3); +- OptEnt.Undi = (PXEBC_DHCP6_OPTION_UNDI *) OptList[Index]->Data; ++ OptList[Index]->OpCode = HTONS (DHCP6_OPT_UNDI); ++ OptList[Index]->OpLen = HTONS ((UINT16)3); ++ OptEnt.Undi = (PXEBC_DHCP6_OPTION_UNDI *)OptList[Index]->Data; + + if (Private->Nii != NULL) { +- OptEnt.Undi->Type = Private->Nii->Type; +- OptEnt.Undi->MajorVer = Private->Nii->MajorVer; +- OptEnt.Undi->MinorVer = Private->Nii->MinorVer; ++ OptEnt.Undi->Type = Private->Nii->Type; ++ OptEnt.Undi->MajorVer = Private->Nii->MajorVer; ++ OptEnt.Undi->MinorVer = Private->Nii->MinorVer; + } else { +- OptEnt.Undi->Type = DEFAULT_UNDI_TYPE; +- OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR; +- OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR; ++ OptEnt.Undi->Type = DEFAULT_UNDI_TYPE; ++ OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR; ++ OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR; + } + + Index++; +- OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); ++ OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); + + // + // Append client system architecture option + // +- OptList[Index]->OpCode = HTONS (DHCP6_OPT_ARCH); +- OptList[Index]->OpLen = HTONS ((UINT16) sizeof (PXEBC_DHCP6_OPTION_ARCH)); +- OptEnt.Arch = (PXEBC_DHCP6_OPTION_ARCH *) OptList[Index]->Data; +- Value = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE); ++ OptList[Index]->OpCode = HTONS (DHCP6_OPT_ARCH); ++ OptList[Index]->OpLen = HTONS ((UINT16)sizeof (PXEBC_DHCP6_OPTION_ARCH)); ++ OptEnt.Arch = (PXEBC_DHCP6_OPTION_ARCH *)OptList[Index]->Data; ++ Value = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE); + CopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16)); + Index++; +- OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); ++ OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); + + // + // Append vendor class option to store the PXE class identifier. + // + OptList[Index]->OpCode = HTONS (DHCP6_OPT_VENDOR_CLASS); +- OptList[Index]->OpLen = HTONS ((UINT16) sizeof (PXEBC_DHCP6_OPTION_VENDOR_CLASS)); +- OptEnt.VendorClass = (PXEBC_DHCP6_OPTION_VENDOR_CLASS *) OptList[Index]->Data; ++ OptList[Index]->OpLen = HTONS ((UINT16)sizeof (PXEBC_DHCP6_OPTION_VENDOR_CLASS)); ++ OptEnt.VendorClass = (PXEBC_DHCP6_OPTION_VENDOR_CLASS *)OptList[Index]->Data; + OptEnt.VendorClass->Vendor = HTONL (PXEBC_DHCP6_ENTERPRISE_NUM); +- OptEnt.VendorClass->ClassLen = HTONS ((UINT16) sizeof (PXEBC_CLASS_ID)); ++ OptEnt.VendorClass->ClassLen = HTONS ((UINT16)sizeof (PXEBC_CLASS_ID)); + CopyMem ( + &OptEnt.VendorClass->ClassId, + DEFAULT_CLASS_ID_DATA, +@@ -169,7 +168,6 @@ PxeBcBuildDhcp6Options ( + return Index; + } + +- + /** + Cache the DHCPv6 packet. + +@@ -182,8 +180,8 @@ PxeBcBuildDhcp6Options ( + **/ + EFI_STATUS + PxeBcCacheDhcp6Packet ( +- IN EFI_DHCP6_PACKET *Dst, +- IN EFI_DHCP6_PACKET *Src ++ IN EFI_DHCP6_PACKET *Dst, ++ IN EFI_DHCP6_PACKET *Src + ) + { + if (Dst->Size < Src->Length) { +@@ -211,22 +209,22 @@ PxeBcCacheDhcp6Packet ( + **/ + EFI_STATUS + PxeBcDns6 ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN CHAR16 *HostName, +- OUT EFI_IPv6_ADDRESS *IpAddress ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN CHAR16 *HostName, ++ OUT EFI_IPv6_ADDRESS *IpAddress + ) + { +- EFI_STATUS Status; +- EFI_DNS6_PROTOCOL *Dns6; +- EFI_DNS6_CONFIG_DATA Dns6ConfigData; +- EFI_DNS6_COMPLETION_TOKEN Token; +- EFI_HANDLE Dns6Handle; +- EFI_IPv6_ADDRESS *DnsServerList; +- BOOLEAN IsDone; +- +- Dns6 = NULL; +- Dns6Handle = NULL; +- DnsServerList = Private->DnsServer; ++ EFI_STATUS Status; ++ EFI_DNS6_PROTOCOL *Dns6; ++ EFI_DNS6_CONFIG_DATA Dns6ConfigData; ++ EFI_DNS6_COMPLETION_TOKEN Token; ++ EFI_HANDLE Dns6Handle; ++ EFI_IPv6_ADDRESS *DnsServerList; ++ BOOLEAN IsDone; ++ ++ Dns6 = NULL; ++ Dns6Handle = NULL; ++ DnsServerList = Private->DnsServer; + ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN)); + + // +@@ -245,7 +243,7 @@ PxeBcDns6 ( + Status = gBS->OpenProtocol ( + Dns6Handle, + &gEfiDns6ProtocolGuid, +- (VOID **) &Dns6, ++ (VOID **)&Dns6, + Private->Image, + Private->Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER +@@ -308,10 +306,12 @@ PxeBcDns6 ( + Status = EFI_DEVICE_ERROR; + goto Exit; + } +- if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) { ++ ++ if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } ++ + // + // We just return the first IPv6 address from DNS protocol. + // +@@ -325,10 +325,12 @@ Exit: + if (Token.Event != NULL) { + gBS->CloseEvent (Token.Event); + } ++ + if (Token.RspData.H2AData != NULL) { + if (Token.RspData.H2AData->IpList != NULL) { + FreePool (Token.RspData.H2AData->IpList); + } ++ + FreePool (Token.RspData.H2AData); + } + +@@ -375,26 +377,26 @@ Exit: + **/ + EFI_STATUS + PxeBcExtractBootFileUrl ( +- IN PXEBC_PRIVATE_DATA *Private, +- OUT UINT8 **FileName, +- IN OUT EFI_IPv6_ADDRESS *SrvAddr, +- IN CHAR8 *BootFile, +- IN UINT16 Length ++ IN PXEBC_PRIVATE_DATA *Private, ++ OUT UINT8 **FileName, ++ IN OUT EFI_IPv6_ADDRESS *SrvAddr, ++ IN CHAR8 *BootFile, ++ IN UINT16 Length + ) + { +- UINT16 PrefixLen; +- CHAR8 *BootFileNamePtr; +- CHAR8 *BootFileName; +- UINT16 BootFileNameLen; +- CHAR8 *TmpStr; +- CHAR8 TmpChar; +- CHAR8 *ServerAddressOption; +- CHAR8 *ServerAddress; +- CHAR8 *ModeStr; +- CHAR16 *HostName; +- BOOLEAN IpExpressedUrl; +- UINTN Len; +- EFI_STATUS Status; ++ UINT16 PrefixLen; ++ CHAR8 *BootFileNamePtr; ++ CHAR8 *BootFileName; ++ UINT16 BootFileNameLen; ++ CHAR8 *TmpStr; ++ CHAR8 TmpChar; ++ CHAR8 *ServerAddressOption; ++ CHAR8 *ServerAddress; ++ CHAR8 *ModeStr; ++ CHAR16 *HostName; ++ BOOLEAN IpExpressedUrl; ++ UINTN Len; ++ EFI_STATUS Status; + + IpExpressedUrl = TRUE; + // +@@ -417,17 +419,18 @@ PxeBcExtractBootFileUrl ( + // As an example where the BOOTFILE_NAME is the EFI loader and + // SERVER_ADDRESS is the ASCII encoding of an IPV6 address. + // +- PrefixLen = (UINT16) AsciiStrLen (PXEBC_DHCP6_BOOT_FILE_URL_PREFIX); ++ PrefixLen = (UINT16)AsciiStrLen (PXEBC_DHCP6_BOOT_FILE_URL_PREFIX); + +- if (Length <= PrefixLen || +- CompareMem (BootFile, PXEBC_DHCP6_BOOT_FILE_URL_PREFIX, PrefixLen) != 0) { ++ if ((Length <= PrefixLen) || ++ (CompareMem (BootFile, PXEBC_DHCP6_BOOT_FILE_URL_PREFIX, PrefixLen) != 0)) ++ { + return EFI_NOT_FOUND; + } + + BootFile = BootFile + PrefixLen; +- Length = (UINT16) (Length - PrefixLen); ++ Length = (UINT16)(Length - PrefixLen); + +- TmpStr = (CHAR8 *) AllocateZeroPool (Length + 1); ++ TmpStr = (CHAR8 *)AllocateZeroPool (Length + 1); + if (TmpStr == NULL) { + return EFI_OUT_OF_RESOURCES; + } +@@ -440,7 +443,7 @@ PxeBcExtractBootFileUrl ( + // + ServerAddressOption = TmpStr; + if (*ServerAddressOption == PXEBC_ADDR_START_DELIMITER) { +- ServerAddressOption ++; ++ ServerAddressOption++; + ServerAddress = ServerAddressOption; + while (*ServerAddress != '\0' && *ServerAddress != PXEBC_ADDR_END_DELIMITER) { + ServerAddress++; +@@ -461,10 +464,9 @@ PxeBcExtractBootFileUrl ( + FreePool (TmpStr); + return Status; + } +- + } else { + IpExpressedUrl = FALSE; +- ServerAddress = ServerAddressOption; ++ ServerAddress = ServerAddressOption; + while (*ServerAddress != '\0' && *ServerAddress != PXEBC_TFTP_URL_SEPARATOR) { + ServerAddress++; + } +@@ -473,14 +475,16 @@ PxeBcExtractBootFileUrl ( + FreePool (TmpStr); + return EFI_INVALID_PARAMETER; + } ++ + *ServerAddress = '\0'; + +- Len = AsciiStrSize (ServerAddressOption); ++ Len = AsciiStrSize (ServerAddressOption); + HostName = AllocateZeroPool (Len * sizeof (CHAR16)); + if (HostName == NULL) { + FreePool (TmpStr); + return EFI_OUT_OF_RESOURCES; + } ++ + AsciiStrToUnicodeStrS ( + ServerAddressOption, + HostName, +@@ -490,7 +494,7 @@ PxeBcExtractBootFileUrl ( + // + // Perform DNS resolution. + // +- Status = PxeBcDns6 (Private,HostName, SrvAddr); ++ Status = PxeBcDns6 (Private, HostName, SrvAddr); + if (EFI_ERROR (Status)) { + FreePool (TmpStr); + return Status; +@@ -500,23 +504,24 @@ PxeBcExtractBootFileUrl ( + // + // Get the part of BOOTFILE_NAME string. + // +- BootFileNamePtr = (CHAR8*)((UINTN)ServerAddress + 1); ++ BootFileNamePtr = (CHAR8 *)((UINTN)ServerAddress + 1); + if (IpExpressedUrl) { + if (*BootFileNamePtr != PXEBC_TFTP_URL_SEPARATOR) { + FreePool (TmpStr); + return EFI_INVALID_PARAMETER; + } ++ + ++BootFileNamePtr; + } + +- BootFileNameLen = (UINT16)(Length - (UINT16) ((UINTN)BootFileNamePtr - (UINTN)TmpStr) + 1); +- if (BootFileNameLen != 0 || FileName != NULL) { ++ BootFileNameLen = (UINT16)(Length - (UINT16)((UINTN)BootFileNamePtr - (UINTN)TmpStr) + 1); ++ if ((BootFileNameLen != 0) || (FileName != NULL)) { + // + // Remove trailing mode=octet if present and ignore. All other modes are + // invalid for netboot6, so reject them. + // + ModeStr = AsciiStrStr (BootFileNamePtr, ";mode=octet"); +- if (ModeStr != NULL && *(ModeStr + AsciiStrLen (";mode=octet")) == '\0') { ++ if ((ModeStr != NULL) && (*(ModeStr + AsciiStrLen (";mode=octet")) == '\0')) { + *ModeStr = '\0'; + } else if (AsciiStrStr (BootFileNamePtr, ";mode=") != NULL) { + FreePool (TmpStr); +@@ -526,30 +531,32 @@ PxeBcExtractBootFileUrl ( + // + // Extract boot file name from URL. + // +- BootFileName = (CHAR8 *) AllocateZeroPool (BootFileNameLen); ++ BootFileName = (CHAR8 *)AllocateZeroPool (BootFileNameLen); + if (BootFileName == NULL) { + FreePool (TmpStr); + return EFI_OUT_OF_RESOURCES; + } +- *FileName = (UINT8*) BootFileName; ++ ++ *FileName = (UINT8 *)BootFileName; + + // + // Decode percent-encoding in boot file name. + // + while (*BootFileNamePtr != '\0') { + if (*BootFileNamePtr == '%') { +- TmpChar = *(BootFileNamePtr+ 3); ++ TmpChar = *(BootFileNamePtr+ 3); + *(BootFileNamePtr+ 3) = '\0'; +- *BootFileName = (UINT8) AsciiStrHexToUintn ((CHAR8*)(BootFileNamePtr + 1)); ++ *BootFileName = (UINT8)AsciiStrHexToUintn ((CHAR8 *)(BootFileNamePtr + 1)); + BootFileName++; + *(BootFileNamePtr+ 3) = TmpChar; +- BootFileNamePtr += 3; ++ BootFileNamePtr += 3; + } else { + *BootFileName = *BootFileNamePtr; + BootFileName++; + BootFileNamePtr++; + } + } ++ + *BootFileName = '\0'; + } + +@@ -558,7 +565,6 @@ PxeBcExtractBootFileUrl ( + return EFI_SUCCESS; + } + +- + /** + Parse the Boot File Parameter option. + +@@ -571,14 +577,14 @@ PxeBcExtractBootFileUrl ( + **/ + EFI_STATUS + PxeBcExtractBootFileParam ( +- IN CHAR8 *BootFilePara, +- OUT UINT16 *BootFileSize ++ IN CHAR8 *BootFilePara, ++ OUT UINT16 *BootFileSize + ) + { +- UINT16 Length; +- UINT8 Index; +- UINT8 Digit; +- UINT32 Size; ++ UINT16 Length; ++ UINT8 Index; ++ UINT8 Digit; ++ UINT32 Size; + + CopyMem (&Length, BootFilePara, sizeof (UINT16)); + Length = NTOHS (Length); +@@ -586,7 +592,7 @@ PxeBcExtractBootFileParam ( + // + // The BootFile Size should be 1~5 byte ASCII strings + // +- if (Length < 1 || Length > 5) { ++ if ((Length < 1) || (Length > 5)) { + return EFI_NOT_FOUND; + } + +@@ -608,11 +614,10 @@ PxeBcExtractBootFileParam ( + return EFI_NOT_FOUND; + } + +- *BootFileSize = (UINT16) Size; ++ *BootFileSize = (UINT16)Size; + return EFI_SUCCESS; + } + +- + /** + Parse the cached DHCPv6 packet, including all the options. + +@@ -627,15 +632,15 @@ PxeBcParseDhcp6Packet ( + IN PXEBC_DHCP6_PACKET_CACHE *Cache6 + ) + { +- EFI_DHCP6_PACKET *Offer; +- EFI_DHCP6_PACKET_OPTION **Options; +- EFI_DHCP6_PACKET_OPTION *Option; +- PXEBC_OFFER_TYPE OfferType; +- BOOLEAN IsProxyOffer; +- BOOLEAN IsPxeOffer; +- UINT32 Offset; +- UINT32 Length; +- UINT32 EnterpriseNum; ++ EFI_DHCP6_PACKET *Offer; ++ EFI_DHCP6_PACKET_OPTION **Options; ++ EFI_DHCP6_PACKET_OPTION *Option; ++ PXEBC_OFFER_TYPE OfferType; ++ BOOLEAN IsProxyOffer; ++ BOOLEAN IsPxeOffer; ++ UINT32 Offset; ++ UINT32 Length; ++ UINT32 EnterpriseNum; + + IsProxyOffer = TRUE; + IsPxeOffer = FALSE; +@@ -644,15 +649,14 @@ PxeBcParseDhcp6Packet ( + + ZeroMem (Cache6->OptList, sizeof (Cache6->OptList)); + +- Option = (EFI_DHCP6_PACKET_OPTION *) (Offer->Dhcp6.Option); +- Offset = 0; +- Length = GET_DHCP6_OPTION_SIZE (Offer); ++ Option = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option); ++ Offset = 0; ++ Length = GET_DHCP6_OPTION_SIZE (Offer); + + // + // OpLen and OpCode here are both stored in network order, since they are from original packet. + // + while (Offset < Length) { +- + if (NTOHS (Option->OpCode) == DHCP6_OPT_IA_NA) { + Options[PXEBC_DHCP6_IDX_IA_NA] = Option; + } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_URL) { +@@ -669,7 +673,7 @@ PxeBcParseDhcp6Packet ( + } + + Offset += (NTOHS (Option->OpLen) + 4); +- Option = (EFI_DHCP6_PACKET_OPTION *) (Offer->Dhcp6.Option + Offset); ++ Option = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option + Offset); + } + + // +@@ -683,7 +687,7 @@ PxeBcParseDhcp6Packet ( + NTOHS (Option->OpLen), + DHCP6_OPT_STATUS_CODE + ); +- if ((Option != NULL && Option->Data[0] == 0) || (Option == NULL)) { ++ if (((Option != NULL) && (Option->Data[0] == 0)) || (Option == NULL)) { + IsProxyOffer = FALSE; + } + } +@@ -692,12 +696,13 @@ PxeBcParseDhcp6Packet ( + // The offer with "PXEClient" is a pxe offer. + // + Option = Options[PXEBC_DHCP6_IDX_VENDOR_CLASS]; +- EnterpriseNum = HTONL(PXEBC_DHCP6_ENTERPRISE_NUM); ++ EnterpriseNum = HTONL (PXEBC_DHCP6_ENTERPRISE_NUM); + +- if (Option != NULL && +- NTOHS(Option->OpLen) >= 13 && +- CompareMem (Option->Data, &EnterpriseNum, sizeof (UINT32)) == 0 && +- CompareMem (&Option->Data[6], DEFAULT_CLASS_ID_DATA, 9) == 0) { ++ if ((Option != NULL) && ++ (NTOHS (Option->OpLen) >= 13) && ++ (CompareMem (Option->Data, &EnterpriseNum, sizeof (UINT32)) == 0) && ++ (CompareMem (&Option->Data[6], DEFAULT_CLASS_ID_DATA, 9) == 0)) ++ { + IsPxeOffer = TRUE; + } + +@@ -721,7 +726,6 @@ PxeBcParseDhcp6Packet ( + return EFI_SUCCESS; + } + +- + /** + Cache the DHCPv6 ack packet, and parse it on demand. + +@@ -735,9 +739,9 @@ PxeBcParseDhcp6Packet ( + **/ + EFI_STATUS + PxeBcCopyDhcp6Ack ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN EFI_DHCP6_PACKET *Ack, +- IN BOOLEAN Verified ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN EFI_DHCP6_PACKET *Ack, ++ IN BOOLEAN Verified + ) + { + EFI_PXE_BASE_CODE_MODE *Mode; +@@ -762,7 +766,6 @@ PxeBcCopyDhcp6Ack ( + return EFI_SUCCESS; + } + +- + /** + Cache the DHCPv6 proxy offer packet according to the received order. + +@@ -775,12 +778,12 @@ PxeBcCopyDhcp6Ack ( + **/ + EFI_STATUS + PxeBcCopyDhcp6Proxy ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN UINT32 OfferIndex ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN UINT32 OfferIndex + ) + { +- EFI_PXE_BASE_CODE_MODE *Mode; +- EFI_DHCP6_PACKET *Offer; ++ EFI_PXE_BASE_CODE_MODE *Mode; ++ EFI_DHCP6_PACKET *Offer; + EFI_STATUS Status; + + ASSERT (OfferIndex < Private->OfferNum); +@@ -793,9 +796,10 @@ PxeBcCopyDhcp6Proxy ( + // Cache the proxy offer packet and parse it. + // + Status = PxeBcCacheDhcp6Packet (&Private->ProxyOffer.Dhcp6.Packet.Offer, Offer); +- if (EFI_ERROR(Status)) { ++ if (EFI_ERROR (Status)) { + return Status; + } ++ + PxeBcParseDhcp6Packet (&Private->ProxyOffer.Dhcp6); + + // +@@ -820,33 +824,33 @@ PxeBcCopyDhcp6Proxy ( + **/ + UINT8 * + PxeBcDhcp6SeekOption ( +- IN UINT8 *Buf, +- IN UINT32 SeekLen, +- IN UINT16 OptType ++ IN UINT8 *Buf, ++ IN UINT32 SeekLen, ++ IN UINT16 OptType + ) + { +- UINT8 *Cursor; +- UINT8 *Option; +- UINT16 DataLen; +- UINT16 OpCode; ++ UINT8 *Cursor; ++ UINT8 *Option; ++ UINT16 DataLen; ++ UINT16 OpCode; + + Option = NULL; + Cursor = Buf; + + while (Cursor < Buf + SeekLen) { +- OpCode = ReadUnaligned16 ((UINT16 *) Cursor); ++ OpCode = ReadUnaligned16 ((UINT16 *)Cursor); + if (OpCode == HTONS (OptType)) { + Option = Cursor; + break; + } +- DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2))); ++ ++ DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2))); + Cursor += (DataLen + 4); + } + + return Option; + } + +- + /** + Build and send out the request packet for the bootfile, and parse the reply. + +@@ -861,34 +865,34 @@ PxeBcDhcp6SeekOption ( + **/ + EFI_STATUS + PxeBcRequestBootService ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN UINT32 Index ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN UINT32 Index + ) + { +- EFI_PXE_BASE_CODE_UDP_PORT SrcPort; +- EFI_PXE_BASE_CODE_UDP_PORT DestPort; +- EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; +- EFI_PXE_BASE_CODE_DHCPV6_PACKET *Discover; +- UINTN DiscoverLen; +- EFI_DHCP6_PACKET *Request; +- UINTN RequestLen; +- EFI_DHCP6_PACKET *Reply; +- UINT8 *RequestOpt; +- UINT8 *DiscoverOpt; +- UINTN ReadSize; +- UINT16 OpFlags; +- UINT16 OpCode; +- UINT16 OpLen; +- EFI_STATUS Status; +- EFI_DHCP6_PACKET *IndexOffer; +- UINT8 *Option; +- +- PxeBc = &Private->PxeBc; +- Request = Private->Dhcp6Request; +- IndexOffer = &Private->OfferBuffer[Index].Dhcp6.Packet.Offer; +- SrcPort = PXEBC_BS_DISCOVER_PORT; +- DestPort = PXEBC_BS_DISCOVER_PORT; +- OpFlags = 0; ++ EFI_PXE_BASE_CODE_UDP_PORT SrcPort; ++ EFI_PXE_BASE_CODE_UDP_PORT DestPort; ++ EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; ++ EFI_PXE_BASE_CODE_DHCPV6_PACKET *Discover; ++ UINTN DiscoverLen; ++ EFI_DHCP6_PACKET *Request; ++ UINTN RequestLen; ++ EFI_DHCP6_PACKET *Reply; ++ UINT8 *RequestOpt; ++ UINT8 *DiscoverOpt; ++ UINTN ReadSize; ++ UINT16 OpFlags; ++ UINT16 OpCode; ++ UINT16 OpLen; ++ EFI_STATUS Status; ++ EFI_DHCP6_PACKET *IndexOffer; ++ UINT8 *Option; ++ ++ PxeBc = &Private->PxeBc; ++ Request = Private->Dhcp6Request; ++ IndexOffer = &Private->OfferBuffer[Index].Dhcp6.Packet.Offer; ++ SrcPort = PXEBC_BS_DISCOVER_PORT; ++ DestPort = PXEBC_BS_DISCOVER_PORT; ++ OpFlags = 0; + + if (Request == NULL) { + return EFI_DEVICE_ERROR; +@@ -925,19 +929,20 @@ PxeBcRequestBootService ( + // + // Add Server ID Option. + // +- OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) Option)->OpLen); ++ OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)Option)->OpLen); + CopyMem (DiscoverOpt, Option, OpLen + 4); + DiscoverOpt += (OpLen + 4); + DiscoverLen += (OpLen + 4); + } + + while (RequestLen < Request->Length) { +- OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpCode); +- OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpLen); +- if (OpCode != EFI_DHCP6_IA_TYPE_NA && +- OpCode != EFI_DHCP6_IA_TYPE_TA && +- OpCode != DHCP6_OPT_SERVER_ID +- ) { ++ OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode); ++ OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen); ++ if ((OpCode != EFI_DHCP6_IA_TYPE_NA) && ++ (OpCode != EFI_DHCP6_IA_TYPE_TA) && ++ (OpCode != DHCP6_OPT_SERVER_ID) ++ ) ++ { + // + // Copy all the options except IA option and Server ID + // +@@ -945,6 +950,7 @@ PxeBcRequestBootService ( + DiscoverOpt += (OpLen + 4); + DiscoverLen += (OpLen + 4); + } ++ + RequestOpt += (OpLen + 4); + RequestLen += (OpLen + 4); + } +@@ -959,7 +965,7 @@ PxeBcRequestBootService ( + ); + if (Option != NULL) { + CalcElapsedTime (Private); +- WriteUnaligned16 ((UINT16*)(Option + 4), HTONS((UINT16) Private->ElapsedTime)); ++ WriteUnaligned16 ((UINT16 *)(Option + 4), HTONS ((UINT16)Private->ElapsedTime)); + } + + Status = PxeBc->UdpWrite ( +@@ -973,7 +979,7 @@ PxeBcRequestBootService ( + NULL, + NULL, + &DiscoverLen, +- (VOID *) Discover ++ (VOID *)Discover + ); + + if (EFI_ERROR (Status)) { +@@ -984,8 +990,8 @@ PxeBcRequestBootService ( + // Cache the right PXE reply packet here, set valid flag later. + // Especially for PXE discover packet, store it into mode data here. + // +- Reply = &Private->ProxyOffer.Dhcp6.Packet.Offer; +- ReadSize = (UINTN) Reply->Size; ++ Reply = &Private->ProxyOffer.Dhcp6.Packet.Offer; ++ ReadSize = (UINTN)Reply->Size; + + // + // Start Udp6Read instance +@@ -1005,7 +1011,7 @@ PxeBcRequestBootService ( + NULL, + NULL, + &ReadSize, +- (VOID *) &Reply->Dhcp6 ++ (VOID *)&Reply->Dhcp6 + ); + // + // Stop Udp6Read instance +@@ -1019,7 +1025,7 @@ PxeBcRequestBootService ( + // + // Update length + // +- Reply->Length = (UINT32) ReadSize; ++ Reply->Length = (UINT32)ReadSize; + + return EFI_SUCCESS; + +@@ -1031,7 +1037,6 @@ ON_ERROR: + return Status; + } + +- + /** + Retry to request bootfile name by the BINL offer. + +@@ -1054,8 +1059,10 @@ PxeBcRetryDhcp6Binl ( + EFI_STATUS Status; + + ASSERT (Index < PXEBC_OFFER_MAX_NUM); +- ASSERT (Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeDhcpBinl || +- Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeProxyBinl); ++ ASSERT ( ++ Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeDhcpBinl || ++ Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeProxyBinl ++ ); + + Mode = Private->PxeBc.Mode; + Private->IsDoDiscover = FALSE; +@@ -1078,7 +1085,7 @@ PxeBcRetryDhcp6Binl ( + Private, + &Private->BootFileName, + &Private->ServerIp.v6, +- (CHAR8 *) (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->Data), ++ (CHAR8 *)(Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->Data), + NTOHS (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->OpLen) + ); + if (EFI_ERROR (Status)) { +@@ -1101,9 +1108,10 @@ PxeBcRetryDhcp6Binl ( + return Status; + } + +- if (Cache6->OfferType != PxeOfferTypeProxyPxe10 && +- Cache6->OfferType != PxeOfferTypeProxyWfm11a && +- Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL) { ++ if ((Cache6->OfferType != PxeOfferTypeProxyPxe10) && ++ (Cache6->OfferType != PxeOfferTypeProxyWfm11a) && ++ (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL)) ++ { + // + // This BINL ack doesn't have discovery option set or multicast option set + // or bootfile name specified. +@@ -1121,7 +1129,6 @@ PxeBcRetryDhcp6Binl ( + return EFI_SUCCESS; + } + +- + /** + Cache all the received DHCPv6 offers, and set OfferIndex and OfferCount. + +@@ -1133,8 +1140,8 @@ PxeBcRetryDhcp6Binl ( + **/ + EFI_STATUS + PxeBcCacheDhcp6Offer ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN EFI_DHCP6_PACKET *RcvdOffer ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN EFI_DHCP6_PACKET *RcvdOffer + ) + { + PXEBC_DHCP6_PACKET_CACHE *Cache6; +@@ -1179,8 +1186,9 @@ PxeBcCacheDhcp6Offer ( + // + Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum; + Private->OfferCount[OfferType]++; +- } else if ((OfferType == PxeOfferTypeProxyPxe10 || OfferType == PxeOfferTypeProxyWfm11a) && +- Private->OfferCount[OfferType] < 1) { ++ } else if (((OfferType == PxeOfferTypeProxyPxe10) || (OfferType == PxeOfferTypeProxyWfm11a)) && ++ (Private->OfferCount[OfferType] < 1)) ++ { + // + // Only cache the first PXE10/WFM11a offer, and discard the others. + // +@@ -1202,7 +1210,6 @@ PxeBcCacheDhcp6Offer ( + return EFI_SUCCESS; + } + +- + /** + Select an DHCPv6 offer, and record SelectIndex and SelectProxyType. + +@@ -1211,12 +1218,12 @@ PxeBcCacheDhcp6Offer ( + **/ + VOID + PxeBcSelectDhcp6Offer ( +- IN PXEBC_PRIVATE_DATA *Private ++ IN PXEBC_PRIVATE_DATA *Private + ) + { +- UINT32 Index; +- UINT32 OfferIndex; +- PXEBC_OFFER_TYPE OfferType; ++ UINT32 Index; ++ UINT32 OfferIndex; ++ PXEBC_OFFER_TYPE OfferType; + + Private->SelectIndex = 0; + +@@ -1229,43 +1236,40 @@ PxeBcSelectDhcp6Offer ( + // 1. DhcpPxe10 offer + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpPxe10][0] + 1; +- + } else if (Private->OfferCount[PxeOfferTypeDhcpWfm11a] > 0) { + // + // 2. DhcpWfm11a offer + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpWfm11a][0] + 1; +- +- } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 && +- Private->OfferCount[PxeOfferTypeProxyPxe10] > 0) { ++ } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) && ++ (Private->OfferCount[PxeOfferTypeProxyPxe10] > 0)) ++ { + // + // 3. DhcpOnly offer and ProxyPxe10 offer. + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1; + Private->SelectProxyType = PxeOfferTypeProxyPxe10; +- +- } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 && +- Private->OfferCount[PxeOfferTypeProxyWfm11a] > 0) { ++ } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) && ++ (Private->OfferCount[PxeOfferTypeProxyWfm11a] > 0)) ++ { + // + // 4. DhcpOnly offer and ProxyWfm11a offer. + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1; + Private->SelectProxyType = PxeOfferTypeProxyWfm11a; +- + } else if (Private->OfferCount[PxeOfferTypeDhcpBinl] > 0) { + // + // 5. DhcpBinl offer. + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpBinl][0] + 1; +- +- } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 && +- Private->OfferCount[PxeOfferTypeProxyBinl] > 0) { ++ } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) && ++ (Private->OfferCount[PxeOfferTypeProxyBinl] > 0)) ++ { + // + // 6. DhcpOnly offer and ProxyBinl offer. + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1; + Private->SelectProxyType = PxeOfferTypeProxyBinl; +- + } else { + // + // 7. DhcpOnly offer with bootfilename. +@@ -1283,7 +1287,6 @@ PxeBcSelectDhcp6Offer ( + // Select offer by received order. + // + for (Index = 0; Index < Private->OfferNum; Index++) { +- + OfferType = Private->OfferBuffer[Index].Dhcp6.OfferType; + + if (IS_PROXY_OFFER (OfferType)) { +@@ -1294,8 +1297,9 @@ PxeBcSelectDhcp6Offer ( + } + + if (!Private->IsProxyRecved && +- OfferType == PxeOfferTypeDhcpOnly && +- Private->OfferBuffer[Index].Dhcp6.OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL) { ++ (OfferType == PxeOfferTypeDhcpOnly) && ++ (Private->OfferBuffer[Index].Dhcp6.OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL)) ++ { + // + // Skip if DhcpOnly offer without any other proxy offers or bootfilename. + // +@@ -1308,7 +1312,6 @@ PxeBcSelectDhcp6Offer ( + } + } + +- + /** + Handle the DHCPv6 offer packet. + +@@ -1322,21 +1325,21 @@ PxeBcSelectDhcp6Offer ( + **/ + EFI_STATUS + PxeBcHandleDhcp6Offer ( +- IN PXEBC_PRIVATE_DATA *Private ++ IN PXEBC_PRIVATE_DATA *Private + ) + { +- PXEBC_DHCP6_PACKET_CACHE *Cache6; +- EFI_STATUS Status; +- PXEBC_OFFER_TYPE OfferType; +- UINT32 ProxyIndex; +- UINT32 SelectIndex; +- UINT32 Index; ++ PXEBC_DHCP6_PACKET_CACHE *Cache6; ++ EFI_STATUS Status; ++ PXEBC_OFFER_TYPE OfferType; ++ UINT32 ProxyIndex; ++ UINT32 SelectIndex; ++ UINT32 Index; + + ASSERT (Private->SelectIndex > 0); +- SelectIndex = (UINT32) (Private->SelectIndex - 1); ++ SelectIndex = (UINT32)(Private->SelectIndex - 1); + ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM); +- Cache6 = &Private->OfferBuffer[SelectIndex].Dhcp6; +- Status = EFI_SUCCESS; ++ Cache6 = &Private->OfferBuffer[SelectIndex].Dhcp6; ++ Status = EFI_SUCCESS; + + // + // First try to cache DNS server address if DHCP6 offer provides. +@@ -1346,6 +1349,7 @@ PxeBcHandleDhcp6Offer ( + if (Private->DnsServer == NULL) { + return EFI_OUT_OF_RESOURCES; + } ++ + CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS)); + } + +@@ -1357,7 +1361,6 @@ PxeBcHandleDhcp6Offer ( + Status = EFI_NO_RESPONSE; + } + } else if (Cache6->OfferType == PxeOfferTypeDhcpOnly) { +- + if (Private->IsProxyRecved) { + // + // DhcpOnly offer is selected, so need try to request bootfilename. +@@ -1375,12 +1378,12 @@ PxeBcHandleDhcp6Offer ( + // Try all the cached ProxyBinl offer one by one to request bootfilename. + // + for (Index = 0; Index < Private->OfferCount[Private->SelectProxyType]; Index++) { +- + ProxyIndex = Private->OfferIndex[Private->SelectProxyType][Index]; + if (!EFI_ERROR (PxeBcRetryDhcp6Binl (Private, ProxyIndex))) { + break; + } + } ++ + if (Index == Private->OfferCount[Private->SelectProxyType]) { + Status = EFI_NO_RESPONSE; + } +@@ -1397,7 +1400,6 @@ PxeBcHandleDhcp6Offer ( + Status = EFI_NO_RESPONSE; + + for (Index = 0; Index < Private->OfferNum; Index++) { +- + OfferType = Private->OfferBuffer[Index].Dhcp6.OfferType; + + if (!IS_PROXY_OFFER (OfferType)) { +@@ -1423,7 +1425,7 @@ PxeBcHandleDhcp6Offer ( + } + } + +- if (!EFI_ERROR (Status) && Private->SelectProxyType != PxeOfferTypeProxyBinl) { ++ if (!EFI_ERROR (Status) && (Private->SelectProxyType != PxeOfferTypeProxyBinl)) { + // + // Success to try to request by a ProxyPxe10 or ProxyWfm11a offer, copy and parse it. + // +@@ -1441,14 +1443,13 @@ PxeBcHandleDhcp6Offer ( + // + // All PXE boot information is ready by now. + // +- Status = PxeBcCopyDhcp6Ack (Private, &Private->DhcpAck.Dhcp6.Packet.Ack, TRUE); ++ Status = PxeBcCopyDhcp6Ack (Private, &Private->DhcpAck.Dhcp6.Packet.Ack, TRUE); + Private->PxeBc.Mode->DhcpDiscoverValid = TRUE; + } + + return Status; + } + +- + /** + Unregister the address by Ip6Config protocol. + +@@ -1457,7 +1458,7 @@ PxeBcHandleDhcp6Offer ( + **/ + VOID + PxeBcUnregisterIp6Address ( +- IN PXEBC_PRIVATE_DATA *Private ++ IN PXEBC_PRIVATE_DATA *Private + ) + { + if (Private->Ip6Policy != PXEBC_IP6_POLICY_MAX) { +@@ -1485,18 +1486,18 @@ PxeBcUnregisterIp6Address ( + **/ + EFI_STATUS + PxeBcCheckRouteTable ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN UINTN TimeOutInSecond, +- OUT EFI_IPv6_ADDRESS *GatewayAddr ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN UINTN TimeOutInSecond, ++ OUT EFI_IPv6_ADDRESS *GatewayAddr + ) + { +- EFI_STATUS Status; +- EFI_IP6_PROTOCOL *Ip6; +- EFI_IP6_MODE_DATA Ip6ModeData; +- UINTN Index; +- EFI_EVENT TimeOutEvt; +- UINTN RetryCount; +- BOOLEAN GatewayIsFound; ++ EFI_STATUS Status; ++ EFI_IP6_PROTOCOL *Ip6; ++ EFI_IP6_MODE_DATA Ip6ModeData; ++ UINTN Index; ++ EFI_EVENT TimeOutEvt; ++ UINTN RetryCount; ++ BOOLEAN GatewayIsFound; + + ASSERT (GatewayAddr != NULL); + ASSERT (Private != NULL); +@@ -1527,23 +1528,28 @@ PxeBcCheckRouteTable ( + if (Ip6ModeData.AddressList != NULL) { + FreePool (Ip6ModeData.AddressList); + } ++ + if (Ip6ModeData.GroupTable != NULL) { + FreePool (Ip6ModeData.GroupTable); + } ++ + if (Ip6ModeData.RouteTable != NULL) { + FreePool (Ip6ModeData.RouteTable); + } ++ + if (Ip6ModeData.NeighborCache != NULL) { + FreePool (Ip6ModeData.NeighborCache); + } ++ + if (Ip6ModeData.PrefixTable != NULL) { + FreePool (Ip6ModeData.PrefixTable); + } ++ + if (Ip6ModeData.IcmpTypeList != NULL) { + FreePool (Ip6ModeData.IcmpTypeList); + } + +- if (GatewayIsFound || RetryCount == TimeOutInSecond) { ++ if (GatewayIsFound || (RetryCount == TimeOutInSecond)) { + break; + } + +@@ -1569,6 +1575,7 @@ PxeBcCheckRouteTable ( + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } ++ + while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) { + Ip6->Poll (Ip6); + } +@@ -1600,29 +1607,29 @@ ON_EXIT: + **/ + EFI_STATUS + PxeBcRegisterIp6Address ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN EFI_IPv6_ADDRESS *Address ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN EFI_IPv6_ADDRESS *Address + ) + { +- EFI_IP6_PROTOCOL *Ip6; +- EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; +- EFI_IP6_CONFIG_POLICY Policy; +- EFI_IP6_CONFIG_MANUAL_ADDRESS CfgAddr; +- EFI_IPv6_ADDRESS GatewayAddr; +- UINTN DataSize; +- EFI_EVENT MappedEvt; +- EFI_STATUS Status; +- BOOLEAN NoGateway; +- EFI_IPv6_ADDRESS *Ip6Addr; +- UINTN Index; +- +- Status = EFI_SUCCESS; +- MappedEvt = NULL; +- Ip6Addr = NULL; +- DataSize = sizeof (EFI_IP6_CONFIG_POLICY); +- Ip6Cfg = Private->Ip6Cfg; +- Ip6 = Private->Ip6; +- NoGateway = FALSE; ++ EFI_IP6_PROTOCOL *Ip6; ++ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; ++ EFI_IP6_CONFIG_POLICY Policy; ++ EFI_IP6_CONFIG_MANUAL_ADDRESS CfgAddr; ++ EFI_IPv6_ADDRESS GatewayAddr; ++ UINTN DataSize; ++ EFI_EVENT MappedEvt; ++ EFI_STATUS Status; ++ BOOLEAN NoGateway; ++ EFI_IPv6_ADDRESS *Ip6Addr; ++ UINTN Index; ++ ++ Status = EFI_SUCCESS; ++ MappedEvt = NULL; ++ Ip6Addr = NULL; ++ DataSize = sizeof (EFI_IP6_CONFIG_POLICY); ++ Ip6Cfg = Private->Ip6Cfg; ++ Ip6 = Private->Ip6; ++ NoGateway = FALSE; + + ZeroMem (&CfgAddr, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)); + CopyMem (&CfgAddr.Address, Address, sizeof (EFI_IPv6_ADDRESS)); +@@ -1648,7 +1655,7 @@ PxeBcRegisterIp6Address ( + Status = Ip6Cfg->SetData ( + Ip6Cfg, + Ip6ConfigDataTypePolicy, +- sizeof(EFI_IP6_CONFIG_POLICY), ++ sizeof (EFI_IP6_CONFIG_POLICY), + &Policy + ); + if (EFI_ERROR (Status)) { +@@ -1674,22 +1681,22 @@ PxeBcRegisterIp6Address ( + } + + Private->IsAddressOk = FALSE; +- Status = Ip6Cfg->RegisterDataNotify ( +- Ip6Cfg, +- Ip6ConfigDataTypeManualAddress, +- MappedEvt +- ); +- if (EFI_ERROR(Status)) { ++ Status = Ip6Cfg->RegisterDataNotify ( ++ Ip6Cfg, ++ Ip6ConfigDataTypeManualAddress, ++ MappedEvt ++ ); ++ if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status = Ip6Cfg->SetData ( + Ip6Cfg, + Ip6ConfigDataTypeManualAddress, +- sizeof(EFI_IP6_CONFIG_MANUAL_ADDRESS), ++ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS), + &CfgAddr + ); +- if (EFI_ERROR(Status) && Status != EFI_NOT_READY) { ++ if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) { + goto ON_EXIT; + } else if (Status == EFI_NOT_READY) { + // +@@ -1698,17 +1705,18 @@ PxeBcRegisterIp6Address ( + while (!Private->IsAddressOk) { + Ip6->Poll (Ip6); + } ++ + // + // Check whether the IP6 address setting is successed. + // + DataSize = 0; +- Status = Ip6Cfg->GetData ( +- Ip6Cfg, +- Ip6ConfigDataTypeManualAddress, +- &DataSize, +- NULL +- ); +- if (Status != EFI_BUFFER_TOO_SMALL || DataSize == 0) { ++ Status = Ip6Cfg->GetData ( ++ Ip6Cfg, ++ Ip6ConfigDataTypeManualAddress, ++ &DataSize, ++ NULL ++ ); ++ if ((Status != EFI_BUFFER_TOO_SMALL) || (DataSize == 0)) { + Status = EFI_DEVICE_ERROR; + goto ON_EXIT; + } +@@ -1717,11 +1725,12 @@ PxeBcRegisterIp6Address ( + if (Ip6Addr == NULL) { + return EFI_OUT_OF_RESOURCES; + } ++ + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeManualAddress, + &DataSize, +- (VOID*) Ip6Addr ++ (VOID *)Ip6Addr + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; +@@ -1733,6 +1742,7 @@ PxeBcRegisterIp6Address ( + break; + } + } ++ + if (Index == DataSize / sizeof (EFI_IPv6_ADDRESS)) { + Status = EFI_ABORTED; + goto ON_EXIT; +@@ -1763,9 +1773,11 @@ ON_EXIT: + ); + gBS->CloseEvent (MappedEvt); + } ++ + if (Ip6Addr != NULL) { + FreePool (Ip6Addr); + } ++ + return Status; + } + +@@ -1780,16 +1792,16 @@ ON_EXIT: + **/ + EFI_STATUS + PxeBcSetIp6Policy ( +- IN PXEBC_PRIVATE_DATA *Private ++ IN PXEBC_PRIVATE_DATA *Private + ) + { +- EFI_IP6_CONFIG_POLICY Policy; +- EFI_STATUS Status; +- EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; +- UINTN DataSize; ++ EFI_IP6_CONFIG_POLICY Policy; ++ EFI_STATUS Status; ++ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; ++ UINTN DataSize; + +- Ip6Cfg = Private->Ip6Cfg; +- DataSize = sizeof (EFI_IP6_CONFIG_POLICY); ++ Ip6Cfg = Private->Ip6Cfg; ++ DataSize = sizeof (EFI_IP6_CONFIG_POLICY); + + // + // Get and store the current policy of IP6 driver. +@@ -1809,7 +1821,7 @@ PxeBcSetIp6Policy ( + Status = Ip6Cfg->SetData ( + Ip6Cfg, + Ip6ConfigDataTypePolicy, +- sizeof(EFI_IP6_CONFIG_POLICY), ++ sizeof (EFI_IP6_CONFIG_POLICY), + &Policy + ); + if (EFI_ERROR (Status)) { +@@ -1834,11 +1846,11 @@ PxeBcSetIp6Policy ( + **/ + EFI_STATUS + PxeBcSetIp6Address ( +- IN PXEBC_PRIVATE_DATA *Private ++ IN PXEBC_PRIVATE_DATA *Private + ) + { +- EFI_STATUS Status; +- EFI_DHCP6_PROTOCOL *Dhcp6; ++ EFI_STATUS Status; ++ EFI_DHCP6_PROTOCOL *Dhcp6; + + Dhcp6 = Private->Dhcp6; + +@@ -1885,47 +1897,48 @@ PxeBcSetIp6Address ( + EFI_STATUS + EFIAPI + PxeBcDhcp6CallBack ( +- IN EFI_DHCP6_PROTOCOL *This, +- IN VOID *Context, +- IN EFI_DHCP6_STATE CurrentState, +- IN EFI_DHCP6_EVENT Dhcp6Event, +- IN EFI_DHCP6_PACKET *Packet, +- OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL ++ IN EFI_DHCP6_PROTOCOL *This, ++ IN VOID *Context, ++ IN EFI_DHCP6_STATE CurrentState, ++ IN EFI_DHCP6_EVENT Dhcp6Event, ++ IN EFI_DHCP6_PACKET *Packet, ++ OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL + ) + { +- PXEBC_PRIVATE_DATA *Private; +- EFI_PXE_BASE_CODE_MODE *Mode; +- EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback; +- EFI_DHCP6_PACKET *SelectAd; +- EFI_STATUS Status; +- BOOLEAN Received; ++ PXEBC_PRIVATE_DATA *Private; ++ EFI_PXE_BASE_CODE_MODE *Mode; ++ EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback; ++ EFI_DHCP6_PACKET *SelectAd; ++ EFI_STATUS Status; ++ BOOLEAN Received; + + if ((Dhcp6Event != Dhcp6RcvdAdvertise) && + (Dhcp6Event != Dhcp6SelectAdvertise) && + (Dhcp6Event != Dhcp6SendSolicit) && + (Dhcp6Event != Dhcp6SendRequest) && +- (Dhcp6Event != Dhcp6RcvdReply)) { ++ (Dhcp6Event != Dhcp6RcvdReply)) ++ { + return EFI_SUCCESS; + } + + ASSERT (Packet != NULL); + +- Private = (PXEBC_PRIVATE_DATA *) Context; +- Mode = Private->PxeBc.Mode; +- Callback = Private->PxeBcCallback; ++ Private = (PXEBC_PRIVATE_DATA *)Context; ++ Mode = Private->PxeBc.Mode; ++ Callback = Private->PxeBcCallback; + + // + // Callback to user when any traffic occurred if has. + // +- if (Dhcp6Event != Dhcp6SelectAdvertise && Callback != NULL) { +- Received = (BOOLEAN) (Dhcp6Event == Dhcp6RcvdAdvertise || Dhcp6Event == Dhcp6RcvdReply); +- Status = Callback->Callback ( +- Callback, +- Private->Function, +- Received, +- Packet->Length, +- (EFI_PXE_BASE_CODE_PACKET *) &Packet->Dhcp6 +- ); ++ if ((Dhcp6Event != Dhcp6SelectAdvertise) && (Callback != NULL)) { ++ Received = (BOOLEAN)(Dhcp6Event == Dhcp6RcvdAdvertise || Dhcp6Event == Dhcp6RcvdReply); ++ Status = Callback->Callback ( ++ Callback, ++ Private->Function, ++ Received, ++ Packet->Length, ++ (EFI_PXE_BASE_CODE_PACKET *)&Packet->Dhcp6 ++ ); + if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { + return EFI_ABORTED; + } +@@ -1934,108 +1947,114 @@ PxeBcDhcp6CallBack ( + Status = EFI_SUCCESS; + + switch (Dhcp6Event) { ++ case Dhcp6SendSolicit: ++ if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { ++ // ++ // If the to be sent packet exceeds the maximum length, abort the DHCP process. ++ // ++ Status = EFI_ABORTED; ++ break; ++ } + +- case Dhcp6SendSolicit: +- if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { + // +- // If the to be sent packet exceeds the maximum length, abort the DHCP process. ++ // Record the first Solicate msg time + // +- Status = EFI_ABORTED; +- break; +- } +- +- // +- // Record the first Solicate msg time +- // +- if (Private->SolicitTimes == 0) { +- CalcElapsedTime (Private); +- Private->SolicitTimes++; +- } +- // +- // Cache the dhcp discover packet to mode data directly. +- // +- CopyMem (&Mode->DhcpDiscover.Dhcpv4, &Packet->Dhcp6, Packet->Length); +- break; ++ if (Private->SolicitTimes == 0) { ++ CalcElapsedTime (Private); ++ Private->SolicitTimes++; ++ } + +- case Dhcp6RcvdAdvertise: +- Status = EFI_NOT_READY; +- if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { + // +- // Ignore the incoming packets which exceed the maximum length. ++ // Cache the dhcp discover packet to mode data directly. + // ++ CopyMem (&Mode->DhcpDiscover.Dhcpv4, &Packet->Dhcp6, Packet->Length); + break; +- } +- if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) { ++ ++ case Dhcp6RcvdAdvertise: ++ Status = EFI_NOT_READY; ++ if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { ++ // ++ // Ignore the incoming packets which exceed the maximum length. ++ // ++ break; ++ } ++ ++ if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) { ++ // ++ // Cache the dhcp offers to OfferBuffer[] for select later, and record ++ // the OfferIndex and OfferCount. ++ // ++ PxeBcCacheDhcp6Offer (Private, Packet); ++ } ++ ++ break; ++ ++ case Dhcp6SendRequest: ++ if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { ++ // ++ // If the to be sent packet exceeds the maximum length, abort the DHCP process. ++ // ++ Status = EFI_ABORTED; ++ break; ++ } ++ + // +- // Cache the dhcp offers to OfferBuffer[] for select later, and record +- // the OfferIndex and OfferCount. ++ // Store the request packet as seed packet for discover. + // +- PxeBcCacheDhcp6Offer (Private, Packet); +- } +- break; ++ if (Private->Dhcp6Request != NULL) { ++ FreePool (Private->Dhcp6Request); ++ } ++ ++ Private->Dhcp6Request = AllocateZeroPool (Packet->Size); ++ if (Private->Dhcp6Request != NULL) { ++ CopyMem (Private->Dhcp6Request, Packet, Packet->Size); ++ } ++ ++ break; + +- case Dhcp6SendRequest: +- if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { ++ case Dhcp6SelectAdvertise: + // +- // If the to be sent packet exceeds the maximum length, abort the DHCP process. ++ // Select offer by the default policy or by order, and record the SelectIndex ++ // and SelectProxyType. + // +- Status = EFI_ABORTED; +- break; +- } ++ PxeBcSelectDhcp6Offer (Private); + +- // +- // Store the request packet as seed packet for discover. +- // +- if (Private->Dhcp6Request != NULL) { +- FreePool (Private->Dhcp6Request); +- } +- Private->Dhcp6Request = AllocateZeroPool (Packet->Size); +- if (Private->Dhcp6Request != NULL) { +- CopyMem (Private->Dhcp6Request, Packet, Packet->Size); +- } +- break; ++ if (Private->SelectIndex == 0) { ++ Status = EFI_ABORTED; ++ } else { ++ ASSERT (NewPacket != NULL); ++ SelectAd = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer; ++ *NewPacket = AllocateZeroPool (SelectAd->Size); ++ ASSERT (*NewPacket != NULL); ++ if (*NewPacket == NULL) { ++ return EFI_ABORTED; ++ } + +- case Dhcp6SelectAdvertise: +- // +- // Select offer by the default policy or by order, and record the SelectIndex +- // and SelectProxyType. +- // +- PxeBcSelectDhcp6Offer (Private); ++ CopyMem (*NewPacket, SelectAd, SelectAd->Size); ++ } + +- if (Private->SelectIndex == 0) { +- Status = EFI_ABORTED; +- } else { +- ASSERT (NewPacket != NULL); +- SelectAd = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer; +- *NewPacket = AllocateZeroPool (SelectAd->Size); +- ASSERT (*NewPacket != NULL); +- if (*NewPacket == NULL) { +- return EFI_ABORTED; ++ break; ++ ++ case Dhcp6RcvdReply: ++ // ++ // Cache the dhcp ack to Private->Dhcp6Ack, but it's not the final ack in mode data ++ // without verification. ++ // ++ ASSERT (Private->SelectIndex != 0); ++ Status = PxeBcCopyDhcp6Ack (Private, Packet, FALSE); ++ if (EFI_ERROR (Status)) { ++ Status = EFI_ABORTED; + } +- CopyMem (*NewPacket, SelectAd, SelectAd->Size); +- } +- break; + +- case Dhcp6RcvdReply: +- // +- // Cache the dhcp ack to Private->Dhcp6Ack, but it's not the final ack in mode data +- // without verification. +- // +- ASSERT (Private->SelectIndex != 0); +- Status = PxeBcCopyDhcp6Ack (Private, Packet, FALSE); +- if (EFI_ERROR (Status)) { +- Status = EFI_ABORTED; +- } +- break; ++ break; + +- default: +- ASSERT (0); ++ default: ++ ASSERT (0); + } + + return Status; + } + +- + /** + Build and send out the request packet for the bootfile, and parse the reply. + +@@ -2053,37 +2072,37 @@ PxeBcDhcp6CallBack ( + **/ + EFI_STATUS + PxeBcDhcp6Discover ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN UINT16 Type, +- IN UINT16 *Layer, +- IN BOOLEAN UseBis, +- IN EFI_IP_ADDRESS *DestIp ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN UINT16 Type, ++ IN UINT16 *Layer, ++ IN BOOLEAN UseBis, ++ IN EFI_IP_ADDRESS *DestIp + ) + { +- EFI_PXE_BASE_CODE_UDP_PORT SrcPort; +- EFI_PXE_BASE_CODE_UDP_PORT DestPort; +- EFI_PXE_BASE_CODE_MODE *Mode; +- EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; +- EFI_PXE_BASE_CODE_DHCPV6_PACKET *Discover; +- UINTN DiscoverLen; +- EFI_DHCP6_PACKET *Request; +- UINTN RequestLen; +- EFI_DHCP6_PACKET *Reply; +- UINT8 *RequestOpt; +- UINT8 *DiscoverOpt; +- UINTN ReadSize; +- UINT16 OpCode; +- UINT16 OpLen; +- UINT32 Xid; +- EFI_STATUS Status; +- +- PxeBc = &Private->PxeBc; +- Mode = PxeBc->Mode; +- Request = Private->Dhcp6Request; +- SrcPort = PXEBC_BS_DISCOVER_PORT; +- DestPort = PXEBC_BS_DISCOVER_PORT; +- +- if (!UseBis && Layer != NULL) { ++ EFI_PXE_BASE_CODE_UDP_PORT SrcPort; ++ EFI_PXE_BASE_CODE_UDP_PORT DestPort; ++ EFI_PXE_BASE_CODE_MODE *Mode; ++ EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; ++ EFI_PXE_BASE_CODE_DHCPV6_PACKET *Discover; ++ UINTN DiscoverLen; ++ EFI_DHCP6_PACKET *Request; ++ UINTN RequestLen; ++ EFI_DHCP6_PACKET *Reply; ++ UINT8 *RequestOpt; ++ UINT8 *DiscoverOpt; ++ UINTN ReadSize; ++ UINT16 OpCode; ++ UINT16 OpLen; ++ UINT32 Xid; ++ EFI_STATUS Status; ++ ++ PxeBc = &Private->PxeBc; ++ Mode = PxeBc->Mode; ++ Request = Private->Dhcp6Request; ++ SrcPort = PXEBC_BS_DISCOVER_PORT; ++ DestPort = PXEBC_BS_DISCOVER_PORT; ++ ++ if (!UseBis && (Layer != NULL)) { + *Layer &= EFI_PXE_BASE_CODE_BOOT_LAYER_MASK; + } + +@@ -2108,10 +2127,11 @@ PxeBcDhcp6Discover ( + RequestLen = DiscoverLen; + + while (RequestLen < Request->Length) { +- OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpCode); +- OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpLen); +- if (OpCode != EFI_DHCP6_IA_TYPE_NA && +- OpCode != EFI_DHCP6_IA_TYPE_TA) { ++ OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode); ++ OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen); ++ if ((OpCode != EFI_DHCP6_IA_TYPE_NA) && ++ (OpCode != EFI_DHCP6_IA_TYPE_TA)) ++ { + // + // Copy all the options except IA option. + // +@@ -2119,6 +2139,7 @@ PxeBcDhcp6Discover ( + DiscoverOpt += (OpLen + 4); + DiscoverLen += (OpLen + 4); + } ++ + RequestOpt += (OpLen + 4); + RequestLen += (OpLen + 4); + } +@@ -2134,7 +2155,7 @@ PxeBcDhcp6Discover ( + NULL, + NULL, + &DiscoverLen, +- (VOID *) Discover ++ (VOID *)Discover + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; +@@ -2150,7 +2171,8 @@ PxeBcDhcp6Discover ( + } else { + Reply = &Private->ProxyOffer.Dhcp6.Packet.Offer; + } +- ReadSize = (UINTN) Reply->Size; ++ ++ ReadSize = (UINTN)Reply->Size; + + // + // Start Udp6Read instance +@@ -2170,7 +2192,7 @@ PxeBcDhcp6Discover ( + NULL, + NULL, + &ReadSize, +- (VOID *) &Reply->Dhcp6 ++ (VOID *)&Reply->Dhcp6 + ); + // + // Stop Udp6Read instance +@@ -2190,7 +2212,6 @@ ON_ERROR: + return Status; + } + +- + /** + Start the DHCPv6 S.A.R.R. process to acquire the IPv6 address and other PXE boot information. + +@@ -2203,35 +2224,35 @@ ON_ERROR: + **/ + EFI_STATUS + PxeBcDhcp6Sarr ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN EFI_DHCP6_PROTOCOL *Dhcp6 ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN EFI_DHCP6_PROTOCOL *Dhcp6 + ) + { +- EFI_PXE_BASE_CODE_MODE *PxeMode; +- EFI_DHCP6_CONFIG_DATA Config; +- EFI_DHCP6_MODE_DATA Mode; +- EFI_DHCP6_RETRANSMISSION *Retransmit; +- EFI_DHCP6_PACKET_OPTION *OptList[PXEBC_DHCP6_OPTION_MAX_NUM]; +- UINT8 Buffer[PXEBC_DHCP6_OPTION_MAX_SIZE]; +- UINT32 OptCount; +- EFI_STATUS Status; +- EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; +- EFI_STATUS TimerStatus; +- EFI_EVENT Timer; +- UINT64 GetMappingTimeOut; +- UINTN DataSize; +- EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits; +- +- Status = EFI_SUCCESS; +- PxeMode = Private->PxeBc.Mode; +- Ip6Cfg = Private->Ip6Cfg; +- Timer = NULL; ++ EFI_PXE_BASE_CODE_MODE *PxeMode; ++ EFI_DHCP6_CONFIG_DATA Config; ++ EFI_DHCP6_MODE_DATA Mode; ++ EFI_DHCP6_RETRANSMISSION *Retransmit; ++ EFI_DHCP6_PACKET_OPTION *OptList[PXEBC_DHCP6_OPTION_MAX_NUM]; ++ UINT8 Buffer[PXEBC_DHCP6_OPTION_MAX_SIZE]; ++ UINT32 OptCount; ++ EFI_STATUS Status; ++ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; ++ EFI_STATUS TimerStatus; ++ EFI_EVENT Timer; ++ UINT64 GetMappingTimeOut; ++ UINTN DataSize; ++ EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits; ++ ++ Status = EFI_SUCCESS; ++ PxeMode = Private->PxeBc.Mode; ++ Ip6Cfg = Private->Ip6Cfg; ++ Timer = NULL; + + // + // Build option list for the request packet. + // +- OptCount = PxeBcBuildDhcp6Options (Private, OptList, Buffer); +- ASSERT (OptCount> 0); ++ OptCount = PxeBcBuildDhcp6Options (Private, OptList, Buffer); ++ ASSERT (OptCount > 0); + + Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION)); + if (Retransmit == NULL) { +@@ -2274,7 +2295,6 @@ PxeBcDhcp6Sarr ( + ZeroMem (Private->OfferCount, sizeof (Private->OfferCount)); + ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex)); + +- + // + // Start DHCPv6 S.A.R.R. process to acquire IPv6 address. + // +@@ -2290,12 +2310,12 @@ PxeBcDhcp6Sarr ( + // Get Duplicate Address Detection Transmits count. + // + DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS); +- Status = Ip6Cfg->GetData ( +- Ip6Cfg, +- Ip6ConfigDataTypeDupAddrDetectTransmits, +- &DataSize, +- &DadXmits +- ); ++ Status = Ip6Cfg->GetData ( ++ Ip6Cfg, ++ Ip6ConfigDataTypeDupAddrDetectTransmits, ++ &DataSize, ++ &DadXmits ++ ); + if (EFI_ERROR (Status)) { + Dhcp6->Configure (Dhcp6, NULL); + return Status; +@@ -2308,7 +2328,7 @@ PxeBcDhcp6Sarr ( + } + + GetMappingTimeOut = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + PXEBC_DAD_ADDITIONAL_DELAY; +- Status = gBS->SetTimer (Timer, TimerRelative, GetMappingTimeOut); ++ Status = gBS->SetTimer (Timer, TimerRelative, GetMappingTimeOut); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (Timer); + Dhcp6->Configure (Dhcp6, NULL); +@@ -2316,7 +2336,6 @@ PxeBcDhcp6Sarr ( + } + + do { +- + TimerStatus = gBS->CheckEvent (Timer); + if (!EFI_ERROR (TimerStatus)) { + Status = Dhcp6->Start (Dhcp6); +@@ -2325,10 +2344,12 @@ PxeBcDhcp6Sarr ( + + gBS->CloseEvent (Timer); + } ++ + if (EFI_ERROR (Status)) { + if (Status == EFI_ICMP_ERROR) { + PxeMode->IcmpErrorReceived = TRUE; + } ++ + Dhcp6->Configure (Dhcp6, NULL); + return Status; + } +@@ -2354,9 +2375,11 @@ PxeBcDhcp6Sarr ( + if (Mode.ClientId != NULL) { + FreePool (Mode.ClientId); + } ++ + if (Mode.Ia != NULL) { + FreePool (Mode.Ia); + } ++ + // + // Check the selected offer whether BINL retry is needed. + // +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch b/edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch new file mode 100644 index 0000000..e37b524 --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch @@ -0,0 +1,69 @@ +From 649fe647114ca5dee84b0c55106ee58a9703984f Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 15/15] NetworkPkg: Dhcp6Dxe: Packet-Length is not updated + before appending + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [15/15] bc7ef287311bb3f757bc26f8921875566bcb5917 + +JIRA: https://issues.redhat.com/browse/RHEL-21840 +CVE: CVE-2023-45229 +Upstream: Merged + +commit 75deaf5c3c0d164c61653258c331151241bb69d8 +Author: Doug Flick +Date: Tue Feb 13 10:46:02 2024 -0800 + + NetworkPkg: Dhcp6Dxe: Packet-Length is not updated before appending + + In order for Dhcp6AppendIaAddrOption (..) to safely append the IA + Address option, the Packet-Length field must be updated before appending + the option. + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + Reviewed-by: Leif Lindholm + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +index e172ffc2a2..c23eff8766 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +@@ -948,6 +948,11 @@ Dhcp6AppendIaOption ( + *PacketCursor += sizeof (T2); + } + ++ // ++ // Update the packet length ++ // ++ Packet->Length += BytesNeeded; ++ + // + // Fill all the addresses belong to the Ia + // +@@ -959,11 +964,6 @@ Dhcp6AppendIaOption ( + } + } + +- // +- // Update the packet length +- // +- Packet->Length += BytesNeeded; +- + // + // Fill the value of Ia option length + // +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch b/edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch new file mode 100644 index 0000000..a928fa2 --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch @@ -0,0 +1,161 @@ +From 4bf844922a963cb20fb1e72ca11a65a673992ca2 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 14/15] NetworkPkg: Dhcp6Dxe: Removes duplicate check and + replaces with macro + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [14/15] a943400f9267b219bf1fd202534500f82a2a4c56 + +JIRA: https://issues.redhat.com/browse/RHEL-21840 +CVE: CVE-2023-45229 +Upstream: Merged + +commit af3fad99d6088881562e50149f414f76a5be0140 +Author: Doug Flick +Date: Tue Feb 13 10:46:01 2024 -0800 + + NetworkPkg: Dhcp6Dxe: Removes duplicate check and replaces with macro + + Removes duplicate check after merge + + > + > // + > // Verify the PacketCursor is within the packet + > // + > if ( (*PacketCursor < Packet->Dhcp6.Option) + > || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - + sizeof (EFI_DHCP6_HEADER)))) + > { + > return EFI_INVALID_PARAMETER; + > } + > + + Converts the check to a macro and replaces all instances of the check + with the macro + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + Reviewed-by: Leif Lindholm + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 43 +++++++++++++----------------- + 1 file changed, 18 insertions(+), 25 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +index 484c360a96..e172ffc2a2 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +@@ -10,6 +10,15 @@ + + #include "Dhcp6Impl.h" + ++// ++// Verifies the packet cursor is within the packet ++// otherwise it is invalid ++// ++#define IS_INVALID_PACKET_CURSOR(PacketCursor, Packet) \ ++ (((*PacketCursor) < (Packet)->Dhcp6.Option) || \ ++ ((*PacketCursor) >= (Packet)->Dhcp6.Option + ((Packet)->Size - sizeof(EFI_DHCP6_HEADER))) \ ++ ) \ ++ + + /** + Generate client Duid in the format of Duid-llt. +@@ -662,9 +671,7 @@ Dhcp6AppendOption ( + // + // Verify the PacketCursor is within the packet + // +- if ( (*PacketCursor < Packet->Dhcp6.Option) +- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) +- { ++ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) { + return EFI_INVALID_PARAMETER; + } + +@@ -681,15 +688,6 @@ Dhcp6AppendOption ( + return EFI_BUFFER_TOO_SMALL; + } + +- // +- // Verify the PacketCursor is within the packet +- // +- if ( (*PacketCursor < Packet->Dhcp6.Option) +- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) +- { +- return EFI_INVALID_PARAMETER; +- } +- + WriteUnaligned16 ((UINT16 *)*PacketCursor, OptType); + *PacketCursor += DHCP6_SIZE_OF_OPT_CODE; + WriteUnaligned16 ((UINT16 *)*PacketCursor, OptLen); +@@ -768,9 +766,7 @@ Dhcp6AppendIaAddrOption ( + // + // Verify the PacketCursor is within the packet + // +- if ( (*PacketCursor < Packet->Dhcp6.Option) +- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) +- { ++ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) { + return EFI_INVALID_PARAMETER; + } + +@@ -902,9 +898,7 @@ Dhcp6AppendIaOption ( + // + // Verify the PacketCursor is within the packet + // +- if ( (*PacketCursor < Packet->Dhcp6.Option) +- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) +- { ++ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) { + return EFI_INVALID_PARAMETER; + } + +@@ -966,14 +960,14 @@ Dhcp6AppendIaOption ( + } + + // +- // Fill the value of Ia option length ++ // Update the packet length + // +- *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2)); ++ Packet->Length += BytesNeeded; + + // +- // Update the packet length ++ // Fill the value of Ia option length + // +- Packet->Length += BytesNeeded; ++ *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2)); + + return EFI_SUCCESS; + } +@@ -982,6 +976,7 @@ Dhcp6AppendIaOption ( + Append the appointed Elapsed time option to Buf, and move Buf to the end. + + @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ will be updated. + @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor + will be moved to the end of the option. + @param[in] Instance The pointer to the Dhcp6 instance. +@@ -1037,9 +1032,7 @@ Dhcp6AppendETOption ( + // + // Verify the PacketCursor is within the packet + // +- if ( (*PacketCursor < Packet->Dhcp6.Option) +- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) +- { ++ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) { + return EFI_INVALID_PARAMETER; + } + +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch new file mode 100644 index 0000000..dcf5bb7 --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch @@ -0,0 +1,621 @@ +From a115d0a66c3e73c60b74ec6d09e3759da89e919b Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 9 Feb 2024 17:57:07 -0500 +Subject: [PATCH 17/17] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 + Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 50: CVE-2023-45230 and CVE-2023-45229 +RH-Jira: RHEL-21840 RHEL-21842 +RH-Acked-by: Oliver Steffen +RH-Commit: [4/4] 3daf69000f78416ee1f1bad0b6ceb01ed28a84a5 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21840 +CVE: CVE-2023-45229 +Upstream: Merged + +commit 1dbb10cc52dc8ef49bb700daa1cefc76b26d52e0 +Author: Doug Flick via groups.io +Date: Fri Jan 26 05:54:46 2024 +0800 + + NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534 + + Bug Details: + PixieFail Bug #1 + CVE-2023-45229 + CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N + CWE-125 Out-of-bounds Read + + Change Overview: + + Introduce Dhcp6SeekInnerOptionSafe which performs checks before seeking + the Inner Option from a DHCP6 Option. + + > + > EFI_STATUS + > Dhcp6SeekInnerOptionSafe ( + > IN UINT16 IaType, + > IN UINT8 *Option, + > IN UINT32 OptionLen, + > OUT UINT8 **IaInnerOpt, + > OUT UINT16 *IaInnerLen + > ); + > + + Lots of code cleanup to improve code readability. + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 138 ++++++++++++++++++--- + NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 205 +++++++++++++++++++++----------- + 2 files changed, 257 insertions(+), 86 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h +index ec0ed5d8f5..e759ab9a62 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h +@@ -47,6 +47,20 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE; + #define DHCP6_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'S') + #define DHCP6_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'I') + ++#define DHCP6_PACKET_ALL 0 ++#define DHCP6_PACKET_STATEFUL 1 ++#define DHCP6_PACKET_STATELESS 2 ++ ++#define DHCP6_BASE_PACKET_SIZE 1024 ++ ++#define DHCP6_PORT_CLIENT 546 ++#define DHCP6_PORT_SERVER 547 ++ ++#define DHCP_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20) ++ ++#define DHCP6_INSTANCE_FROM_THIS(Instance) CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE) ++#define DHCP6_SERVICE_FROM_THIS(Service) CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE) ++ + // + // For more information on DHCP options see RFC 8415, Section 21.1 + // +@@ -61,12 +75,10 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE; + // | (option-len octets) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // +-#define DHCP6_SIZE_OF_OPT_CODE (sizeof(UINT16)) +-#define DHCP6_SIZE_OF_OPT_LEN (sizeof(UINT16)) ++#define DHCP6_SIZE_OF_OPT_CODE (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpCode)) ++#define DHCP6_SIZE_OF_OPT_LEN (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpLen)) + +-// + // Combined size of Code and Length +-// + #define DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN (DHCP6_SIZE_OF_OPT_CODE + \ + DHCP6_SIZE_OF_OPT_LEN) + +@@ -75,34 +87,122 @@ STATIC_ASSERT ( + "Combined size of Code and Length must be 4 per RFC 8415" + ); + +-// + // Offset to the length is just past the code +-// +-#define DHCP6_OPT_LEN_OFFSET(a) (a + DHCP6_SIZE_OF_OPT_CODE) ++#define DHCP6_OFFSET_OF_OPT_LEN(a) (a + DHCP6_SIZE_OF_OPT_CODE) + STATIC_ASSERT ( +- DHCP6_OPT_LEN_OFFSET (0) == 2, ++ DHCP6_OFFSET_OF_OPT_LEN (0) == 2, + "Offset of length is + 2 past start of option" + ); + +-#define DHCP6_OPT_DATA_OFFSET(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN) ++#define DHCP6_OFFSET_OF_OPT_DATA(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN) + STATIC_ASSERT ( +- DHCP6_OPT_DATA_OFFSET (0) == 4, ++ DHCP6_OFFSET_OF_OPT_DATA (0) == 4, + "Offset to option data should be +4 from start of option" + ); ++// ++// Identity Association options (both NA (Non-Temporary) and TA (Temporary Association)) ++// are defined in RFC 8415 and are a deriviation of a TLV stucture ++// For more information on IA_NA see Section 21.4 ++// For more information on IA_TA see Section 21.5 ++// ++// ++// The format of IA_NA and IA_TA option: ++// ++// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | OPTION_IA_NA | option-len | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | IAID (4 octets) | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | T1 (only for IA_NA) | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | T2 (only for IA_NA) | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | | ++// . IA_NA-options/IA_TA-options . ++// . . ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// ++#define DHCP6_SIZE_OF_IAID (sizeof(UINT32)) ++#define DHCP6_SIZE_OF_TIME_INTERVAL (sizeof(UINT32)) + +-#define DHCP6_PACKET_ALL 0 +-#define DHCP6_PACKET_STATEFUL 1 +-#define DHCP6_PACKET_STATELESS 2 ++// Combined size of IAID, T1, and T2 ++#define DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 (DHCP6_SIZE_OF_IAID + \ ++ DHCP6_SIZE_OF_TIME_INTERVAL + \ ++ DHCP6_SIZE_OF_TIME_INTERVAL) ++STATIC_ASSERT ( ++ DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 == 12, ++ "Combined size of IAID, T1, T2 must be 12 per RFC 8415" ++ ); + +-#define DHCP6_BASE_PACKET_SIZE 1024 ++// This is the size of IA_TA without options ++#define DHCP6_MIN_SIZE_OF_IA_TA (DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \ ++ DHCP6_SIZE_OF_IAID) ++STATIC_ASSERT ( ++ DHCP6_MIN_SIZE_OF_IA_TA == 8, ++ "Minimum combined size of IA_TA per RFC 8415" ++ ); + +-#define DHCP6_PORT_CLIENT 546 +-#define DHCP6_PORT_SERVER 547 ++// Offset to a IA_TA inner option ++#define DHCP6_OFFSET_OF_IA_TA_INNER_OPT(a) (a + DHCP6_MIN_SIZE_OF_IA_TA) ++STATIC_ASSERT ( ++ DHCP6_OFFSET_OF_IA_TA_INNER_OPT (0) == 8, ++ "Offset of IA_TA Inner option is + 8 past start of option" ++ ); + +-#define DHCP_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20) ++// This is the size of IA_NA without options (16) ++#define DHCP6_MIN_SIZE_OF_IA_NA DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \ ++ DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 ++STATIC_ASSERT ( ++ DHCP6_MIN_SIZE_OF_IA_NA == 16, ++ "Minimum combined size of IA_TA per RFC 8415" ++ ); + +-#define DHCP6_INSTANCE_FROM_THIS(Instance) CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE) +-#define DHCP6_SERVICE_FROM_THIS(Service) CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE) ++#define DHCP6_OFFSET_OF_IA_NA_INNER_OPT(a) (a + DHCP6_MIN_SIZE_OF_IA_NA) ++STATIC_ASSERT ( ++ DHCP6_OFFSET_OF_IA_NA_INNER_OPT (0) == 16, ++ "Offset of IA_NA Inner option is + 16 past start of option" ++ ); ++ ++#define DHCP6_OFFSET_OF_IA_NA_T1(a) (a + \ ++ DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \ ++ DHCP6_SIZE_OF_IAID) ++STATIC_ASSERT ( ++ DHCP6_OFFSET_OF_IA_NA_T1 (0) == 8, ++ "Offset of IA_NA Inner option is + 8 past start of option" ++ ); ++ ++#define DHCP6_OFFSET_OF_IA_NA_T2(a) (a + \ ++ DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN +\ ++ DHCP6_SIZE_OF_IAID + \ ++ DHCP6_SIZE_OF_TIME_INTERVAL) ++STATIC_ASSERT ( ++ DHCP6_OFFSET_OF_IA_NA_T2 (0) == 12, ++ "Offset of IA_NA Inner option is + 12 past start of option" ++ ); ++ ++// ++// For more information see RFC 8415 Section 21.13 ++// ++// The format of the Status Code Option: ++// ++// 0 1 2 3 ++// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | OPTION_STATUS_CODE | option-len | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | status-code | | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ++// . . ++// . status-message . ++// . . ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// ++#define DHCP6_OFFSET_OF_STATUS_CODE(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN) ++STATIC_ASSERT ( ++ DHCP6_OFFSET_OF_STATUS_CODE (0) == 4, ++ "Offset of status is + 4 past start of option" ++ ); + + extern EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress; + extern EFI_DHCP6_PROTOCOL gDhcp6ProtocolTemplate; +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +index 2976684aba..d680febbf1 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +@@ -611,8 +611,8 @@ Dhcp6UpdateIaInfo ( + // The inner options still start with 2 bytes option-code and 2 bytes option-len. + // + if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) { +- T1 = NTOHL (ReadUnaligned32 ((UINT32 *) (Option + 8))); +- T2 = NTOHL (ReadUnaligned32 ((UINT32 *) (Option + 12))); ++ T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T1 (Option)))); ++ T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T2 (Option)))); + // + // Refer to RFC3155 Chapter 22.4. If a client receives an IA_NA with T1 greater than T2, + // and both T1 and T2 are greater than 0, the client discards the IA_NA option and processes +@@ -621,13 +621,14 @@ Dhcp6UpdateIaInfo ( + if (T1 > T2 && T2 > 0) { + return EFI_DEVICE_ERROR; + } +- IaInnerOpt = Option + 16; +- IaInnerLen = (UINT16) (NTOHS (ReadUnaligned16 ((UINT16 *) (Option + 2))) - 12); ++ IaInnerOpt = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option); ++ IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_COMBINED_IAID_T1_T2); + } else { + T1 = 0; + T2 = 0; +- IaInnerOpt = Option + 8; +- IaInnerLen = (UINT16) (NTOHS (ReadUnaligned16 ((UINT16 *) (Option + 2))) - 4); ++ ++ IaInnerOpt = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option); ++ IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_IAID); + } + + // +@@ -653,7 +654,7 @@ Dhcp6UpdateIaInfo ( + Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode); + + if (Option != NULL) { +- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *) (Option + 4))); ++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))); + if (StsCode != Dhcp6StsSuccess) { + return EFI_DEVICE_ERROR; + } +@@ -675,6 +676,87 @@ Dhcp6UpdateIaInfo ( + + + ++/** ++ Seeks the Inner Options from a DHCP6 Option ++ ++ @param[in] IaType The type of the IA option. ++ @param[in] Option The pointer to the DHCP6 Option. ++ @param[in] OptionLen The length of the DHCP6 Option. ++ @param[out] IaInnerOpt The pointer to the IA inner option. ++ @param[out] IaInnerLen The length of the IA inner option. ++ ++ @retval EFI_SUCCESS Seek the inner option successfully. ++ @retval EFI_DEVICE_ERROR The OptionLen is invalid. On Error, ++ the pointers are not modified ++**/ ++EFI_STATUS ++Dhcp6SeekInnerOptionSafe ( ++ IN UINT16 IaType, ++ IN UINT8 *Option, ++ IN UINT32 OptionLen, ++ OUT UINT8 **IaInnerOpt, ++ OUT UINT16 *IaInnerLen ++ ) ++{ ++ UINT16 IaInnerLenTmp; ++ UINT8 *IaInnerOptTmp; ++ ++ if (Option == NULL) { ++ ASSERT (Option != NULL); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ if (IaInnerOpt == NULL) { ++ ASSERT (IaInnerOpt != NULL); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ if (IaInnerLen == NULL) { ++ ASSERT (IaInnerLen != NULL); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ if (IaType == Dhcp6OptIana) { ++ // Verify we have a fully formed IA_NA ++ if (OptionLen < DHCP6_MIN_SIZE_OF_IA_NA) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ IaInnerOptTmp = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option); ++ ++ // Verify the IaInnerLen is valid. ++ IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)DHCP6_OFFSET_OF_OPT_LEN (Option))); ++ if (IaInnerLenTmp < DHCP6_SIZE_OF_COMBINED_IAID_T1_T2) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ IaInnerLenTmp -= DHCP6_SIZE_OF_COMBINED_IAID_T1_T2; ++ } else if (IaType == Dhcp6OptIata) { ++ // Verify the OptionLen is valid. ++ if (OptionLen < DHCP6_MIN_SIZE_OF_IA_TA) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ IaInnerOptTmp = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option); ++ ++ // Verify the IaInnerLen is valid. ++ IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))); ++ if (IaInnerLenTmp < DHCP6_SIZE_OF_IAID) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ IaInnerLenTmp -= DHCP6_SIZE_OF_IAID; ++ } else { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ *IaInnerOpt = IaInnerOptTmp; ++ *IaInnerLen = IaInnerLenTmp; ++ ++ return EFI_SUCCESS; ++} ++ + /** + Seek StatusCode Option in package. A Status Code option may appear in the + options field of a DHCP message and/or in the options field of another option. +@@ -695,9 +777,15 @@ Dhcp6SeekStsOption ( + OUT UINT8 **Option + ) + { +- UINT8 *IaInnerOpt; +- UINT16 IaInnerLen; +- UINT16 StsCode; ++ UINT8 *IaInnerOpt; ++ UINT16 IaInnerLen; ++ UINT16 StsCode; ++ UINT32 OptionLen; ++ ++ // OptionLen is the length of the Options excluding the DHCP header. ++ // Length of the EFI_DHCP6_PACKET from the first byte of the Header field to the last ++ // byte of the Option[] field. ++ OptionLen = Packet->Length - sizeof (Packet->Dhcp6.Header); + + // + // Seek StatusCode option directly in DHCP message body. That is, search in +@@ -705,12 +793,12 @@ Dhcp6SeekStsOption ( + // + *Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ OptionLen, + Dhcp6OptStatusCode + ); + + if (*Option != NULL) { +- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *) (*Option + 4))); ++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_STATUS_CODE (*Option)))); + if (StsCode != Dhcp6StsSuccess) { + return EFI_DEVICE_ERROR; + } +@@ -721,7 +809,7 @@ Dhcp6SeekStsOption ( + // + *Option = Dhcp6SeekIaOption ( + Packet->Dhcp6.Option, +- Packet->Length - sizeof (EFI_DHCP6_HEADER), ++ OptionLen, + &Instance->Config->IaDescriptor + ); + if (*Option == NULL) { +@@ -729,52 +817,35 @@ Dhcp6SeekStsOption ( + } + + // +- // The format of the IA_NA option is: ++ // Calculate the distance from Packet->Dhcp6.Option to the IA option. + // +- // 0 1 2 3 +- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | OPTION_IA_NA | option-len | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | IAID (4 octets) | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | T1 | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | T2 | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | | +- // . IA_NA-options . +- // . . +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ // Packet->Size and Packet->Length are both UINT32 type, and Packet->Size is ++ // the size of the whole packet, including the DHCP header, and Packet->Length ++ // is the length of the DHCP message body, excluding the DHCP header. + // +- // The format of the IA_TA option is: ++ // (*Option - Packet->Dhcp6.Option) is the number of bytes from the start of ++ // DHCP6 option area to the start of the IA option. + // +- // 0 1 2 3 +- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | OPTION_IA_TA | option-len | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | IAID (4 octets) | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | | +- // . IA_TA-options . +- // . . +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ // Dhcp6SeekInnerOptionSafe() is searching starting from the start of the ++ // IA option to the end of the DHCP6 option area, thus subtract the space ++ // up until this option + // ++ OptionLen = OptionLen - (*Option - Packet->Dhcp6.Option); + + // +- // sizeof (option-code + option-len + IaId) = 8 +- // sizeof (option-code + option-len + IaId + T1) = 12 +- // sizeof (option-code + option-len + IaId + T1 + T2) = 16 ++ // Seek the inner option + // +- // The inner options still start with 2 bytes option-code and 2 bytes option-len. +- // +- if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) { +- IaInnerOpt = *Option + 16; +- IaInnerLen = (UINT16) (NTOHS (ReadUnaligned16 ((UINT16 *) (*Option + 2))) - 12); +- } else { +- IaInnerOpt = *Option + 8; +- IaInnerLen = (UINT16) (NTOHS (ReadUnaligned16 ((UINT16 *) (*Option + 2))) - 4); ++ if (EFI_ERROR ( ++ Dhcp6SeekInnerOptionSafe ( ++ Instance->Config->IaDescriptor.Type, ++ *Option, ++ OptionLen, ++ &IaInnerOpt, ++ &IaInnerLen ++ ) ++ )) ++ { ++ return EFI_DEVICE_ERROR; + } + + // +@@ -798,7 +869,7 @@ Dhcp6SeekStsOption ( + // + *Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode); + if (*Option != NULL) { +- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *) (*Option + 4))); ++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE (*Option))))); + if (StsCode != Dhcp6StsSuccess) { + return EFI_DEVICE_ERROR; + } +@@ -1123,7 +1194,7 @@ Dhcp6SendRequestMsg ( + // + Option = Dhcp6SeekOption ( + Instance->AdSelect->Dhcp6.Option, +- Instance->AdSelect->Length - 4, ++ Instance->AdSelect->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerId + ); + if (Option == NULL) { +@@ -1309,7 +1380,7 @@ Dhcp6SendDeclineMsg ( + // + Option = Dhcp6SeekOption ( + LastReply->Dhcp6.Option, +- LastReply->Length - 4, ++ LastReply->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerId + ); + if (Option == NULL) { +@@ -1469,7 +1540,7 @@ Dhcp6SendReleaseMsg ( + // + Option = Dhcp6SeekOption ( + LastReply->Dhcp6.Option, +- LastReply->Length - 4, ++ LastReply->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerId + ); + if (Option == NULL) { +@@ -1695,7 +1766,7 @@ Dhcp6SendRenewRebindMsg ( + + Option = Dhcp6SeekOption ( + LastReply->Dhcp6.Option, +- LastReply->Length - 4, ++ LastReply->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerId + ); + if (Option == NULL) { +@@ -2235,7 +2306,7 @@ Dhcp6HandleReplyMsg ( + // + Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ Packet->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptRapidCommit + ); + +@@ -2383,7 +2454,7 @@ Dhcp6HandleReplyMsg ( + // + // Any error status code option is found. + // +- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *) (Option + 4))); ++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE (Option))))); + switch (StsCode) { + case Dhcp6StsUnspecFail: + // +@@ -2514,7 +2585,7 @@ Dhcp6SelectAdvertiseMsg ( + // + Option = Dhcp6SeekOption( + AdSelect->Dhcp6.Option, +- AdSelect->Length - 4, ++ AdSelect->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerUnicast + ); + +@@ -2526,7 +2597,7 @@ Dhcp6SelectAdvertiseMsg ( + return EFI_OUT_OF_RESOURCES; + } + +- CopyMem (Instance->Unicast, Option + 4, sizeof(EFI_IPv6_ADDRESS)); ++ CopyMem (Instance->Unicast, DHCP6_OFFSET_OF_OPT_DATA (Option), sizeof (EFI_IPv6_ADDRESS)); + } + + // +@@ -2580,7 +2651,7 @@ Dhcp6HandleAdvertiseMsg ( + // + Option = Dhcp6SeekOption( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ Packet->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptRapidCommit + ); + +@@ -2676,7 +2747,7 @@ Dhcp6HandleAdvertiseMsg ( + CopyMem (Instance->AdSelect, Packet, Packet->Size); + + if (Option != NULL) { +- Instance->AdPref = *(Option + 4); ++ Instance->AdPref = *(DHCP6_OFFSET_OF_OPT_DATA (Option)); + } + } else { + // +@@ -2747,11 +2818,11 @@ Dhcp6HandleStateful ( + // + Option = Dhcp6SeekOption( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN, + Dhcp6OptClientId + ); + +- if (Option == NULL || CompareMem (Option + 4, ClientId->Duid, ClientId->Length) != 0) { ++ if ((Option == NULL) || (CompareMem (DHCP6_OFFSET_OF_OPT_DATA (Option), ClientId->Duid, ClientId->Length) != 0)) { + goto ON_CONTINUE; + } + +@@ -2760,7 +2831,7 @@ Dhcp6HandleStateful ( + // + Option = Dhcp6SeekOption( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN, + Dhcp6OptServerId + ); + +@@ -2865,7 +2936,7 @@ Dhcp6HandleStateless ( + // + Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ Packet->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerId + ); + +-- +2.41.0 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch new file mode 100644 index 0000000..ea1b84f --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch @@ -0,0 +1,257 @@ +From 1b58858f28a364a8f8fa897a78db7ced068719dd Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 13/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 + Related Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [13/15] 904fd82592208d0ca42bbb64f437691a5bdfd0b6 + +JIRA: https://issues.redhat.com/browse/RHEL-21840 +CVE: CVE-2023-45229 +Upstream: Merged + +commit 1c440a5eceedc64e892877eeac0f1a4938f5abbb +Author: Doug Flick +Date: Tue Feb 13 10:46:00 2024 -0800 + + NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Related Patch + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4673 + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534 + + This was not part of the Quarkslab bugs however the same pattern + as CVE-2023-45229 exists in Dhcp6UpdateIaInfo. + + This patch replaces the code in question with the safe function + created to patch CVE-2023-45229 + + > + > if (EFI_ERROR ( + > Dhcp6SeekInnerOptionSafe ( + > Instance->Config->IaDescriptor.Type, + > Option, + > OptionLen, + > &IaInnerOpt, + > &IaInnerLen + > ) + > )) + > { + > return EFI_DEVICE_ERROR; + > } + > + + Additionally corrects incorrect usage of macro to read the status + + > - StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)DHCP6_OFFSET_OF_OPT_LEN + (Option))); + > + StsCode = NTOHS (ReadUnaligned16 ((UINT16 *) + DHCP6_OFFSET_OF_STATUS_CODE (Option)); + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + Reviewed-by: Leif Lindholm + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 70 ++++++++++++++++++++++++++--------- + NetworkPkg/Dhcp6Dxe/Dhcp6Io.h | 22 +++++++++++ + 2 files changed, 75 insertions(+), 17 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +index 3b8feb4a20..a9bffae353 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +@@ -528,13 +528,23 @@ Dhcp6UpdateIaInfo ( + { + EFI_STATUS Status; + UINT8 *Option; ++ UINT32 OptionLen; + UINT8 *IaInnerOpt; + UINT16 IaInnerLen; + UINT16 StsCode; + UINT32 T1; + UINT32 T2; + ++ T1 = 0; ++ T2 = 0; ++ + ASSERT (Instance->Config != NULL); ++ ++ // OptionLen is the length of the Options excluding the DHCP header. ++ // Length of the EFI_DHCP6_PACKET from the first byte of the Header field to the last ++ // byte of the Option[] field. ++ OptionLen = Packet->Length - sizeof (Packet->Dhcp6.Header); ++ + // + // If the reply was received in response to a solicit with rapid commit option, + // request, renew or rebind message, the client updates the information it has +@@ -549,13 +559,29 @@ Dhcp6UpdateIaInfo ( + // + Option = Dhcp6SeekIaOption ( + Packet->Dhcp6.Option, +- Packet->Length - sizeof (EFI_DHCP6_HEADER), ++ OptionLen, + &Instance->Config->IaDescriptor + ); + if (Option == NULL) { + return EFI_DEVICE_ERROR; + } + ++ // ++ // Calculate the distance from Packet->Dhcp6.Option to the IA option. ++ // ++ // Packet->Size and Packet->Length are both UINT32 type, and Packet->Size is ++ // the size of the whole packet, including the DHCP header, and Packet->Length ++ // is the length of the DHCP message body, excluding the DHCP header. ++ // ++ // (*Option - Packet->Dhcp6.Option) is the number of bytes from the start of ++ // DHCP6 option area to the start of the IA option. ++ // ++ // Dhcp6SeekInnerOptionSafe() is searching starting from the start of the ++ // IA option to the end of the DHCP6 option area, thus subtract the space ++ // up until this option ++ // ++ OptionLen = OptionLen - (UINT32)(Option - Packet->Dhcp6.Option); ++ + // + // The format of the IA_NA option is: + // +@@ -591,32 +617,32 @@ Dhcp6UpdateIaInfo ( + // + + // +- // sizeof (option-code + option-len + IaId) = 8 +- // sizeof (option-code + option-len + IaId + T1) = 12 +- // sizeof (option-code + option-len + IaId + T1 + T2) = 16 +- // +- // The inner options still start with 2 bytes option-code and 2 bytes option-len. ++ // Seek the inner option + // ++ if (EFI_ERROR ( ++ Dhcp6SeekInnerOptionSafe ( ++ Instance->Config->IaDescriptor.Type, ++ Option, ++ OptionLen, ++ &IaInnerOpt, ++ &IaInnerLen ++ ) ++ )) ++ { ++ return EFI_DEVICE_ERROR; ++ } ++ + if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) { + T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T1 (Option)))); + T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T2 (Option)))); + // + // Refer to RFC3155 Chapter 22.4. If a client receives an IA_NA with T1 greater than T2, + // and both T1 and T2 are greater than 0, the client discards the IA_NA option and processes +- // the remainder of the message as though the server had not included the invalid IA_NA option. ++ // the remainder of the message as though the server had not included the invalid IA_NA option. + // + if ((T1 > T2) && (T2 > 0)) { + return EFI_DEVICE_ERROR; + } +- +- IaInnerOpt = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option); +- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_COMBINED_IAID_T1_T2); +- } else { +- T1 = 0; +- T2 = 0; +- +- IaInnerOpt = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option); +- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_IAID); + } + + // +@@ -642,7 +668,7 @@ Dhcp6UpdateIaInfo ( + Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode); + + if (Option != NULL) { +- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))); ++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_STATUS_CODE (Option)))); + if (StsCode != Dhcp6StsSuccess) { + return EFI_DEVICE_ERROR; + } +@@ -703,15 +729,21 @@ Dhcp6SeekInnerOptionSafe ( + } + + if (IaType == Dhcp6OptIana) { ++ // + // Verify we have a fully formed IA_NA ++ // + if (OptionLen < DHCP6_MIN_SIZE_OF_IA_NA) { + return EFI_DEVICE_ERROR; + } + ++ // ++ // Get the IA Inner Option and Length + // + IaInnerOptTmp = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option); + ++ // + // Verify the IaInnerLen is valid. ++ // + IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)DHCP6_OFFSET_OF_OPT_LEN (Option))); + if (IaInnerLenTmp < DHCP6_SIZE_OF_COMBINED_IAID_T1_T2) { + return EFI_DEVICE_ERROR; +@@ -719,14 +751,18 @@ Dhcp6SeekInnerOptionSafe ( + + IaInnerLenTmp -= DHCP6_SIZE_OF_COMBINED_IAID_T1_T2; + } else if (IaType == Dhcp6OptIata) { ++ // + // Verify the OptionLen is valid. ++ // + if (OptionLen < DHCP6_MIN_SIZE_OF_IA_TA) { + return EFI_DEVICE_ERROR; + } + + IaInnerOptTmp = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option); + ++ // + // Verify the IaInnerLen is valid. ++ // + IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))); + if (IaInnerLenTmp < DHCP6_SIZE_OF_IAID) { + return EFI_DEVICE_ERROR; +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h +index 554f0f5e5d..8c0d282bca 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h +@@ -218,4 +218,26 @@ Dhcp6OnTimerTick ( + IN VOID *Context + ); + ++/** ++ Seeks the Inner Options from a DHCP6 Option ++ ++ @param[in] IaType The type of the IA option. ++ @param[in] Option The pointer to the DHCP6 Option. ++ @param[in] OptionLen The length of the DHCP6 Option. ++ @param[out] IaInnerOpt The pointer to the IA inner option. ++ @param[out] IaInnerLen The length of the IA inner option. ++ ++ @retval EFI_SUCCESS Seek the inner option successfully. ++ @retval EFI_DEVICE_ERROR The OptionLen is invalid. On Error, ++ the pointers are not modified ++**/ ++EFI_STATUS ++Dhcp6SeekInnerOptionSafe ( ++ IN UINT16 IaType, ++ IN UINT8 *Option, ++ IN UINT32 OptionLen, ++ OUT UINT8 **IaInnerOpt, ++ OUT UINT16 *IaInnerLen ++ ); ++ + #endif +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch new file mode 100644 index 0000000..f4ee0d4 --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch @@ -0,0 +1,1644 @@ +From 1ef9758121ee50437322d84ce394279e38a7055f Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 8 Feb 2024 10:35:14 -0500 +Subject: [PATCH 14/17] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 + Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 50: CVE-2023-45230 and CVE-2023-45229 +RH-Jira: RHEL-21840 RHEL-21842 +RH-Acked-by: Oliver Steffen +RH-Commit: [1/4] 26695f0c8bd1032ba04179cb9281f753fcff2c92 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21842 +CVE: CVE-2023-45230 +Upstream: Merged +Conflicts: Only whitespace issues caused by the 'uncrustify' tool. + +commit f31453e8d6542461d92d835e0b79fec8b039174d +Author: Doug Flick via groups.io +Date: Fri Jan 26 05:54:43 2024 +0800 + + NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4535 + + Bug Details: + PixieFail Bug #2 + CVE-2023-45230 + CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H + CWE-119 Improper Restriction of Operations within the Bounds + of a Memory Buffer + + Changes Overview: + > -UINT8 * + > +EFI_STATUS + > Dhcp6AppendOption ( + > - IN OUT UINT8 *Buf, + > - IN UINT16 OptType, + > - IN UINT16 OptLen, + > - IN UINT8 *Data + > + IN OUT EFI_DHCP6_PACKET *Packet, + > + IN OUT UINT8 **PacketCursor, + > + IN UINT16 OptType, + > + IN UINT16 OptLen, + > + IN UINT8 *Data + > ); + + Dhcp6AppendOption() and variants can return errors now. All callsites + are adapted accordingly. + + It gets passed in EFI_DHCP6_PACKET as additional parameter ... + + > + // + > + // Verify the PacketCursor is within the packet + > + // + > + if ( (*PacketCursor < Packet->Dhcp6.Option) + > + || (*PacketCursor >= Packet->Dhcp6.Option + + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) + > + { + > + return EFI_INVALID_PARAMETER; + > + } + + ... so it can look at Packet->Size when checking buffer space. + Also to allow Packet->Length updates. + + Lots of checks added. + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 49 +++- + NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 409 +++++++++++++++++++---------- + NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 382 +++++++++++++++++++++------ + NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h | 82 +++--- + 4 files changed, 676 insertions(+), 246 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h +index f88b00ad04..ec0ed5d8f5 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h +@@ -47,9 +47,52 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE; + #define DHCP6_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'S') + #define DHCP6_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'I') + +-#define DHCP6_PACKET_ALL 0 +-#define DHCP6_PACKET_STATEFUL 1 +-#define DHCP6_PACKET_STATELESS 2 ++// ++// For more information on DHCP options see RFC 8415, Section 21.1 ++// ++// The format of DHCP options is: ++// ++// 0 1 2 3 ++// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | option-code | option-len | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | option-data | ++// | (option-len octets) | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// ++#define DHCP6_SIZE_OF_OPT_CODE (sizeof(UINT16)) ++#define DHCP6_SIZE_OF_OPT_LEN (sizeof(UINT16)) ++ ++// ++// Combined size of Code and Length ++// ++#define DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN (DHCP6_SIZE_OF_OPT_CODE + \ ++ DHCP6_SIZE_OF_OPT_LEN) ++ ++STATIC_ASSERT ( ++ DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN == 4, ++ "Combined size of Code and Length must be 4 per RFC 8415" ++ ); ++ ++// ++// Offset to the length is just past the code ++// ++#define DHCP6_OPT_LEN_OFFSET(a) (a + DHCP6_SIZE_OF_OPT_CODE) ++STATIC_ASSERT ( ++ DHCP6_OPT_LEN_OFFSET (0) == 2, ++ "Offset of length is + 2 past start of option" ++ ); ++ ++#define DHCP6_OPT_DATA_OFFSET(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN) ++STATIC_ASSERT ( ++ DHCP6_OPT_DATA_OFFSET (0) == 4, ++ "Offset to option data should be +4 from start of option" ++ ); ++ ++#define DHCP6_PACKET_ALL 0 ++#define DHCP6_PACKET_STATEFUL 1 ++#define DHCP6_PACKET_STATELESS 2 + + #define DHCP6_BASE_PACKET_SIZE 1024 + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +index c20876d5a5..2976684aba 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +@@ -3,9 +3,9 @@ + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
++ Copyright (c) Microsoft Corporation + + SPDX-License-Identifier: BSD-2-Clause-Patent +- + **/ + + #include "Dhcp6Impl.h" +@@ -946,7 +946,8 @@ Dhcp6SendSolicitMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; +@@ -960,26 +961,38 @@ Dhcp6SendSolicitMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption ( +- Cursor, ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, + Instance->IaCb.Ia, + Instance->IaCb.T1, + Instance->IaCb.T2, + Packet->Dhcp6.Header.MessageType + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + // + // Append user-defined when configurate Dhcp6 service. +@@ -987,28 +1000,26 @@ Dhcp6SendSolicitMsg ( + for (Index = 0; Index < Instance->Config->OptionCount; Index++) { + + UserOpt = Instance->Config->OptionList[Index]; +- Cursor = Dhcp6AppendOption( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + UserOpt->OpCode, + UserOpt->OpLen, + UserOpt->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // + // Callback to user with the packet to be sent and check the user's feedback. + // + Status = Dhcp6CallbackUser (Instance, Dhcp6SendSolicit, &Packet); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1022,10 +1033,8 @@ Dhcp6SendSolicitMsg ( + Instance->StartTime = 0; + + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1037,6 +1046,14 @@ Dhcp6SendSolicitMsg ( + Elapsed, + Instance->Config->SolicitRetransmission + ); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + /** +@@ -1128,7 +1145,8 @@ Dhcp6SendRequestMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; +@@ -1142,33 +1160,49 @@ Dhcp6SendRequestMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptServerId), + ServerId->Length, + ServerId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption ( +- Cursor, ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, + Instance->IaCb.Ia, + Instance->IaCb.T1, + Instance->IaCb.T2, + Packet->Dhcp6.Header.MessageType + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + // + // Append user-defined when configurate Dhcp6 service. +@@ -1176,18 +1210,18 @@ Dhcp6SendRequestMsg ( + for (Index = 0; Index < Instance->Config->OptionCount; Index++) { + + UserOpt = Instance->Config->OptionList[Index]; +- Cursor = Dhcp6AppendOption( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + UserOpt->OpCode, + UserOpt->OpLen, + UserOpt->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // +@@ -1196,8 +1230,7 @@ Dhcp6SendRequestMsg ( + Status = Dhcp6CallbackUser (Instance, Dhcp6SendRequest, &Packet); + + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1213,14 +1246,21 @@ Dhcp6SendRequestMsg ( + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); + + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + +@@ -1286,7 +1326,8 @@ Dhcp6SendDeclineMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE; +@@ -1300,42 +1341,58 @@ Dhcp6SendDeclineMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptServerId), + ServerId->Length, + ServerId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption (Cursor, DecIa, 0, 0, Packet->Dhcp6.Header.MessageType); ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, ++ DecIa, ++ 0, ++ 0, ++ Packet->Dhcp6.Header.MessageType ++ ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // + // Callback to user with the packet to be sent and check the user's feedback. + // + Status = Dhcp6CallbackUser (Instance, Dhcp6SendDecline, &Packet); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1349,16 +1406,22 @@ Dhcp6SendDeclineMsg ( + Instance->StartTime = 0; + + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + +@@ -1420,7 +1483,8 @@ Dhcp6SendReleaseMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE; +@@ -1434,45 +1498,61 @@ Dhcp6SendReleaseMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + // + // ServerId is extracted from packet, it's network order. + // +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptServerId), + ServerId->Length, + ServerId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption (Cursor, RelIa, 0, 0, Packet->Dhcp6.Header.MessageType); ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, ++ RelIa, ++ 0, ++ 0, ++ Packet->Dhcp6.Header.MessageType ++ ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- // +- // Determine the size/length of packet +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // + // Callback to user with the packet to be sent and check the user's feedback. + // + Status = Dhcp6CallbackUser (Instance, Dhcp6SendRelease, &Packet); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1482,16 +1562,22 @@ Dhcp6SendReleaseMsg ( + Instance->IaCb.Ia->State = Dhcp6Releasing; + + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + +@@ -1551,7 +1637,8 @@ Dhcp6SendRenewRebindMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; +@@ -1565,26 +1652,38 @@ Dhcp6SendRenewRebindMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption ( +- Cursor, ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, + Instance->IaCb.Ia, + Instance->IaCb.T1, + Instance->IaCb.T2, + Packet->Dhcp6.Header.MessageType + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + if (!RebindRequest) { + // +@@ -1600,18 +1699,22 @@ Dhcp6SendRenewRebindMsg ( + Dhcp6OptServerId + ); + if (Option == NULL) { +- FreePool (Packet); +- return EFI_DEVICE_ERROR; ++ Status = EFI_DEVICE_ERROR; ++ goto ON_ERROR; + } + + ServerId = (EFI_DHCP6_DUID *) (Option + 2); + +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptServerId), + ServerId->Length, + ServerId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + + // +@@ -1620,18 +1723,18 @@ Dhcp6SendRenewRebindMsg ( + for (Index = 0; Index < Instance->Config->OptionCount; Index++) { + + UserOpt = Instance->Config->OptionList[Index]; +- Cursor = Dhcp6AppendOption( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + UserOpt->OpCode, + UserOpt->OpLen, + UserOpt->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // +@@ -1641,10 +1744,8 @@ Dhcp6SendRenewRebindMsg ( + Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing; + + Status = Dhcp6CallbackUser (Instance, Event, &Packet); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1661,16 +1762,22 @@ Dhcp6SendRenewRebindMsg ( + Instance->StartTime = 0; + + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + /** +@@ -1834,7 +1941,8 @@ Dhcp6SendInfoRequestMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; +@@ -1851,26 +1959,38 @@ Dhcp6SendInfoRequestMsg ( + + if (SendClientId) { + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + OptionRequest->OpCode, + OptionRequest->OpLen, + OptionRequest->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + // + // Append user-defined when configurate Dhcp6 service. +@@ -1878,18 +1998,18 @@ Dhcp6SendInfoRequestMsg ( + for (Index = 0; Index < OptionCount; Index++) { + + UserOpt = OptionList[Index]; +- Cursor = Dhcp6AppendOption( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + UserOpt->OpCode, + UserOpt->OpLen, + UserOpt->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // +@@ -1901,16 +2021,22 @@ Dhcp6SendInfoRequestMsg ( + // Send info-request packet with no state. + // + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, Retransmission); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + +@@ -1962,7 +2088,8 @@ Dhcp6SendConfirmMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; +@@ -1976,54 +2103,64 @@ Dhcp6SendConfirmMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption ( +- Cursor, ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, + Instance->IaCb.Ia, + Instance->IaCb.T1, + Instance->IaCb.T2, + Packet->Dhcp6.Header.MessageType + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + // + // Append user-defined when configurate Dhcp6 service. + // + for (Index = 0; Index < Instance->Config->OptionCount; Index++) { + UserOpt = Instance->Config->OptionList[Index]; +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + UserOpt->OpCode, + UserOpt->OpLen, + UserOpt->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // + // Callback to user with the packet to be sent and check the user's feedback. + // + Status = Dhcp6CallbackUser (Instance, Dhcp6SendConfirm, &Packet); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -2037,16 +2174,22 @@ Dhcp6SendConfirmMsg ( + Instance->StartTime = 0; + + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +index d249a1cca7..484c360a96 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +@@ -601,24 +601,33 @@ Dhcp6OnTransmitted ( + + + /** +- Append the option to Buf, and move Buf to the end. ++ Append the option to Buf, update the length of packet, and move Buf to the end. + +- @param[in, out] Buf The pointer to the buffer. +- @param[in] OptType The option type. +- @param[in] OptLen The length of option contents. +- @param[in] Data The pointer to the option content. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ will be updated. ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. ++ @param[in] OptType The option type. ++ @param[in] OptLen The length of option contents. ++ @param[in] Data The pointer to the option content. + +- @return Buf The position to append the next option. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendOption ( +- IN OUT UINT8 *Buf, +- IN UINT16 OptType, +- IN UINT16 OptLen, +- IN UINT8 *Data ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN UINT16 OptType, ++ IN UINT16 OptLen, ++ IN UINT8 *Data + ) + { ++ UINT32 Length; ++ UINT32 BytesNeeded; ++ + // + // The format of Dhcp6 option: + // +@@ -631,35 +640,94 @@ Dhcp6AppendOption ( + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // + +- ASSERT (OptLen != 0); ++ // ++ // Verify the arguments are valid ++ // ++ if (Packet == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (Data == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (OptLen == 0) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Verify the PacketCursor is within the packet ++ // ++ if ( (*PacketCursor < Packet->Dhcp6.Option) ++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) ++ { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Calculate the bytes needed for the option ++ // ++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + NTOHS (OptLen); ++ ++ // ++ // Space remaining in the packet ++ // ++ Length = Packet->Size - Packet->Length; ++ if (Length < BytesNeeded) { ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ ++ // ++ // Verify the PacketCursor is within the packet ++ // ++ if ( (*PacketCursor < Packet->Dhcp6.Option) ++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) ++ { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, OptType); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, OptLen); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN; ++ CopyMem (*PacketCursor, Data, NTOHS (OptLen)); ++ *PacketCursor += NTOHS (OptLen); + +- WriteUnaligned16 ((UINT16 *) Buf, OptType); +- Buf += 2; +- WriteUnaligned16 ((UINT16 *) Buf, OptLen); +- Buf += 2; +- CopyMem (Buf, Data, NTOHS (OptLen)); +- Buf += NTOHS (OptLen); ++ // Update the packet length by the length of the option + 4 bytes ++ Packet->Length += BytesNeeded; + +- return Buf; ++ return EFI_SUCCESS; + } + + /** + Append the appointed IA Address option to Buf, and move Buf to the end. + +- @param[in, out] Buf The pointer to the position to append. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ will be updated. ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. + @param[in] IaAddr The pointer to the IA Address. + @param[in] MessageType Message type of DHCP6 package. + +- @return Buf The position to append the next option. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendIaAddrOption ( +- IN OUT UINT8 *Buf, +- IN EFI_DHCP6_IA_ADDRESS *IaAddr, +- IN UINT32 MessageType +-) ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN EFI_DHCP6_IA_ADDRESS *IaAddr, ++ IN UINT32 MessageType ++ ) + { ++ UINT32 BytesNeeded; ++ UINT32 Length; + + // The format of the IA Address option is: + // +@@ -682,17 +750,60 @@ Dhcp6AppendIaAddrOption ( + // . . + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ++ // ++ // Verify the arguments are valid ++ // ++ if (Packet == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (IaAddr == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Verify the PacketCursor is within the packet ++ // ++ if ( (*PacketCursor < Packet->Dhcp6.Option) ++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) ++ { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN; ++ BytesNeeded += sizeof (EFI_IPv6_ADDRESS); ++ // ++ // Even if the preferred-lifetime is 0, it still needs to store it. ++ // ++ BytesNeeded += sizeof (IaAddr->PreferredLifetime); ++ // ++ // Even if the valid-lifetime is 0, it still needs to store it. ++ // ++ BytesNeeded += sizeof (IaAddr->ValidLifetime); ++ ++ // ++ // Space remaining in the packet ++ // ++ Length = Packet->Size - Packet->Length; ++ if (Length < BytesNeeded) { ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ + // + // Fill the value of Ia Address option type + // +- WriteUnaligned16 ((UINT16 *) Buf, HTONS (Dhcp6OptIaAddr)); +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptIaAddr)); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE; + +- WriteUnaligned16 ((UINT16 *) Buf, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS))); +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS))); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN; + +- CopyMem (Buf, &IaAddr->IpAddress, sizeof(EFI_IPv6_ADDRESS)); +- Buf += sizeof(EFI_IPv6_ADDRESS); ++ CopyMem (*PacketCursor, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS)); ++ *PacketCursor += sizeof (EFI_IPv6_ADDRESS); + + // + // Fill the value of preferred-lifetime and valid-lifetime. +@@ -700,43 +811,59 @@ Dhcp6AppendIaAddrOption ( + // should set to 0 when initiate a Confirm message. + // + if (MessageType != Dhcp6MsgConfirm) { +- WriteUnaligned32 ((UINT32 *) Buf, HTONL (IaAddr->PreferredLifetime)); ++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->PreferredLifetime)); + } +- Buf += 4; ++ ++ *PacketCursor += sizeof (IaAddr->PreferredLifetime); + + if (MessageType != Dhcp6MsgConfirm) { +- WriteUnaligned32 ((UINT32 *) Buf, HTONL (IaAddr->ValidLifetime)); ++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->ValidLifetime)); + } +- Buf += 4; + +- return Buf; ++ *PacketCursor += sizeof (IaAddr->ValidLifetime); ++ ++ // ++ // Update the packet length ++ // ++ Packet->Length += BytesNeeded; ++ ++ return EFI_SUCCESS; + } + + + /** + Append the appointed Ia option to Buf, and move Buf to the end. + +- @param[in, out] Buf The pointer to the position to append. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ will be updated. ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. + @param[in] Ia The pointer to the Ia. + @param[in] T1 The time of T1. + @param[in] T2 The time of T2. + @param[in] MessageType Message type of DHCP6 package. + +- @return Buf The position to append the next Ia option. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendIaOption ( +- IN OUT UINT8 *Buf, +- IN EFI_DHCP6_IA *Ia, +- IN UINT32 T1, +- IN UINT32 T2, +- IN UINT32 MessageType ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN EFI_DHCP6_IA *Ia, ++ IN UINT32 T1, ++ IN UINT32 T2, ++ IN UINT32 MessageType + ) + { +- UINT8 *AddrOpt; +- UINT16 *Len; +- UINTN Index; ++ UINT8 *AddrOpt; ++ UINT16 *Len; ++ UINTN Index; ++ UINT32 BytesNeeded; ++ UINT32 Length; ++ EFI_STATUS Status; + + // + // The format of IA_NA and IA_TA option: +@@ -757,68 +884,126 @@ Dhcp6AppendIaOption ( + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // + ++ // ++ // Verify the arguments are valid ++ // ++ if (Packet == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (Ia == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Verify the PacketCursor is within the packet ++ // ++ if ( (*PacketCursor < Packet->Dhcp6.Option) ++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) ++ { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN; ++ BytesNeeded += sizeof (Ia->Descriptor.IaId); ++ // ++ // + N for the IA_NA-options/IA_TA-options ++ // Dhcp6AppendIaAddrOption will need to check the length for each address ++ // ++ if (Ia->Descriptor.Type == Dhcp6OptIana) { ++ BytesNeeded += sizeof (T1) + sizeof (T2); ++ } ++ ++ // ++ // Space remaining in the packet ++ // ++ Length = (UINT16)(Packet->Size - Packet->Length); ++ if (Length < BytesNeeded) { ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ + // + // Fill the value of Ia option type + // +- WriteUnaligned16 ((UINT16 *) Buf, HTONS (Ia->Descriptor.Type)); +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Ia->Descriptor.Type)); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE; + + // + // Fill the len of Ia option later, keep the pointer first + // +- Len = (UINT16 *) Buf; +- Buf += 2; ++ Len = (UINT16 *)*PacketCursor; ++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN; + + // + // Fill the value of iaid + // +- WriteUnaligned32 ((UINT32 *) Buf, HTONL (Ia->Descriptor.IaId)); +- Buf += 4; ++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (Ia->Descriptor.IaId)); ++ *PacketCursor += sizeof (Ia->Descriptor.IaId); + + // + // Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified. + // + if (Ia->Descriptor.Type == Dhcp6OptIana) { +- WriteUnaligned32 ((UINT32 *) Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff)); +- Buf += 4; +- WriteUnaligned32 ((UINT32 *) Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff)); +- Buf += 4; ++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T1 != 0) ? T1 : 0xffffffff)); ++ *PacketCursor += sizeof (T1); ++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T2 != 0) ? T2 : 0xffffffff)); ++ *PacketCursor += sizeof (T2); + } + + // + // Fill all the addresses belong to the Ia + // + for (Index = 0; Index < Ia->IaAddressCount; Index++) { +- AddrOpt = (UINT8 *) Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS); +- Buf = Dhcp6AppendIaAddrOption (Buf, (EFI_DHCP6_IA_ADDRESS *) AddrOpt, MessageType); ++ AddrOpt = (UINT8 *)Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS); ++ Status = Dhcp6AppendIaAddrOption (Packet, PacketCursor, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } + } + + // + // Fill the value of Ia option length + // +- *Len = HTONS ((UINT16) (Buf - (UINT8 *) Len - 2)); ++ *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2)); ++ ++ // ++ // Update the packet length ++ // ++ Packet->Length += BytesNeeded; + +- return Buf; ++ return EFI_SUCCESS; + } + + /** + Append the appointed Elapsed time option to Buf, and move Buf to the end. + +- @param[in, out] Buf The pointer to the position to append. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. + @param[in] Instance The pointer to the Dhcp6 instance. + @param[out] Elapsed The pointer to the elapsed time value in +- the generated packet. ++ the generated packet. + +- @return Buf The position to append the next Ia option. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendETOption ( +- IN OUT UINT8 *Buf, +- IN DHCP6_INSTANCE *Instance, +- OUT UINT16 **Elapsed ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN DHCP6_INSTANCE *Instance, ++ OUT UINT16 **Elapsed + ) + { ++ UINT32 BytesNeeded; ++ UINT32 Length; ++ + // + // The format of elapsed time option: + // +@@ -830,27 +1015,70 @@ Dhcp6AppendETOption ( + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // + ++ // ++ // Verify the arguments are valid ++ // ++ if (Packet == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (Instance == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((Elapsed == NULL)) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Verify the PacketCursor is within the packet ++ // ++ if ( (*PacketCursor < Packet->Dhcp6.Option) ++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) ++ { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN; ++ // ++ // + 2 for elapsed-time ++ // ++ BytesNeeded += sizeof (UINT16); ++ // ++ // Space remaining in the packet ++ // ++ Length = Packet->Size - Packet->Length; ++ if (Length < BytesNeeded) { ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ + // + // Fill the value of elapsed-time option type. + // +- WriteUnaligned16 ((UINT16 *) Buf, HTONS (Dhcp6OptElapsedTime)); +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptElapsedTime)); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE; + + // + // Fill the len of elapsed-time option, which is fixed. + // +- WriteUnaligned16 ((UINT16 *) Buf, HTONS(2)); +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (2)); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN; + + // + // Fill in elapsed time value with 0 value for now. The actual value is + // filled in later just before the packet is transmitted. + // +- WriteUnaligned16 ((UINT16 *) Buf, HTONS(0)); +- *Elapsed = (UINT16 *) Buf; +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (0)); ++ *Elapsed = (UINT16 *)*PacketCursor; ++ *PacketCursor += sizeof (UINT16); + +- return Buf; ++ Packet->Length += BytesNeeded; ++ ++ return EFI_SUCCESS; + } + + /** +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h +index 2f18eb3609..af68f77e8b 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h +@@ -161,69 +161,85 @@ Dhcp6OnTransmitted ( + ); + + /** +- Append the appointed option to the buf, and move the buf to the end. +- +- @param[in, out] Buf The pointer to buffer. +- @param[in] OptType The option type. +- @param[in] OptLen The length of option content.s +- @param[in] Data The pointer to the option content. +- +- @return Buf The position to append the next option. +- ++ Append the option to Buf, update the length of packet, and move Buf to the end. ++ ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ will be updated. ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. ++ @param[in] OptType The option type. ++ @param[in] OptLen The length of option contents. ++ @param[in] Data The pointer to the option content. ++ ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendOption ( +- IN OUT UINT8 *Buf, +- IN UINT16 OptType, +- IN UINT16 OptLen, +- IN UINT8 *Data ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN UINT16 OptType, ++ IN UINT16 OptLen, ++ IN UINT8 *Data + ); + + /** +- Append the Ia option to Buf, and move Buf to the end. +- +- @param[in, out] Buf The pointer to the position to append. ++ Append the appointed Ia option to Buf, update the Ia option length, and move Buf ++ to the end of the option. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ will be updated. ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. + @param[in] Ia The pointer to the Ia. + @param[in] T1 The time of T1. + @param[in] T2 The time of T2. + @param[in] MessageType Message type of DHCP6 package. + +- @return Buf The position to append the next Ia option. +- ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendIaOption ( +- IN OUT UINT8 *Buf, +- IN EFI_DHCP6_IA *Ia, +- IN UINT32 T1, +- IN UINT32 T2, +- IN UINT32 MessageType ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN EFI_DHCP6_IA *Ia, ++ IN UINT32 T1, ++ IN UINT32 T2, ++ IN UINT32 MessageType + ); + + /** + Append the appointed Elapsed time option to Buf, and move Buf to the end. + +- @param[in, out] Buf The pointer to the position to append. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. + @param[in] Instance The pointer to the Dhcp6 instance. + @param[out] Elapsed The pointer to the elapsed time value in + the generated packet. + +- @return Buf The position to append the next Ia option. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendETOption ( +- IN OUT UINT8 *Buf, +- IN DHCP6_INSTANCE *Instance, +- OUT UINT16 **Elapsed ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN DHCP6_INSTANCE *Instance, ++ OUT UINT16 **Elapsed + ); + + /** + Set the elapsed time based on the given instance and the pointer to the + elapsed time option. + +- @param[in] Elapsed The pointer to the position to append. +- @param[in] Instance The pointer to the Dhcp6 instance. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + **/ + VOID + SetElapsedTime ( +-- +2.41.0 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch new file mode 100644 index 0000000..e7e40c1 --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch @@ -0,0 +1,629 @@ +From f5274b449181cb37efce0f08ed5d75a6bf6e54a8 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 8 Feb 2024 10:35:14 -0500 +Subject: [PATCH 16/17] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 + Unit Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 50: CVE-2023-45230 and CVE-2023-45229 +RH-Jira: RHEL-21840 RHEL-21842 +RH-Acked-by: Oliver Steffen +RH-Commit: [3/4] 43b8569c0586c7dbf66b19c5db335d0ce05829de (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21842 +CVE: CVE-2023-45230 +Upstream: Merged + +commit 5f3658197bf29c83b3349b0ab1d99cdb0c3814bc +Author: Doug Flick via groups.io +Date: Fri Jan 26 05:54:45 2024 +0800 + + NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4535 + + Confirms that reported issue... + + "Buffer overflow in the DHCPv6 client via a long Server ID option" + + ..has been corrected by the provided patch. + + Tests the following functions to ensure they appropriately handle + untrusted data (either too long or too small) to prevent a buffer + overflow: + + Dhcp6AppendOption + Dhcp6AppendETOption + Dhcp6AppendIaOption + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + .../GoogleTest/Dhcp6DxeGoogleTest.cpp | 20 + + .../GoogleTest/Dhcp6DxeGoogleTest.inf | 43 ++ + .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 478 ++++++++++++++++++ + NetworkPkg/Test/NetworkPkgHostTest.dsc | 1 + + 4 files changed, 542 insertions(+) + create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp + create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf + create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp + +diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp +new file mode 100644 +index 0000000000..9aeced2f91 +--- /dev/null ++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp +@@ -0,0 +1,20 @@ ++/** @file ++ Acts as the main entry point for the tests for the Dhcp6Dxe module. ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++ ++//////////////////////////////////////////////////////////////////////////////// ++// Run the tests ++//////////////////////////////////////////////////////////////////////////////// ++int ++main ( ++ int argc, ++ char *argv[] ++ ) ++{ ++ testing::InitGoogleTest (&argc, argv); ++ return RUN_ALL_TESTS (); ++} +diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf +new file mode 100644 +index 0000000000..8e9119a371 +--- /dev/null ++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf +@@ -0,0 +1,43 @@ ++## @file ++# Unit test suite for the Dhcp6Dxe using Google Test ++# ++# Copyright (c) Microsoft Corporation.
++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++[Defines] ++ INF_VERSION = 0x00010017 ++ BASE_NAME = Dhcp6DxeGoogleTest ++ FILE_GUID = 1D2A4C65-38C8-4C2F-BB60-B5FA49625AA9 ++ VERSION_STRING = 1.0 ++ MODULE_TYPE = HOST_APPLICATION ++# ++# The following information is for reference only and not required by the build tools. ++# ++# VALID_ARCHITECTURES = IA32 X64 AARCH64 ++# ++[Sources] ++ Dhcp6DxeGoogleTest.cpp ++ Dhcp6IoGoogleTest.cpp ++ ../Dhcp6Io.c ++ ../Dhcp6Utility.c ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ MdeModulePkg/MdeModulePkg.dec ++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec ++ NetworkPkg/NetworkPkg.dec ++ ++[LibraryClasses] ++ GoogleTestLib ++ DebugLib ++ NetLib ++ PcdLib ++ ++[Protocols] ++ gEfiDhcp6ServiceBindingProtocolGuid ++ ++[Pcd] ++ gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType ++ ++[Guids] ++ gZeroGuid +diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp +new file mode 100644 +index 0000000000..7ee40e4af4 +--- /dev/null ++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp +@@ -0,0 +1,478 @@ ++/** @file ++ Tests for Dhcp6Io.c. ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++ ++extern "C" { ++ #include ++ #include ++ #include ++ #include ++ #include "../Dhcp6Impl.h" ++ #include "../Dhcp6Utility.h" ++} ++ ++//////////////////////////////////////////////////////////////////////// ++// Defines ++//////////////////////////////////////////////////////////////////////// ++ ++#define DHCP6_PACKET_MAX_LEN 1500 ++ ++//////////////////////////////////////////////////////////////////////// ++//////////////////////////////////////////////////////////////////////// ++// Symbol Definitions ++// These functions are not directly under test - but required to compile ++//////////////////////////////////////////////////////////////////////// ++ ++// This definition is used by this test but is also required to compile ++// by Dhcp6Io.c ++EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = { ++ { 0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2 } ++}; ++ ++EFI_STATUS ++EFIAPI ++UdpIoSendDatagram ( ++ IN UDP_IO *UdpIo, ++ IN NET_BUF *Packet, ++ IN UDP_END_POINT *EndPoint OPTIONAL, ++ IN EFI_IP_ADDRESS *Gateway OPTIONAL, ++ IN UDP_IO_CALLBACK CallBack, ++ IN VOID *Context ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++UdpIoRecvDatagram ( ++ IN UDP_IO *UdpIo, ++ IN UDP_IO_CALLBACK CallBack, ++ IN VOID *Context, ++ IN UINT32 HeadLen ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++//////////////////////////////////////////////////////////////////////// ++// Dhcp6AppendOptionTest Tests ++//////////////////////////////////////////////////////////////////////// ++ ++class Dhcp6AppendOptionTest : public ::testing::Test { ++public: ++ UINT8 *Buffer = NULL; ++ EFI_DHCP6_PACKET *Packet; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Initialize any resources or variables ++ Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN); ++ ASSERT_NE (Buffer, (UINT8 *)NULL); ++ ++ Packet = (EFI_DHCP6_PACKET *)Buffer; ++ Packet->Size = DHCP6_PACKET_MAX_LEN; ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ if (Buffer != NULL) { ++ FreePool (Buffer); ++ } ++ } ++}; ++ ++// Test Description: ++// Attempt to append an option to a packet that is too small by a duid that is too large ++TEST_F (Dhcp6AppendOptionTest, InvalidDataExpectBufferTooSmall) { ++ UINT8 *Cursor; ++ EFI_DHCP6_DUID *UntrustedDuid; ++ EFI_STATUS Status; ++ ++ UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID)); ++ ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL); ++ ++ UntrustedDuid->Length = NTOHS (0xFFFF); ++ ++ Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option; ++ ++ Status = Dhcp6AppendOption ( ++ Dhcp6AppendOptionTest::Packet, ++ &Cursor, ++ HTONS (Dhcp6OptServerId), ++ UntrustedDuid->Length, ++ UntrustedDuid->Duid ++ ); ++ ++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL); ++} ++ ++// Test Description: ++// Attempt to append an option to a packet that is large enough ++TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) { ++ UINT8 *Cursor; ++ EFI_DHCP6_DUID *UntrustedDuid; ++ EFI_STATUS Status; ++ UINTN OriginalLength; ++ ++ UINT8 Duid[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; ++ ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++ OriginalLength = Packet->Length; ++ ++ UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID)); ++ ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL); ++ ++ UntrustedDuid->Length = NTOHS (sizeof (Duid)); ++ CopyMem (UntrustedDuid->Duid, Duid, sizeof (Duid)); ++ ++ Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option; ++ ++ Status = Dhcp6AppendOption ( ++ Dhcp6AppendOptionTest::Packet, ++ &Cursor, ++ HTONS (Dhcp6OptServerId), ++ UntrustedDuid->Length, ++ UntrustedDuid->Duid ++ ); ++ ++ ASSERT_EQ (Status, EFI_SUCCESS); ++ ++ // verify that the pointer to cursor moved by the expected amount ++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendOptionTest::Packet->Dhcp6.Option + sizeof (Duid) + 4); ++ ++ // verify that the length of the packet is now the expected amount ++ ASSERT_EQ (Dhcp6AppendOptionTest::Packet->Length, OriginalLength + sizeof (Duid) + 4); ++} ++ ++//////////////////////////////////////////////////////////////////////// ++// Dhcp6AppendETOption Tests ++//////////////////////////////////////////////////////////////////////// ++ ++class Dhcp6AppendETOptionTest : public ::testing::Test { ++public: ++ UINT8 *Buffer = NULL; ++ EFI_DHCP6_PACKET *Packet; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Initialize any resources or variables ++ Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN); ++ ASSERT_NE (Buffer, (UINT8 *)NULL); ++ ++ Packet = (EFI_DHCP6_PACKET *)Buffer; ++ Packet->Size = DHCP6_PACKET_MAX_LEN; ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ if (Buffer != NULL) { ++ FreePool (Buffer); ++ } ++ } ++}; ++ ++// Test Description: ++// Attempt to append an option to a packet that is too small by a duid that is too large ++TEST_F (Dhcp6AppendETOptionTest, InvalidDataExpectBufferTooSmall) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ DHCP6_INSTANCE Instance; ++ UINT16 ElapsedTimeVal; ++ UINT16 *ElapsedTime; ++ ++ Cursor = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option; ++ ElapsedTime = &ElapsedTimeVal; ++ ++ Packet->Length = Packet->Size - 2; ++ ++ Status = Dhcp6AppendETOption ( ++ Dhcp6AppendETOptionTest::Packet, ++ &Cursor, ++ &Instance, // Instance is not used in this function ++ &ElapsedTime ++ ); ++ ++ // verify that we error out because the packet is too small for the option header ++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL); ++ ++ // reset the length ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++} ++ ++// Test Description: ++// Attempt to append an option to a packet that is large enough ++TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ DHCP6_INSTANCE Instance; ++ UINT16 ElapsedTimeVal; ++ UINT16 *ElapsedTime; ++ UINTN ExpectedSize; ++ UINTN OriginalLength; ++ ++ Cursor = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option; ++ ElapsedTime = &ElapsedTimeVal; ++ ExpectedSize = 6; ++ OriginalLength = Packet->Length; ++ ++ Status = Dhcp6AppendETOption ( ++ Dhcp6AppendETOptionTest::Packet, ++ &Cursor, ++ &Instance, // Instance is not used in this function ++ &ElapsedTime ++ ); ++ ++ // verify that the status is EFI_SUCCESS ++ ASSERT_EQ (Status, EFI_SUCCESS); ++ ++ // verify that the pointer to cursor moved by the expected amount ++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendETOptionTest::Packet->Dhcp6.Option + ExpectedSize); ++ ++ // verify that the length of the packet is now the expected amount ++ ASSERT_EQ (Dhcp6AppendETOptionTest::Packet->Length, OriginalLength + ExpectedSize); ++} ++ ++//////////////////////////////////////////////////////////////////////// ++// Dhcp6AppendIaOption Tests ++//////////////////////////////////////////////////////////////////////// ++ ++class Dhcp6AppendIaOptionTest : public ::testing::Test { ++public: ++ UINT8 *Buffer = NULL; ++ EFI_DHCP6_PACKET *Packet; ++ EFI_DHCP6_IA *Ia; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Initialize any resources or variables ++ Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN); ++ ASSERT_NE (Buffer, (UINT8 *)NULL); ++ ++ Packet = (EFI_DHCP6_PACKET *)Buffer; ++ Packet->Size = DHCP6_PACKET_MAX_LEN; ++ ++ Ia = (EFI_DHCP6_IA *)AllocateZeroPool (sizeof (EFI_DHCP6_IA) + sizeof (EFI_DHCP6_IA_ADDRESS) * 2); ++ ASSERT_NE (Ia, (EFI_DHCP6_IA *)NULL); ++ ++ CopyMem (Ia->IaAddress, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS)); ++ CopyMem (Ia->IaAddress + 1, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS)); ++ ++ Ia->IaAddressCount = 2; ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ if (Buffer != NULL) { ++ FreePool (Buffer); ++ } ++ ++ if (Ia != NULL) { ++ FreePool (Ia); ++ } ++ } ++}; ++ ++// Test Description: ++// Attempt to append an option to a packet that doesn't have enough space ++// for the option header ++TEST_F (Dhcp6AppendIaOptionTest, IaNaInvalidDataExpectBufferTooSmall) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ ++ Packet->Length = Packet->Size - 2; ++ ++ Ia->Descriptor.Type = Dhcp6OptIana; ++ Ia->Descriptor.IaId = 0x12345678; ++ ++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option; ++ ++ Status = Dhcp6AppendIaOption ( ++ Dhcp6AppendIaOptionTest::Packet, ++ &Cursor, ++ Ia, ++ 0x12345678, ++ 0x11111111, ++ Dhcp6OptIana ++ ); ++ ++ // verify that we error out because the packet is too small for the option header ++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL); ++ ++ // reset the length ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++} ++ ++// Test Description: ++// Attempt to append an option to a packet that doesn't have enough space ++// for the option header ++TEST_F (Dhcp6AppendIaOptionTest, IaTaInvalidDataExpectBufferTooSmall) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ ++ // Use up nearly all the space in the packet ++ Packet->Length = Packet->Size - 2; ++ ++ Ia->Descriptor.Type = Dhcp6OptIata; ++ Ia->Descriptor.IaId = 0x12345678; ++ ++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option; ++ ++ Status = Dhcp6AppendIaOption ( ++ Dhcp6AppendIaOptionTest::Packet, ++ &Cursor, ++ Ia, ++ 0, ++ 0, ++ Dhcp6OptIata ++ ); ++ ++ // verify that we error out because the packet is too small for the option header ++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL); ++ ++ // reset the length ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++} ++ ++TEST_F (Dhcp6AppendIaOptionTest, IaNaValidDataExpectSuccess) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ UINTN ExpectedSize; ++ UINTN OriginalLength; ++ ++ // ++ // 2 bytes for the option header type ++ // ++ ExpectedSize = 2; ++ // ++ // 2 bytes for the option header length ++ // ++ ExpectedSize += 2; ++ // ++ // 4 bytes for the IAID ++ // ++ ExpectedSize += 4; ++ // ++ // + 4 bytes for the T1 ++ // ++ ExpectedSize += 4; ++ // ++ // + 4 bytes for the T2 ++ // ++ ExpectedSize += 4; ++ // ++ // + (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2; ++ // + 2 bytes for the option header type ++ // + 2 bytes for the option header length ++ // + sizeof (EFI_DHCP6_IA_ADDRESS) for the IA Address ++ // ++ ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2; ++ ++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option; ++ ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++ OriginalLength = Packet->Length; ++ ++ Ia->Descriptor.Type = Dhcp6OptIana; ++ Ia->Descriptor.IaId = 0x12345678; ++ ++ Status = Dhcp6AppendIaOption ( ++ Dhcp6AppendIaOptionTest::Packet, ++ &Cursor, ++ Ia, ++ 0x12345678, ++ 0x12345678, ++ Dhcp6OptIana ++ ); ++ ++ // verify that the pointer to cursor moved by the expected amount ++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize); ++ ++ // verify that the length of the packet is now the expected amount ++ ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize); ++ ++ // verify that the status is EFI_SUCCESS ++ ASSERT_EQ (Status, EFI_SUCCESS); ++} ++ ++TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ UINTN ExpectedSize; ++ UINTN OriginalLength; ++ ++ // ++ // 2 bytes for the option header type ++ // ++ ExpectedSize = 2; ++ // ++ // 2 bytes for the option header length ++ // ++ ExpectedSize += 2; ++ // ++ // 4 bytes for the IAID ++ // ++ ExpectedSize += 4; ++ // ++ // + (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2; ++ // + 2 bytes for the option header type ++ // + 2 bytes for the option header length ++ // + sizeof (EFI_DHCP6_IA_ADDRESS) for the IA Address ++ // ++ ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2; ++ ++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option; ++ ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++ OriginalLength = Packet->Length; ++ ++ Ia->Descriptor.Type = Dhcp6OptIata; ++ Ia->Descriptor.IaId = 0x12345678; ++ ++ Status = Dhcp6AppendIaOption ( ++ Dhcp6AppendIaOptionTest::Packet, ++ &Cursor, ++ Ia, ++ 0, ++ 0, ++ Dhcp6OptIata ++ ); ++ ++ // verify that the pointer to cursor moved by the expected amount ++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize); ++ ++ // verify that the length of the packet is now the expected amount ++ ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize); ++ ++ // verify that the status is EFI_SUCCESS ++ ASSERT_EQ (Status, EFI_SUCCESS); ++} +diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc +index 1aeca5c5b3..20bc90b172 100644 +--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -24,6 +24,7 @@ + # + # Build HOST_APPLICATION that tests NetworkPkg + # ++ NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf + + # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests. + [LibraryClasses] +-- +2.41.0 + diff --git a/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch new file mode 100644 index 0000000..b87ded2 --- /dev/null +++ b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch @@ -0,0 +1,78 @@ +From e3f153773bd2ca13ee4869187f1711840fc8afc9 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 15 Feb 2024 11:51:09 -0500 +Subject: [PATCH 02/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [2/15] 61eaf6aac61b774c3a8ace54af8abd607651d2db + +JIRA: https://issues.redhat.com/browse/RHEL-21844 +CVE: CVE-2022-45231 +Upstream: Merged + +commit bbfee34f4188ac00371abe1389ae9c9fb989a0cd +Author: Doug Flick +Date: Fri Jan 26 05:54:48 2024 +0800 + + NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4536 + + Bug Overview: + PixieFail Bug #3 + CVE-2023-45231 + CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N + CWE-125 Out-of-bounds Read + + Out-of-bounds read when handling a ND Redirect message with truncated + options + + Change Overview: + + Adds a check to prevent truncated options from being parsed + + // + + // Cannot process truncated options. + + // Cannot process options with a length of 0 as there is no Type + field. + + // + + if (OptionLen < sizeof (IP6_OPTION_HEADER)) { + + return FALSE; + + } + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Ip6Dxe/Ip6Option.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c +index 199eea124d..8718d5d875 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Option.c ++++ b/NetworkPkg/Ip6Dxe/Ip6Option.c +@@ -137,6 +137,14 @@ Ip6IsNDOptionValid ( + return FALSE; + } + ++ // ++ // Cannot process truncated options. ++ // Cannot process options with a length of 0 as there is no Type field. ++ // ++ if (OptionLen < sizeof (IP6_OPTION_HEADER)) { ++ return FALSE; ++ } ++ + Offset = 0; + + // +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch new file mode 100644 index 0000000..35eaa36 --- /dev/null +++ b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch @@ -0,0 +1,277 @@ +From e8200dda7752d21794b2268efe9e957958ffef29 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 14 Feb 2024 12:24:44 -0500 +Subject: [PATCH 03/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit + Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [3/15] ca554677a3397423073d3bb4774f856b2329ae9c + +JIRA: https://issues.redhat.com/browse/RHEL-21844 +CVE: CVE-2022-45231 +Upstream: Merged + +commit 6f77463d72807ec7f4ed6518c3dac29a1040df9f +Author: Doug Flick +Date: Fri Jan 26 05:54:49 2024 +0800 + + NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4536 + + Validates that the patch for... + + Out-of-bounds read when handling a ND Redirect message with truncated + options + + .. has been fixed + + Tests the following function to ensure that an out of bounds read does + not occur + Ip6OptionValidation + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp | 20 +++ + .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf | 42 ++++++ + .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 129 ++++++++++++++++++ + NetworkPkg/Test/NetworkPkgHostTest.dsc | 1 + + 4 files changed, 192 insertions(+) + create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp + create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf + create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp + +diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp +new file mode 100644 +index 0000000000..6ebfd5fdfb +--- /dev/null ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp +@@ -0,0 +1,20 @@ ++/** @file ++ Acts as the main entry point for the tests for the Ip6Dxe module. ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++ ++//////////////////////////////////////////////////////////////////////////////// ++// Run the tests ++//////////////////////////////////////////////////////////////////////////////// ++int ++main ( ++ int argc, ++ char *argv[] ++ ) ++{ ++ testing::InitGoogleTest (&argc, argv); ++ return RUN_ALL_TESTS (); ++} +diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf +new file mode 100644 +index 0000000000..6e4de0745f +--- /dev/null ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf +@@ -0,0 +1,42 @@ ++## @file ++# Unit test suite for the Ip6Dxe using Google Test ++# ++# Copyright (c) Microsoft Corporation.
++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++[Defines] ++ INF_VERSION = 0x00010017 ++ BASE_NAME = Ip6DxeUnitTest ++ FILE_GUID = 4F05D17D-D3E7-4AAE-820C-576D46D2D34A ++ VERSION_STRING = 1.0 ++ MODULE_TYPE = HOST_APPLICATION ++# ++# The following information is for reference only and not required by the build tools. ++# ++# VALID_ARCHITECTURES = IA32 X64 AARCH64 ++# ++[Sources] ++ Ip6DxeGoogleTest.cpp ++ Ip6OptionGoogleTest.cpp ++ ../Ip6Option.c ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ MdeModulePkg/MdeModulePkg.dec ++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec ++ NetworkPkg/NetworkPkg.dec ++ ++[LibraryClasses] ++ GoogleTestLib ++ DebugLib ++ NetLib ++ PcdLib ++ ++[Protocols] ++ gEfiDhcp6ServiceBindingProtocolGuid ++ ++[Pcd] ++ gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType ++ ++[Guids] ++ gZeroGuid +diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp +new file mode 100644 +index 0000000000..f2cd90e1a9 +--- /dev/null ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp +@@ -0,0 +1,129 @@ ++/** @file ++ Tests for Ip6Option.c. ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++ ++extern "C" { ++ #include ++ #include ++ #include ++ #include "../Ip6Impl.h" ++ #include "../Ip6Option.h" ++} ++ ++///////////////////////////////////////////////////////////////////////// ++// Defines ++/////////////////////////////////////////////////////////////////////// ++ ++#define IP6_PREFIX_INFO_OPTION_DATA_LEN 32 ++#define OPTION_HEADER_IP6_PREFIX_DATA_LEN (sizeof (IP6_OPTION_HEADER) + IP6_PREFIX_INFO_OPTION_DATA_LEN) ++ ++//////////////////////////////////////////////////////////////////////// ++// Symbol Definitions ++// These functions are not directly under test - but required to compile ++//////////////////////////////////////////////////////////////////////// ++UINT32 mIp6Id; ++ ++EFI_STATUS ++Ip6SendIcmpError ( ++ IN IP6_SERVICE *IpSb, ++ IN NET_BUF *Packet, ++ IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL, ++ IN EFI_IPv6_ADDRESS *DestinationAddress, ++ IN UINT8 Type, ++ IN UINT8 Code, ++ IN UINT32 *Pointer OPTIONAL ++ ) ++{ ++ // .. ++ return EFI_SUCCESS; ++} ++ ++//////////////////////////////////////////////////////////////////////// ++// Ip6OptionValidation Tests ++//////////////////////////////////////////////////////////////////////// ++ ++// Define a fixture for your tests if needed ++class Ip6OptionValidationTest : public ::testing::Test { ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Initialize any resources or variables ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ } ++}; ++ ++// Test Description: ++// Null option should return false ++TEST_F (Ip6OptionValidationTest, NullOptionShouldReturnFalse) { ++ UINT8 *option = nullptr; ++ UINT16 optionLen = 10; // Provide a suitable length ++ ++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen)); ++} ++ ++// Test Description: ++// Truncated option should return false ++TEST_F (Ip6OptionValidationTest, TruncatedOptionShouldReturnFalse) { ++ UINT8 option[] = { 0x01 }; // Provide a truncated option ++ UINT16 optionLen = 1; ++ ++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen)); ++} ++ ++// Test Description: ++// Ip6OptionPrefixInfo Option with zero length should return false ++TEST_F (Ip6OptionValidationTest, OptionWithZeroLengthShouldReturnFalse) { ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = Ip6OptionPrefixInfo; ++ optionHeader.Length = 0; ++ UINT8 option[sizeof (IP6_OPTION_HEADER)]; ++ ++ CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER)); ++ UINT16 optionLen = sizeof (IP6_OPTION_HEADER); ++ ++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen)); ++} ++ ++// Test Description: ++// Ip6OptionPrefixInfo Option with valid length should return true ++TEST_F (Ip6OptionValidationTest, ValidPrefixInfoOptionShouldReturnTrue) { ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = Ip6OptionPrefixInfo; ++ optionHeader.Length = 4; // Length 4 * 8 = 32 ++ UINT8 option[OPTION_HEADER_IP6_PREFIX_DATA_LEN]; ++ ++ CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER)); ++ ++ EXPECT_TRUE (Ip6IsNDOptionValid (option, IP6_PREFIX_INFO_OPTION_DATA_LEN)); ++} ++ ++// Test Description: ++// Ip6OptionPrefixInfo Option with invalid length should return false ++TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse) { ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = Ip6OptionPrefixInfo; ++ optionHeader.Length = 3; // Length 3 * 8 = 24 (Invalid) ++ UINT8 option[sizeof (IP6_OPTION_HEADER)]; ++ ++ CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER)); ++ UINT16 optionLen = sizeof (IP6_OPTION_HEADER); ++ ++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen)); ++} +diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc +index 20bc90b172..ab7c2857b6 100644 +--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -25,6 +25,7 @@ + # Build HOST_APPLICATION that tests NetworkPkg + # + NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf ++ NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf + + # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests. + [LibraryClasses] +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch new file mode 100644 index 0000000..a7b6eb8 --- /dev/null +++ b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch @@ -0,0 +1,377 @@ +From 23b31a16bbb789f4c251b1d2f23334210a9fb545 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 15 Feb 2024 11:51:09 -0500 +Subject: [PATCH 04/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [4/15] 48c273e43a6275c7eae3223c4ffa433f4d6531a4 + +JIRA: https://issues.redhat.com/browse/RHEL-21846 +CVE: CVE-2022-45232 +Upstream: Merged + +JIRA: https://issues.redhat.com/browse/RHEL-21848 +CVE: CVE-2022-45233 +Upstream: Merged + +commit 4df0229ef992d4f2721a8508787ebf9dc81fbd6e +Author: Doug Flick +Date: Fri Jan 26 05:54:50 2024 +0800 + + NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4537 + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4538 + + Bug Details: + PixieFail Bug #4 + CVE-2023-45232 + CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H + CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop') + + Infinite loop when parsing unknown options in the Destination Options + header + + PixieFail Bug #5 + CVE-2023-45233 + CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H + CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop') + + Infinite loop when parsing a PadN option in the Destination Options + header + + Change Overview: + + Most importantly this change corrects the following incorrect math + and cleans up the code. + + > // It is a PadN option + > // + > - Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2); + > + OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length; + > + Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen); + + > case Ip6OptionSkip: + > - Offset = (UINT8)(Offset + *(Option + Offset + 1)); + > OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length; + > Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen); + + Additionally, this change also corrects incorrect math where the calling + function was calculating the HDR EXT optionLen as a uint8 instead of a + uint16 + + > - OptionLen = (UINT8)((*Option + 1) * 8 - 2); + > + OptionLen = IP6_HDR_EXT_LEN (*Option) - + IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN; + + Additionally this check adds additional logic to santize the incoming + data + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Ip6Dxe/Ip6Nd.h | 35 ++++++++++++++++ + NetworkPkg/Ip6Dxe/Ip6Option.c | 76 ++++++++++++++++++++++++++++++----- + NetworkPkg/Ip6Dxe/Ip6Option.h | 71 ++++++++++++++++++++++++++++++++ + 3 files changed, 171 insertions(+), 11 deletions(-) + +diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.h b/NetworkPkg/Ip6Dxe/Ip6Nd.h +index 860934a167..bf64e9114e 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Nd.h ++++ b/NetworkPkg/Ip6Dxe/Ip6Nd.h +@@ -56,13 +56,48 @@ VOID + VOID *Context + ); + ++// ++// Per RFC8200 Section 4.2 ++// ++// Two of the currently-defined extension headers -- the Hop-by-Hop ++// Options header and the Destination Options header -- carry a variable ++// number of type-length-value (TLV) encoded "options", of the following ++// format: ++// ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - - ++// | Option Type | Opt Data Len | Option Data ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - - ++// ++// Option Type 8-bit identifier of the type of option. ++// ++// Opt Data Len 8-bit unsigned integer. Length of the Option ++// Data field of this option, in octets. ++// ++// Option Data Variable-length field. Option-Type-specific ++// data. ++// + typedef struct _IP6_OPTION_HEADER { ++ /// ++ /// identifier of the type of option. ++ /// + UINT8 Type; ++ /// ++ /// Length of the Option Data field of this option, in octets. ++ /// + UINT8 Length; ++ /// ++ /// Option-Type-specific data. ++ /// + } IP6_OPTION_HEADER; + + STATIC_ASSERT (sizeof (IP6_OPTION_HEADER) == 2, "IP6_OPTION_HEADER is expected to be exactly 2 bytes long."); + ++#define IP6_NEXT_OPTION_OFFSET(offset, length) (offset + sizeof(IP6_OPTION_HEADER) + length) ++STATIC_ASSERT ( ++ IP6_NEXT_OPTION_OFFSET (0, 0) == 2, ++ "The next option is minimally the combined size of the option tag and length" ++ ); ++ + typedef struct _IP6_ETHE_ADDR_OPTION { + UINT8 Type; + UINT8 Length; +diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c +index 8718d5d875..fd97ce116f 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Option.c ++++ b/NetworkPkg/Ip6Dxe/Ip6Option.c +@@ -17,7 +17,8 @@ + @param[in] IpSb The IP6 service data. + @param[in] Packet The to be validated packet. + @param[in] Option The first byte of the option. +- @param[in] OptionLen The length of the whole option. ++ @param[in] OptionLen The length of all options, expressed in byte length of octets. ++ Maximum length is 2046 bytes or ((n + 1) * 8) - 2 where n is 255. + @param[in] Pointer Identifies the octet offset within + the invoking packet where the error was detected. + +@@ -31,12 +32,33 @@ Ip6IsOptionValid ( + IN IP6_SERVICE *IpSb, + IN NET_BUF *Packet, + IN UINT8 *Option, +- IN UINT8 OptionLen, ++ IN UINT16 OptionLen, + IN UINT32 Pointer + ) + { +- UINT8 Offset; +- UINT8 OptionType; ++ UINT16 Offset; ++ UINT8 OptionType; ++ UINT8 OptDataLen; ++ ++ if (Option == NULL) { ++ ASSERT (Option != NULL); ++ return FALSE; ++ } ++ ++ if ((OptionLen <= 0) || (OptionLen > IP6_MAX_EXT_DATA_LENGTH)) { ++ ASSERT (OptionLen > 0 && OptionLen <= IP6_MAX_EXT_DATA_LENGTH); ++ return FALSE; ++ } ++ ++ if (Packet == NULL) { ++ ASSERT (Packet != NULL); ++ return FALSE; ++ } ++ ++ if (IpSb == NULL) { ++ ASSERT (IpSb != NULL); ++ return FALSE; ++ } + + Offset = 0; + +@@ -54,7 +76,8 @@ Ip6IsOptionValid ( + // + // It is a PadN option + // +- Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2); ++ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length; ++ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen); + break; + case Ip6OptionRouterAlert: + // +@@ -69,7 +92,8 @@ Ip6IsOptionValid ( + // + switch (OptionType & Ip6OptionMask) { + case Ip6OptionSkip: +- Offset = (UINT8)(Offset + *(Option + Offset + 1)); ++ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length; ++ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen); + break; + case Ip6OptionDiscard: + return FALSE; +@@ -308,7 +332,7 @@ Ip6IsExtsValid ( + UINT32 Pointer; + UINT32 Offset; + UINT8 *Option; +- UINT8 OptionLen; ++ UINT16 OptionLen; + BOOLEAN Flag; + UINT8 CountD; + UINT8 CountA; +@@ -385,6 +409,36 @@ Ip6IsExtsValid ( + // Fall through + // + case IP6_DESTINATION: ++ // ++ // See https://www.rfc-editor.org/rfc/rfc2460#section-4.2 page 23 ++ // ++ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ // | Next Header | Hdr Ext Len | | ++ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ++ // | | ++ // . . ++ // . Options . ++ // . . ++ // | | ++ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ // ++ // ++ // Next Header 8-bit selector. Identifies the type of header ++ // immediately following the Destination Options ++ // header. Uses the same values as the IPv4 ++ // Protocol field [RFC-1700 et seq.]. ++ // ++ // Hdr Ext Len 8-bit unsigned integer. Length of the ++ // Destination Options header in 8-octet units, not ++ // including the first 8 octets. ++ // ++ // Options Variable-length field, of length such that the ++ // complete Destination Options header is an ++ // integer multiple of 8 octets long. Contains one ++ // or more TLV-encoded options, as described in ++ // section 4.2. ++ // ++ + if (*NextHeader == IP6_DESTINATION) { + CountD++; + } +@@ -398,7 +452,7 @@ Ip6IsExtsValid ( + + Offset++; + Option = ExtHdrs + Offset; +- OptionLen = (UINT8)((*Option + 1) * 8 - 2); ++ OptionLen = IP6_HDR_EXT_LEN (*Option) - sizeof (IP6_EXT_HDR); + Option++; + Offset++; + +@@ -430,7 +484,7 @@ Ip6IsExtsValid ( + // + // Ignore the routing header and proceed to process the next header. + // +- Offset = Offset + (RoutingHead->HeaderLen + 1) * 8; ++ Offset = Offset + IP6_HDR_EXT_LEN (RoutingHead->HeaderLen); + + if (UnFragmentLen != NULL) { + *UnFragmentLen = Offset; +@@ -441,7 +495,7 @@ Ip6IsExtsValid ( + // to the packet's source address, pointing to the unrecognized routing + // type. + // +- Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER); ++ Pointer = Offset + sizeof (IP6_EXT_HDR) + sizeof (EFI_IP6_HEADER); + if ((IpSb != NULL) && (Packet != NULL) && + !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) + { +@@ -527,7 +581,7 @@ Ip6IsExtsValid ( + // + // RFC2402, Payload length is specified in 32-bit words, minus "2". + // +- OptionLen = (UINT8)((*Option + 2) * 4); ++ OptionLen = ((UINT16)(*Option + 2) * 4); + Offset = Offset + OptionLen; + break; + +diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.h b/NetworkPkg/Ip6Dxe/Ip6Option.h +index bd8e223c8a..fb07c28f5a 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Option.h ++++ b/NetworkPkg/Ip6Dxe/Ip6Option.h +@@ -12,6 +12,77 @@ + + #define IP6_FRAGMENT_OFFSET_MASK (~0x3) + ++// ++// For more information see RFC 8200, Section 4.3, 4.4, and 4.6 ++// ++// This example format is from section 4.6 ++// This does not apply to fragment headers ++// ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | Next Header | Hdr Ext Len | | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ++// | | ++// . . ++// . Header-Specific Data . ++// . . ++// | | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// ++// Next Header 8-bit selector. Identifies the type of ++// header immediately following the extension ++// header. Uses the same values as the IPv4 ++// Protocol field [IANA-PN]. ++// ++// Hdr Ext Len 8-bit unsigned integer. Length of the ++// Destination Options header in 8-octet units, ++// not including the first 8 octets. ++ ++// ++// These defines apply to the following: ++// 1. Hop by Hop ++// 2. Routing ++// 3. Destination ++// ++typedef struct _IP6_EXT_HDR { ++ /// ++ /// The Next Header field identifies the type of header immediately ++ /// ++ UINT8 NextHeader; ++ /// ++ /// The Hdr Ext Len field specifies the length of the Hop-by-Hop Options ++ /// ++ UINT8 HdrExtLen; ++ /// ++ /// Header-Specific Data ++ /// ++} IP6_EXT_HDR; ++ ++STATIC_ASSERT ( ++ sizeof (IP6_EXT_HDR) == 2, ++ "The combined size of Next Header and Len is two 8 bit fields" ++ ); ++ ++// ++// IPv6 extension headers contain an 8-bit length field which describes the size of ++// the header. However, the length field only includes the size of the extension ++// header options, not the size of the first 8 bytes of the header. Therefore, in ++// order to calculate the full size of the extension header, we add 1 (to account ++// for the first 8 bytes omitted by the length field reporting) and then multiply ++// by 8 (since the size is represented in 8-byte units). ++// ++// a is the length field of the extension header (UINT8) ++// The result may be up to 2046 octets (UINT16) ++// ++#define IP6_HDR_EXT_LEN(a) (((UINT16)((UINT8)(a)) + 1) * 8) ++ ++// This is the maxmimum length permissible by a extension header ++// Length is UINT8 of 8 octets not including the first 8 octets ++#define IP6_MAX_EXT_DATA_LENGTH (IP6_HDR_EXT_LEN (MAX_UINT8) - sizeof(IP6_EXT_HDR)) ++STATIC_ASSERT ( ++ IP6_MAX_EXT_DATA_LENGTH == 2046, ++ "Maximum data length is ((MAX_UINT8 + 1) * 8) - 2" ++ ); ++ + typedef struct _IP6_FRAGMENT_HEADER { + UINT8 NextHeader; + UINT8 Reserved; +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch new file mode 100644 index 0000000..1add20a --- /dev/null +++ b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch @@ -0,0 +1,430 @@ +From 2bd8bc051f6394f2ab3c22649c54ecbed5d636cd Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 14 Feb 2024 20:25:29 -0500 +Subject: [PATCH 05/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit + Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [5/15] 624365d403df25927ab0514b0e25faea7376def8 + +JIRA: https://issues.redhat.com/browse/RHEL-21846 +CVE: CVE-2022-45232 +Upstream: Merged + +commit c9c87f08dd6ace36fa843424522c3558a8374cac +Author: Doug Flick +Date: Fri Jan 26 05:54:51 2024 +0800 + + NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4537 + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4538 + + Unit tests to confirm that.. + Infinite loop when parsing unknown options in the Destination Options + header + + and + + Infinite loop when parsing a PadN option in the Destination Options + header + + ... have been patched + + This patch tests the following functions: + Ip6IsOptionValid + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf | 10 +- + .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 278 ++++++++++++++++++ + .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h | 40 +++ + 3 files changed, 324 insertions(+), 4 deletions(-) + create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h + +diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf +index 6e4de0745f..ba29dbabad 100644 +--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf +@@ -1,13 +1,13 @@ + ## @file +-# Unit test suite for the Ip6Dxe using Google Test ++# Unit test suite for the Ip6DxeGoogleTest using Google Test + # + # Copyright (c) Microsoft Corporation.
+ # SPDX-License-Identifier: BSD-2-Clause-Patent + ## + [Defines] + INF_VERSION = 0x00010017 +- BASE_NAME = Ip6DxeUnitTest +- FILE_GUID = 4F05D17D-D3E7-4AAE-820C-576D46D2D34A ++ BASE_NAME = Ip6DxeGoogleTest ++ FILE_GUID = AE39981C-B7FE-41A8-A9C2-F41910477CA3 + VERSION_STRING = 1.0 + MODULE_TYPE = HOST_APPLICATION + # +@@ -16,9 +16,11 @@ + # VALID_ARCHITECTURES = IA32 X64 AARCH64 + # + [Sources] ++ ../Ip6Option.c ++ Ip6OptionGoogleTest.h + Ip6DxeGoogleTest.cpp + Ip6OptionGoogleTest.cpp +- ../Ip6Option.c ++ Ip6OptionGoogleTest.h + + [Packages] + MdePkg/MdePkg.dec +diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp +index f2cd90e1a9..29f8a4a96e 100644 +--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp +@@ -12,6 +12,7 @@ extern "C" { + #include + #include "../Ip6Impl.h" + #include "../Ip6Option.h" ++ #include "Ip6OptionGoogleTest.h" + } + + ///////////////////////////////////////////////////////////////////////// +@@ -127,3 +128,280 @@ TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse) + + EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen)); + } ++ ++//////////////////////////////////////////////////////////////////////// ++// Ip6IsOptionValid Tests ++//////////////////////////////////////////////////////////////////////// ++ ++// Define a fixture for your tests if needed ++class Ip6IsOptionValidTest : public ::testing::Test { ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Initialize any resources or variables ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ } ++}; ++ ++// Test Description ++// Verify that a NULL option is Invalid ++TEST_F (Ip6IsOptionValidTest, NullOptionShouldReturnTrue) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ IP6_SERVICE *IpSb = NULL; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, NULL, 0, 0)); ++} ++ ++// Test Description ++// Verify that an unknown option with a length of 0 and type of does not cause an infinite loop ++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength0) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = 23; // Unknown Option ++ optionHeader.Length = 0; // This will cause an infinite loop if the function is not working correctly ++ ++ // This should be a valid option even though the length is 0 ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify that an unknown option with a length of 1 and type of does not cause an infinite loop ++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength1) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = 23; // Unknown Option ++ optionHeader.Length = 1; // This will cause an infinite loop if the function is not working correctly ++ ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify that an unknown option with a length of 2 and type of does not cause an infinite loop ++TEST_F (Ip6IsOptionValidTest, VerifyIpSkipUnknownOption) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = 23; // Unknown Option ++ optionHeader.Length = 2; // Valid length for an unknown option ++ ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify that Ip6OptionPad1 is valid with a length of 0 ++TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPad1) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = Ip6OptionPad1; ++ optionHeader.Length = 0; ++ ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify that Ip6OptionPadN doesn't overflow with various lengths ++TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPadN) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = Ip6OptionPadN; ++ optionHeader.Length = 0xFF; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFE; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFD; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFC; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify an unknown option doesn't cause an infinite loop with various lengths ++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLengthAttemptOverflow) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = 23; // Unknown Option ++ optionHeader.Length = 0xFF; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFE; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFD; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFC; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify that the function supports multiple options ++TEST_F (Ip6IsOptionValidTest, MultiOptionSupport) { ++ UINT16 HdrLen; ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ UINT8 ExtHdr[1024] = { 0 }; ++ UINT8 *Cursor = ExtHdr; ++ IP6_OPTION_HEADER *Option = (IP6_OPTION_HEADER *)ExtHdr; ++ ++ // Let's start chaining options ++ ++ Option->Type = 23; // Unknown Option ++ Option->Length = 0xFC; ++ ++ Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC; ++ ++ Option = (IP6_OPTION_HEADER *)Cursor; ++ Option->Type = Ip6OptionPad1; ++ ++ Cursor += sizeof (1); ++ ++ // Type and length aren't processed, instead it just moves the pointer forward by 4 bytes ++ Option = (IP6_OPTION_HEADER *)Cursor; ++ Option->Type = Ip6OptionRouterAlert; ++ Option->Length = 4; ++ ++ Cursor += sizeof (IP6_OPTION_HEADER) + 4; ++ ++ Option = (IP6_OPTION_HEADER *)Cursor; ++ Option->Type = Ip6OptionPadN; ++ Option->Length = 0xFC; ++ ++ Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC; ++ ++ Option = (IP6_OPTION_HEADER *)Cursor; ++ Option->Type = Ip6OptionRouterAlert; ++ Option->Length = 4; ++ ++ Cursor += sizeof (IP6_OPTION_HEADER) + 4; ++ ++ // Total 524 ++ ++ HdrLen = (UINT16)(Cursor - ExtHdr); ++ ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, ExtHdr, HdrLen, 0)); ++} +diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h +new file mode 100644 +index 0000000000..0509b6ae30 +--- /dev/null ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h +@@ -0,0 +1,40 @@ ++/** @file ++ Exposes the functions needed to test the Ip6Option module. ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#ifndef IP6_OPTION_HEADER_GOOGLE_TEST_H_ ++#define IP6_OPTION_HEADER_GOOGLE_TEST_H_ ++ ++#include ++#include "../Ip6Impl.h" ++ ++/** ++ Validate the IP6 option format for both the packets we received ++ and that we will transmit. It will compute the ICMPv6 error message fields ++ if the option is malformatted. ++ ++ @param[in] IpSb The IP6 service data. ++ @param[in] Packet The to be validated packet. ++ @param[in] Option The first byte of the option. ++ @param[in] OptionLen The length of the whole option. ++ @param[in] Pointer Identifies the octet offset within ++ the invoking packet where the error was detected. ++ ++ ++ @retval TRUE The option is properly formatted. ++ @retval FALSE The option is malformatted. ++ ++**/ ++BOOLEAN ++Ip6IsOptionValid ( ++ IN IP6_SERVICE *IpSb, ++ IN NET_BUF *Packet, ++ IN UINT8 *Option, ++ IN UINT16 OptionLen, ++ IN UINT32 Pointer ++ ); ++ ++#endif // __IP6_OPTION_HEADER_GOOGLE_TEST_H__ +-- +2.39.3 + diff --git a/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch new file mode 100644 index 0000000..8e6f603 --- /dev/null +++ b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch @@ -0,0 +1,168 @@ +From 38baf93892ec464490b6fe611c23b014f574344b Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 07/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 + Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [7/15] c1baa0b2facbf0b63a90a0bfd55264af9f893098 + +JIRA: https://issues.redhat.com/browse/RHEL-21850 +CVE: CVE-2022-45234 +Upstream: Merged + +commit 1b53515d53d303166b2bbd31e2cc7f16fd0aecd7 +Author: Doug Flick +Date: Fri Jan 26 05:54:52 2024 +0800 + + NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539 + + Bug Details: + PixieFail Bug #6 + CVE-2023-45234 + CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H + CWE-119 Improper Restriction of Operations within the Bounds of + a Memory Buffer + + Buffer overflow when processing DNS Servers option in a DHCPv6 + Advertise message + + Change Overview: + + Introduces a function to cache the Dns Server and perform sanitizing + on the incoming DnsServerLen to ensure that the length is valid + + > + EFI_STATUS + > + PxeBcCacheDnsServerAddresses ( + > + IN PXEBC_PRIVATE_DATA *Private, + > + IN PXEBC_DHCP6_PACKET_CACHE *Cache6 + > + ) + + Additional code cleanup + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 71 +++++++++++++++++++++++++--- + 1 file changed, 65 insertions(+), 6 deletions(-) + +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +index 425e0cf806..2b2d372889 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +@@ -3,6 +3,7 @@ + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
++ Copyright (c) Microsoft Corporation + + SPDX-License-Identifier: BSD-2-Clause-Patent + +@@ -1312,6 +1313,65 @@ PxeBcSelectDhcp6Offer ( + } + } + ++/** ++ Cache the DHCPv6 DNS Server addresses ++ ++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA. ++ @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE. ++ ++ @retval EFI_SUCCESS Cache the DHCPv6 DNS Server address successfully. ++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. ++ @retval EFI_DEVICE_ERROR The DNS Server Address Length provided by a untrusted ++ option is not a multiple of 16 bytes (sizeof (EFI_IPv6_ADDRESS)). ++**/ ++EFI_STATUS ++PxeBcCacheDnsServerAddresses ( ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN PXEBC_DHCP6_PACKET_CACHE *Cache6 ++ ) ++{ ++ UINT16 DnsServerLen; ++ ++ DnsServerLen = NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen); ++ // ++ // Make sure that the number is nonzero ++ // ++ if (DnsServerLen == 0) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // Make sure the DnsServerlen is a multiple of EFI_IPv6_ADDRESS (16) ++ // ++ if (DnsServerLen % sizeof (EFI_IPv6_ADDRESS) != 0) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // This code is currently written to only support a single DNS Server instead ++ // of multiple such as is spec defined (RFC3646, Section 3). The proper behavior ++ // would be to allocate the full space requested, CopyMem all of the data, ++ // and then add a DnsServerCount field to Private and update additional code ++ // that depends on this. ++ // ++ // To support multiple DNS servers the `AllocationSize` would need to be changed to DnsServerLen ++ // ++ // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886 ++ // ++ Private->DnsServer = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS)); ++ if (Private->DnsServer == NULL) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ // ++ // Intentionally only copy over the first server address. ++ // To support multiple DNS servers, the `Length` would need to be changed to DnsServerLen ++ // ++ CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS)); ++ ++ return EFI_SUCCESS; ++} ++ + /** + Handle the DHCPv6 offer packet. + +@@ -1335,6 +1395,7 @@ PxeBcHandleDhcp6Offer ( + UINT32 SelectIndex; + UINT32 Index; + ++ ASSERT (Private != NULL); + ASSERT (Private->SelectIndex > 0); + SelectIndex = (UINT32)(Private->SelectIndex - 1); + ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM); +@@ -1342,15 +1403,13 @@ PxeBcHandleDhcp6Offer ( + Status = EFI_SUCCESS; + + // +- // First try to cache DNS server address if DHCP6 offer provides. ++ // First try to cache DNS server addresses if DHCP6 offer provides. + // + if (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] != NULL) { +- Private->DnsServer = AllocateZeroPool (NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen)); +- if (Private->DnsServer == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = PxeBcCacheDnsServerAddresses (Private, Cache6); ++ if (EFI_ERROR (Status)) { ++ return Status; + } +- +- CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS)); + } + + if (Cache6->OfferType == PxeOfferTypeDhcpBinl) { +-- +2.39.3 + diff --git a/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch new file mode 100644 index 0000000..aac0738 --- /dev/null +++ b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch @@ -0,0 +1,511 @@ +From fd1bc6ff10a45123b0ec7f9ae3354ad3713bc532 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 08/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 + Unit Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [8/15] f88ebc7fa79ce4fe615dd79c42fedee0a0da7a0b + +JIRA: https://issues.redhat.com/browse/RHEL-21850 +CVE: CVE-2022-45234 +Upstream: Merged + +commit 458c582685fc0e8057d2511c5a0394078d988c17 +Author: Doug Flick +Date: Fri Jan 26 05:54:53 2024 +0800 + + NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539 + + Unit tests to that the bug.. + + Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise + message + + ..has been patched + + This contains tests for the following functions: + PxeBcHandleDhcp6Offer + PxeBcCacheDnsServerAddresses + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Test/NetworkPkgHostTest.dsc | 1 + + .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 300 ++++++++++++++++++ + .../GoogleTest/PxeBcDhcp6GoogleTest.h | 50 +++ + .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp | 19 ++ + .../GoogleTest/UefiPxeBcDxeGoogleTest.inf | 48 +++ + 5 files changed, 418 insertions(+) + create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp + create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h + create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp + create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf + +diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc +index ab7c2857b6..c8a991e5c1 100644 +--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -26,6 +26,7 @@ + # + NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf + NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf ++ NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf + + # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests. + [LibraryClasses] +diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp +new file mode 100644 +index 0000000000..8260eeee50 +--- /dev/null ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp +@@ -0,0 +1,300 @@ ++/** @file ++ Host based unit test for PxeBcDhcp6.c. ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++ ++extern "C" { ++ #include ++ #include ++ #include ++ #include "../PxeBcImpl.h" ++ #include "../PxeBcDhcp6.h" ++ #include "PxeBcDhcp6GoogleTest.h" ++} ++ ++/////////////////////////////////////////////////////////////////////////////// ++// Definitions ++/////////////////////////////////////////////////////////////////////////////// ++ ++#define PACKET_SIZE (1500) ++ ++typedef struct { ++ UINT16 OptionCode; // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03) ++ UINT16 OptionLen; // The length of the option (e.g., 16 bytes) ++ UINT8 ServerId[16]; // The 16-byte DHCPv6 Server Identifier ++} DHCP6_OPTION_SERVER_ID; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/// Symbol Definitions ++/////////////////////////////////////////////////////////////////////////////// ++ ++EFI_STATUS ++MockUdpWrite ( ++ IN EFI_PXE_BASE_CODE_PROTOCOL *This, ++ IN UINT16 OpFlags, ++ IN EFI_IP_ADDRESS *DestIp, ++ IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort, ++ IN EFI_IP_ADDRESS *GatewayIp OPTIONAL, ++ IN EFI_IP_ADDRESS *SrcIp OPTIONAL, ++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL, ++ IN UINTN *HeaderSize OPTIONAL, ++ IN VOID *HeaderPtr OPTIONAL, ++ IN UINTN *BufferSize, ++ IN VOID *BufferPtr ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++MockUdpRead ( ++ IN EFI_PXE_BASE_CODE_PROTOCOL *This, ++ IN UINT16 OpFlags, ++ IN OUT EFI_IP_ADDRESS *DestIp OPTIONAL, ++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort OPTIONAL, ++ IN OUT EFI_IP_ADDRESS *SrcIp OPTIONAL, ++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL, ++ IN UINTN *HeaderSize OPTIONAL, ++ IN VOID *HeaderPtr OPTIONAL, ++ IN OUT UINTN *BufferSize, ++ IN VOID *BufferPtr ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++MockConfigure ( ++ IN EFI_UDP6_PROTOCOL *This, ++ IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++// Needed by PxeBcSupport ++EFI_STATUS ++EFIAPI ++QueueDpc ( ++ IN EFI_TPL DpcTpl, ++ IN EFI_DPC_PROCEDURE DpcProcedure, ++ IN VOID *DpcContext OPTIONAL ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++/////////////////////////////////////////////////////////////////////////////// ++// PxeBcHandleDhcp6OfferTest Tests ++/////////////////////////////////////////////////////////////////////////////// ++ ++class PxeBcHandleDhcp6OfferTest : public ::testing::Test { ++public: ++ PXEBC_PRIVATE_DATA Private = { 0 }; ++ EFI_UDP6_PROTOCOL Udp6Read; ++ EFI_PXE_BASE_CODE_MODE Mode = { 0 }; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE); ++ ++ // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL ++ // The function under test really only needs the following: ++ // UdpWrite ++ // UdpRead ++ ++ Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite; ++ Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead; ++ ++ // Need to setup EFI_UDP6_PROTOCOL ++ // The function under test really only needs the following: ++ // Configure ++ ++ Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure; ++ Private.Udp6Read = &Udp6Read; ++ ++ // Need to setup the EFI_PXE_BASE_CODE_MODE ++ Private.PxeBc.Mode = &Mode; ++ ++ // for this test it doesn't really matter what the Dhcpv6 ack is set to ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ if (Private.Dhcp6Request != NULL) { ++ FreePool (Private.Dhcp6Request); ++ } ++ ++ // Clean up any resources or variables ++ } ++}; ++ ++// Note: ++// Testing PxeBcHandleDhcp6Offer() is difficult because it depends on a ++// properly setup Private structure. Attempting to properly test this function ++// without a signficant refactor is a fools errand. Instead, we will test ++// that we can prevent an overflow in the function. ++TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) { ++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL; ++ EFI_DHCP6_PACKET_OPTION Option = { 0 }; ++ ++ Private.SelectIndex = 1; // SelectIndex is 1-based ++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6; ++ ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option; ++ // Setup the DHCPv6 offer packet ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337); ++ ++ ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR); ++} ++ ++class PxeBcCacheDnsServerAddressesTest : public ::testing::Test { ++public: ++ PXEBC_PRIVATE_DATA Private = { 0 }; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ } ++}; ++ ++// Test Description ++// Test that we cache the DNS server address from the DHCPv6 offer packet ++TEST_F (PxeBcCacheDnsServerAddressesTest, BasicUsageTest) { ++ UINT8 SearchPattern[16] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF }; ++ EFI_DHCP6_PACKET_OPTION *Option; ++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL; ++ ++ Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern)); ++ ASSERT_NE (Option, nullptr); ++ ++ Option->OpCode = DHCP6_OPT_SERVER_ID; ++ Option->OpLen = NTOHS (sizeof (SearchPattern)); ++ CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern)); ++ ++ Private.SelectIndex = 1; // SelectIndex is 1-based ++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = Option; ++ ++ Private.DnsServer = nullptr; ++ ++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS); ++ ASSERT_NE (Private.DnsServer, nullptr); ++ ASSERT_EQ (CompareMem (Private.DnsServer, SearchPattern, sizeof (SearchPattern)), 0); ++ ++ if (Private.DnsServer) { ++ FreePool (Private.DnsServer); ++ } ++ ++ if (Option) { ++ FreePool (Option); ++ } ++} ++// Test Description ++// Test that we can prevent an overflow in the function ++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptOverflowTest) { ++ EFI_DHCP6_PACKET_OPTION Option = { 0 }; ++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL; ++ ++ Private.SelectIndex = 1; // SelectIndex is 1-based ++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option; ++ // Setup the DHCPv6 offer packet ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337); ++ ++ Private.DnsServer = NULL; ++ ++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR); ++ ASSERT_EQ (Private.DnsServer, nullptr); ++ ++ if (Private.DnsServer) { ++ FreePool (Private.DnsServer); ++ } ++} ++ ++// Test Description ++// Test that we can prevent an underflow in the function ++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptUnderflowTest) { ++ EFI_DHCP6_PACKET_OPTION Option = { 0 }; ++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL; ++ ++ Private.SelectIndex = 1; // SelectIndex is 1-based ++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option; ++ // Setup the DHCPv6 offer packet ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (2); ++ ++ Private.DnsServer = NULL; ++ ++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR); ++ ASSERT_EQ (Private.DnsServer, nullptr); ++ ++ if (Private.DnsServer) { ++ FreePool (Private.DnsServer); ++ } ++} ++ ++// Test Description ++// Test that we can handle recursive dns (multiple dns entries) ++TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) { ++ EFI_DHCP6_PACKET_OPTION Option = { 0 }; ++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL; ++ ++ Private.SelectIndex = 1; // SelectIndex is 1-based ++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option; ++ // Setup the DHCPv6 offer packet ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID; ++ ++ EFI_IPv6_ADDRESS addresses[2] = { ++ // 2001:db8:85a3::8a2e:370:7334 ++ { 0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34 }, ++ // fe80::d478:91c3:ecd7:4ff9 ++ { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x78, 0x91, 0xc3, 0xec, 0xd7, 0x4f, 0xf9 } ++ }; ++ ++ CopyMem (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof (addresses)); ++ ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (sizeof (addresses)); ++ ++ Private.DnsServer = NULL; ++ ++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS); ++ ++ ASSERT_NE (Private.DnsServer, nullptr); ++ ++ // ++ // This is expected to fail until DnsServer supports multiple DNS servers ++ // ++ // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886 ++ // ++ // Disabling: ++ // ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0); ++ ++ if (Private.DnsServer) { ++ FreePool (Private.DnsServer); ++ } ++} +diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h +new file mode 100644 +index 0000000000..b17c314791 +--- /dev/null ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h +@@ -0,0 +1,50 @@ ++/** @file ++ This file exposes the internal interfaces which may be unit tested ++ for the PxeBcDhcp6Dxe driver. ++ ++ Copyright (c) Microsoft Corporation.
++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#ifndef PXE_BC_DHCP6_GOOGLE_TEST_H_ ++#define PXE_BC_DHCP6_GOOGLE_TEST_H_ ++ ++// ++// Minimal includes needed to compile ++// ++#include ++#include "../PxeBcImpl.h" ++ ++/** ++ Handle the DHCPv6 offer packet. ++ ++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA. ++ ++ @retval EFI_SUCCESS Handled the DHCPv6 offer packet successfully. ++ @retval EFI_NO_RESPONSE No response to the following request packet. ++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. ++ @retval EFI_BUFFER_TOO_SMALL Can't cache the offer pacet. ++ ++**/ ++EFI_STATUS ++PxeBcHandleDhcp6Offer ( ++ IN PXEBC_PRIVATE_DATA *Private ++ ); ++ ++/** ++ Cache the DHCPv6 Server address ++ ++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA. ++ @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE. ++ ++ @retval EFI_SUCCESS Cache the DHCPv6 Server address successfully. ++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. ++ @retval EFI_DEVICE_ERROR Failed to cache the DHCPv6 Server address. ++**/ ++EFI_STATUS ++PxeBcCacheDnsServerAddresses ( ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN PXEBC_DHCP6_PACKET_CACHE *Cache6 ++ ); ++ ++#endif // PXE_BC_DHCP6_GOOGLE_TEST_H_ +diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp +new file mode 100644 +index 0000000000..cc4fdf525b +--- /dev/null ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp +@@ -0,0 +1,19 @@ ++/** @file ++ Acts as the main entry point for the tests for the UefiPxeBcDxe module. ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++ ++//////////////////////////////////////////////////////////////////////////////// ++// Run the tests ++//////////////////////////////////////////////////////////////////////////////// ++int ++main ( ++ int argc, ++ char *argv[] ++ ) ++{ ++ testing::InitGoogleTest (&argc, argv); ++ return RUN_ALL_TESTS (); ++} +diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf +new file mode 100644 +index 0000000000..301dcdf611 +--- /dev/null ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf +@@ -0,0 +1,48 @@ ++## @file ++# Unit test suite for the UefiPxeBcDxe using Google Test ++# ++# Copyright (c) Microsoft Corporation.
++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++[Defines] ++INF_VERSION = 0x00010005 ++BASE_NAME = UefiPxeBcDxeGoogleTest ++FILE_GUID = 77D45C64-EC1E-4174-887B-886E89FD1EDF ++MODULE_TYPE = HOST_APPLICATION ++VERSION_STRING = 1.0 ++ ++# ++# The following information is for reference only and not required by the build tools. ++# ++# VALID_ARCHITECTURES = IA32 X64 ++# ++ ++[Sources] ++ UefiPxeBcDxeGoogleTest.cpp ++ PxeBcDhcp6GoogleTest.cpp ++ PxeBcDhcp6GoogleTest.h ++ ../PxeBcDhcp6.c ++ ../PxeBcSupport.c ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ MdeModulePkg/MdeModulePkg.dec ++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec ++ NetworkPkg/NetworkPkg.dec ++ ++[LibraryClasses] ++ GoogleTestLib ++ DebugLib ++ NetLib ++ PcdLib ++ ++[Protocols] ++ gEfiDhcp6ServiceBindingProtocolGuid ++ gEfiDns6ServiceBindingProtocolGuid ++ gEfiDns6ProtocolGuid ++ ++[Pcd] ++ gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType ++ ++[Guids] ++ gZeroGuid +-- +2.39.3 + diff --git a/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch new file mode 100644 index 0000000..beaa36f --- /dev/null +++ b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch @@ -0,0 +1,257 @@ +From 0016db53099ba979617f376fe1104fefada4fa29 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 09/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 + Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [9/15] c48c060b87761537ee526e1f8a9e5993eb1a0381 + +JIRA: https://issues.redhat.com/browse/RHEL-21852 +CVE: CVE-2022-45235 +Upstream: Merged + +commit fac297724e6cc343430cd0104e55cd7a96d1151e +Author: Doug Flick +Date: Fri Jan 26 05:54:55 2024 +0800 + + NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4540 + + Bug Details: + PixieFail Bug #7 + CVE-2023-45235 + CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H + CWE-119 Improper Restriction of Operations within the Bounds of + a Memory Buffer + + Buffer overflow when handling Server ID option from a DHCPv6 proxy + Advertise message + + Change Overview: + + Performs two checks + + 1. Checks that the length of the duid is accurate + > + // + > + // Check that the minimum and maximum requirements are met + > + // + > + if ((OpLen < PXEBC_MIN_SIZE_OF_DUID) || + (OpLen > PXEBC_MAX_SIZE_OF_DUID)) { + > + Status = EFI_INVALID_PARAMETER; + > + goto ON_ERROR; + > + } + + 2. Ensures that the amount of data written to the buffer is tracked and + never exceeds that + > + // + > + // Check that the option length is valid. + > + // + > + if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN) + > DiscoverLenNeeded) { + > + Status = EFI_OUT_OF_RESOURCES; + > + goto ON_ERROR; + > + } + + Additional code clean up and fix for memory leak in case Option was NULL + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 77 ++++++++++++++++++++++------ + NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h | 17 ++++++ + 2 files changed, 78 insertions(+), 16 deletions(-) + +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +index 2b2d372889..7fd1281c11 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +@@ -887,6 +887,7 @@ PxeBcRequestBootService ( + EFI_STATUS Status; + EFI_DHCP6_PACKET *IndexOffer; + UINT8 *Option; ++ UINTN DiscoverLenNeeded; + + PxeBc = &Private->PxeBc; + Request = Private->Dhcp6Request; +@@ -899,7 +900,8 @@ PxeBcRequestBootService ( + return EFI_DEVICE_ERROR; + } + +- Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET)); ++ DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET); ++ Discover = AllocateZeroPool (DiscoverLenNeeded); + if (Discover == NULL) { + return EFI_OUT_OF_RESOURCES; + } +@@ -924,16 +926,34 @@ PxeBcRequestBootService ( + DHCP6_OPT_SERVER_ID + ); + if (Option == NULL) { +- return EFI_NOT_FOUND; ++ Status = EFI_NOT_FOUND; ++ goto ON_ERROR; + } + + // + // Add Server ID Option. + // + OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)Option)->OpLen); +- CopyMem (DiscoverOpt, Option, OpLen + 4); +- DiscoverOpt += (OpLen + 4); +- DiscoverLen += (OpLen + 4); ++ ++ // ++ // Check that the minimum and maximum requirements are met ++ // ++ if ((OpLen < PXEBC_MIN_SIZE_OF_DUID) || (OpLen > PXEBC_MAX_SIZE_OF_DUID)) { ++ Status = EFI_INVALID_PARAMETER; ++ goto ON_ERROR; ++ } ++ ++ // ++ // Check that the option length is valid. ++ // ++ if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN) > DiscoverLenNeeded) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; ++ } ++ ++ CopyMem (DiscoverOpt, Option, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + + while (RequestLen < Request->Length) { +@@ -944,16 +964,24 @@ PxeBcRequestBootService ( + (OpCode != DHCP6_OPT_SERVER_ID) + ) + { ++ // ++ // Check that the option length is valid. ++ // ++ if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; ++ } ++ + // + // Copy all the options except IA option and Server ID + // +- CopyMem (DiscoverOpt, RequestOpt, OpLen + 4); +- DiscoverOpt += (OpLen + 4); +- DiscoverLen += (OpLen + 4); ++ CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + +- RequestOpt += (OpLen + 4); +- RequestLen += (OpLen + 4); ++ RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + + // +@@ -2154,6 +2182,7 @@ PxeBcDhcp6Discover ( + UINT16 OpLen; + UINT32 Xid; + EFI_STATUS Status; ++ UINTN DiscoverLenNeeded; + + PxeBc = &Private->PxeBc; + Mode = PxeBc->Mode; +@@ -2169,7 +2198,8 @@ PxeBcDhcp6Discover ( + return EFI_DEVICE_ERROR; + } + +- Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET)); ++ DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET); ++ Discover = AllocateZeroPool (DiscoverLenNeeded); + if (Discover == NULL) { + return EFI_OUT_OF_RESOURCES; + } +@@ -2185,22 +2215,37 @@ PxeBcDhcp6Discover ( + DiscoverLen = sizeof (EFI_DHCP6_HEADER); + RequestLen = DiscoverLen; + ++ // ++ // The request packet is generated by the UEFI network stack. In the DHCP4 DORA and DHCP6 SARR sequence, ++ // the first (discover in DHCP4 and solicit in DHCP6) and third (request in both DHCP4 and DHCP6) are ++ // generated by the DHCP client (the UEFI network stack in this case). By the time this function executes, ++ // the DHCP sequence already has been executed once (see UEFI Specification Figures 24.2 and 24.3), with ++ // Private->Dhcp6Request being a cached copy of the DHCP6 request packet that UEFI network stack previously ++ // generated and sent. ++ // ++ // Therefore while this code looks like it could overflow, in practice it's not possible. ++ // + while (RequestLen < Request->Length) { + OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode); + OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen); + if ((OpCode != EFI_DHCP6_IA_TYPE_NA) && + (OpCode != EFI_DHCP6_IA_TYPE_TA)) + { ++ if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; ++ } ++ + // + // Copy all the options except IA option. + // +- CopyMem (DiscoverOpt, RequestOpt, OpLen + 4); +- DiscoverOpt += (OpLen + 4); +- DiscoverLen += (OpLen + 4); ++ CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + +- RequestOpt += (OpLen + 4); +- RequestLen += (OpLen + 4); ++ RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + + Status = PxeBc->UdpWrite ( +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h +index ae4be775e8..47eb8cc0c0 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h +@@ -35,6 +35,23 @@ + #define PXEBC_ADDR_START_DELIMITER '[' + #define PXEBC_ADDR_END_DELIMITER ']' + ++// ++// A DUID consists of a 2-octet type code represented in network byte ++// order, followed by a variable number of octets that make up the ++// actual identifier. The length of the DUID (not including the type ++// code) is at least 1 octet and at most 128 octets. ++// ++#define PXEBC_MIN_SIZE_OF_DUID (sizeof(UINT16) + 1) ++#define PXEBC_MAX_SIZE_OF_DUID (sizeof(UINT16) + 128) ++ ++// ++// This define represents the combineds code and length field from ++// https://datatracker.ietf.org/doc/html/rfc3315#section-22.1 ++// ++#define PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN \ ++ (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpCode) + \ ++ sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpLen)) ++ + #define GET_NEXT_DHCP6_OPTION(Opt) \ + (EFI_DHCP6_PACKET_OPTION *) ((UINT8 *) (Opt) + \ + sizeof (EFI_DHCP6_PACKET_OPTION) + (NTOHS ((Opt)->OpLen)) - 1) +-- +2.39.3 + diff --git a/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch new file mode 100644 index 0000000..8380050 --- /dev/null +++ b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch @@ -0,0 +1,409 @@ +From 80b34c0f56228353c174f9ff739d0755c62d76cf Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 10/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 + Unit Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 56: Pixiefail issues in NetworkPkg package +RH-Jira: RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [10/15] 5dbf3f771506ff9a0c28827c568d04e825572658 + +JIRA: https://issues.redhat.com/browse/RHEL-21852 +CVE: CVE-2022-45235 +Upstream: Merged + +commit ff2986358f75d8f58ef08a66fe673539c9c48f41 +Author: Doug Flick +Date: Fri Jan 26 05:54:56 2024 +0800 + + NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4540 + + Unit tests to confirm that the bug.. + + Buffer overflow when handling Server ID option from a DHCPv6 proxy + Advertise message + + ..has been patched. + + This patch contains unit tests for the following functions: + PxeBcRequestBootService + PxeBcDhcp6Discover + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Test/NetworkPkgHostTest.dsc | 5 +- + .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 278 +++++++++++++++++- + .../GoogleTest/PxeBcDhcp6GoogleTest.h | 18 ++ + 3 files changed, 298 insertions(+), 3 deletions(-) + +diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc +index c8a991e5c1..1010a80a15 100644 +--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -26,7 +26,10 @@ + # + NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf + NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf +- NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf ++ NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf { ++ ++ UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf ++ } + + # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests. + [LibraryClasses] +diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp +index 8260eeee50..bd423ebadf 100644 +--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp +@@ -4,7 +4,9 @@ + Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + **/ +-#include ++#include ++#include ++#include + + extern "C" { + #include +@@ -19,7 +21,8 @@ extern "C" { + // Definitions + /////////////////////////////////////////////////////////////////////////////// + +-#define PACKET_SIZE (1500) ++#define PACKET_SIZE (1500) ++#define REQUEST_OPTION_LENGTH (120) + + typedef struct { + UINT16 OptionCode; // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03) +@@ -76,6 +79,26 @@ MockConfigure ( + } + + // Needed by PxeBcSupport ++EFI_STATUS ++PxeBcDns6 ( ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN CHAR16 *HostName, ++ OUT EFI_IPv6_ADDRESS *IpAddress ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++UINT32 ++PxeBcBuildDhcp6Options ( ++ IN PXEBC_PRIVATE_DATA *Private, ++ OUT EFI_DHCP6_PACKET_OPTION **OptList, ++ IN UINT8 *Buffer ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ + EFI_STATUS + EFIAPI + QueueDpc ( +@@ -159,6 +182,10 @@ TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) { + ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR); + } + ++/////////////////////////////////////////////////////////////////////////////// ++// PxeBcCacheDnsServerAddresses Tests ++/////////////////////////////////////////////////////////////////////////////// ++ + class PxeBcCacheDnsServerAddressesTest : public ::testing::Test { + public: + PXEBC_PRIVATE_DATA Private = { 0 }; +@@ -298,3 +325,250 @@ TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) { + FreePool (Private.DnsServer); + } + } ++ ++/////////////////////////////////////////////////////////////////////////////// ++// PxeBcRequestBootServiceTest Test Cases ++/////////////////////////////////////////////////////////////////////////////// ++ ++class PxeBcRequestBootServiceTest : public ::testing::Test { ++public: ++ PXEBC_PRIVATE_DATA Private = { 0 }; ++ EFI_UDP6_PROTOCOL Udp6Read; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE); ++ ++ // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL ++ // The function under test really only needs the following: ++ // UdpWrite ++ // UdpRead ++ ++ Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite; ++ Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead; ++ ++ // Need to setup EFI_UDP6_PROTOCOL ++ // The function under test really only needs the following: ++ // Configure ++ ++ Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure; ++ Private.Udp6Read = &Udp6Read; ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ if (Private.Dhcp6Request != NULL) { ++ FreePool (Private.Dhcp6Request); ++ } ++ ++ // Clean up any resources or variables ++ } ++}; ++ ++TEST_F (PxeBcRequestBootServiceTest, ServerDiscoverBasicUsageTest) { ++ PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl; ++ ++ DHCP6_OPTION_SERVER_ID Server = { 0 }; ++ ++ Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID); ++ Server.OptionLen = HTONS (16); // valid length ++ UINT8 Index = 0; ++ ++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer; ++ ++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option); ++ ++ CopyMem (Cursor, &Server, sizeof (Server)); ++ Cursor += sizeof (Server); ++ ++ // Update the packet length ++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet); ++ Packet->Size = PACKET_SIZE; ++ ++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS); ++} ++ ++TEST_F (PxeBcRequestBootServiceTest, AttemptDiscoverOverFlowExpectFailure) { ++ PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl; ++ ++ DHCP6_OPTION_SERVER_ID Server = { 0 }; ++ ++ Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID); ++ Server.OptionLen = HTONS (1500); // This length would overflow without a check ++ UINT8 Index = 0; ++ ++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer; ++ ++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option); ++ ++ CopyMem (Cursor, &Server, sizeof (Server)); ++ Cursor += sizeof (Server); ++ ++ // Update the packet length ++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet); ++ Packet->Size = PACKET_SIZE; ++ ++ // This is going to be stopped by the duid overflow check ++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_INVALID_PARAMETER); ++} ++ ++TEST_F (PxeBcRequestBootServiceTest, RequestBasicUsageTest) { ++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter ++ ++ RequestOpt.OpCode = HTONS (0x1337); ++ RequestOpt.OpLen = 0; // valid length ++ ++ UINT8 Index = 0; ++ ++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index]; ++ ++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option); ++ ++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt)); ++ Cursor += sizeof (RequestOpt); ++ ++ // Update the packet length ++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet); ++ Packet->Size = PACKET_SIZE; ++ ++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS); ++} ++ ++TEST_F (PxeBcRequestBootServiceTest, AttemptRequestOverFlowExpectFailure) { ++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter ++ ++ RequestOpt.OpCode = HTONS (0x1337); ++ RequestOpt.OpLen = 1500; // this length would overflow without a check ++ ++ UINT8 Index = 0; ++ ++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index]; ++ ++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option); ++ ++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt)); ++ Cursor += sizeof (RequestOpt); ++ ++ // Update the packet length ++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet); ++ Packet->Size = PACKET_SIZE; ++ ++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_OUT_OF_RESOURCES); ++} ++ ++/////////////////////////////////////////////////////////////////////////////// ++// PxeBcDhcp6Discover Test ++/////////////////////////////////////////////////////////////////////////////// ++ ++class PxeBcDhcp6DiscoverTest : public ::testing::Test { ++public: ++ PXEBC_PRIVATE_DATA Private = { 0 }; ++ EFI_UDP6_PROTOCOL Udp6Read; ++ ++protected: ++ MockUefiRuntimeServicesTableLib RtServicesMock; ++ ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE); ++ ++ // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL ++ // The function under test really only needs the following: ++ // UdpWrite ++ // UdpRead ++ ++ Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite; ++ Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead; ++ ++ // Need to setup EFI_UDP6_PROTOCOL ++ // The function under test really only needs the following: ++ // Configure ++ ++ Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure; ++ Private.Udp6Read = &Udp6Read; ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ if (Private.Dhcp6Request != NULL) { ++ FreePool (Private.Dhcp6Request); ++ } ++ ++ // Clean up any resources or variables ++ } ++}; ++ ++// Test Description ++// This will cause an overflow by an untrusted packet during the option parsing ++TEST_F (PxeBcDhcp6DiscoverTest, BasicOverflowTest) { ++ EFI_IPv6_ADDRESS DestIp = { 0 }; ++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter ++ ++ RequestOpt.OpCode = HTONS (0x1337); ++ RequestOpt.OpLen = HTONS (0xFFFF); // overflow ++ ++ UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option); ++ ++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt)); ++ Cursor += sizeof (RequestOpt); ++ ++ Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request); ++ ++ EXPECT_CALL (RtServicesMock, gRT_GetTime) ++ .WillOnce (::testing::Return (0)); ++ ++ ASSERT_EQ ( ++ PxeBcDhcp6Discover ( ++ &(PxeBcDhcp6DiscoverTest::Private), ++ 0, ++ NULL, ++ FALSE, ++ (EFI_IP_ADDRESS *)&DestIp ++ ), ++ EFI_OUT_OF_RESOURCES ++ ); ++} ++ ++// Test Description ++// This will test that we can handle a packet with a valid option length ++TEST_F (PxeBcDhcp6DiscoverTest, BasicUsageTest) { ++ EFI_IPv6_ADDRESS DestIp = { 0 }; ++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter ++ ++ RequestOpt.OpCode = HTONS (0x1337); ++ RequestOpt.OpLen = HTONS (0x30); ++ ++ UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option); ++ ++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt)); ++ Cursor += sizeof (RequestOpt); ++ ++ Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request); ++ ++ EXPECT_CALL (RtServicesMock, gRT_GetTime) ++ .WillOnce (::testing::Return (0)); ++ ++ ASSERT_EQ ( ++ PxeBcDhcp6Discover ( ++ &(PxeBcDhcp6DiscoverTest::Private), ++ 0, ++ NULL, ++ FALSE, ++ (EFI_IP_ADDRESS *)&DestIp ++ ), ++ EFI_SUCCESS ++ ); ++} +diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h +index b17c314791..0d825e4425 100644 +--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h +@@ -47,4 +47,22 @@ PxeBcCacheDnsServerAddresses ( + IN PXEBC_DHCP6_PACKET_CACHE *Cache6 + ); + ++/** ++ Build and send out the request packet for the bootfile, and parse the reply. ++ ++ @param[in] Private The pointer to PxeBc private data. ++ @param[in] Index PxeBc option boot item type. ++ ++ @retval EFI_SUCCESS Successfully discovered the boot file. ++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. ++ @retval EFI_NOT_FOUND Can't get the PXE reply packet. ++ @retval Others Failed to discover the boot file. ++ ++**/ ++EFI_STATUS ++PxeBcRequestBootService ( ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN UINT32 Index ++ ); ++ + #endif // PXE_BC_DHCP6_GOOGLE_TEST_H_ +-- +2.39.3 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch b/edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch new file mode 100644 index 0000000..adf5b38 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch @@ -0,0 +1,47 @@ +From f2aeff31924f6d070d7f8b87550dc6d9820531ad Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:04 +0100 +Subject: [PATCH 15/18] OvmfPkg/VirtNorFlashDxe: ValidateFvHeader: unwritten + state is EOL too + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [17/20] 37220c700ea816c815e0612031e10b7d466b71a2 + +It is possible to find variable entries with State being 0xff, i.e. not +updated since flash block erase. This indicates the variable driver +could not complete the header write while appending a new entry, and +therefore State was not set to VAR_HEADER_VALID_ONLY. + +This can only happen at the end of the variable list, so treat this as +additional "end of variable list" condition. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-Id: <20240116171105.37831-6-kraxel@redhat.com> +(cherry picked from commit 735d0a5e2e25c1577bf9bea7826da937ca38169d) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +index acc4a413ee..f8e71f88c1 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +@@ -302,6 +302,11 @@ ValidateFvHeader ( + break; + } + ++ if (VarHeader->State == 0xff) { ++ DEBUG ((DEBUG_INFO, "%a: end of var list (unwritten state)\n", __func__)); ++ break; ++ } ++ + VarName = NULL; + switch (VarHeader->State) { + // usage: State = VAR_HEADER_VALID_ONLY +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch b/edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch new file mode 100644 index 0000000..4fc7c3e --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch @@ -0,0 +1,73 @@ +From 00d9e2d6cb03afeef5a1110d6f1fae1389a06f7a Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:02 +0100 +Subject: [PATCH 13/18] OvmfPkg/VirtNorFlashDxe: add a loop for + NorFlashWriteBuffer calls. + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [15/20] 72004a196ea61d627ab528573db657dd7db16de2 + +Replace the two NorFlashWriteBuffer() calls with a loop containing a +single NorFlashWriteBuffer() call. + +With the changes in place the code is able to handle updates larger +than two P30_MAX_BUFFER_SIZE_IN_BYTES blocks, even though the patch +does not actually change the size limit. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-Id: <20240116171105.37831-4-kraxel@redhat.com> +(cherry picked from commit 28ffd726894f11a587a6ac7f71a4c4af341e24d2) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 88a4d2c23f..3d1343b381 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -521,6 +521,7 @@ NorFlashWriteSingleBlock ( + UINTN BlockAddress; + UINT8 *OrigData; + UINTN Start, End; ++ UINT32 Index, Count; + + DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer)); + +@@ -621,23 +622,17 @@ NorFlashWriteSingleBlock ( + goto Exit; + } + +- Status = NorFlashWriteBuffer ( +- Instance, +- BlockAddress + Start, +- P30_MAX_BUFFER_SIZE_IN_BYTES, +- Instance->ShadowBuffer +- ); +- if (EFI_ERROR (Status)) { +- goto Exit; +- } +- +- if ((End - Start) > P30_MAX_BUFFER_SIZE_IN_BYTES) { ++ Count = (End - Start) / P30_MAX_BUFFER_SIZE_IN_BYTES; ++ for (Index = 0; Index < Count; Index++) { + Status = NorFlashWriteBuffer ( + Instance, +- BlockAddress + Start + P30_MAX_BUFFER_SIZE_IN_BYTES, ++ BlockAddress + Start + Index * P30_MAX_BUFFER_SIZE_IN_BYTES, + P30_MAX_BUFFER_SIZE_IN_BYTES, +- Instance->ShadowBuffer + P30_MAX_BUFFER_SIZE_IN_BYTES ++ Instance->ShadowBuffer + Index * P30_MAX_BUFFER_SIZE_IN_BYTES + ); ++ if (EFI_ERROR (Status)) { ++ goto Exit; ++ } + } + + Exit: +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch b/edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch new file mode 100644 index 0000000..2494899 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch @@ -0,0 +1,55 @@ +From e8150ee7fdf1421d2e2801c901e0196496ef599e Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:00 +0100 +Subject: [PATCH 11/18] OvmfPkg/VirtNorFlashDxe: add casts to UINTN and UINT32 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [13/20] fa695acadb9d693242b5221d2bc1958b929718e7 + +This is needed to avoid bit operations being applied to signed integers. + +Suggested-by: László Érsek +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-Id: <20240116171105.37831-2-kraxel@redhat.com> +(cherry picked from commit 0395045ae307c43a41f72ca9a8bf4eb8f16b2fe0) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 2 +- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 1afd60ce66..7f4743b003 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -581,7 +581,7 @@ NorFlashWriteSingleBlock ( + // contents, while checking whether the old version had any bits cleared + // that we want to set. In that case, we will need to erase the block first. + for (CurOffset = 0; CurOffset < *NumBytes; CurOffset++) { +- if (~OrigData[CurOffset] & Buffer[CurOffset]) { ++ if (~(UINT32)OrigData[CurOffset] & (UINT32)Buffer[CurOffset]) { + goto DoErase; + } + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +index b7f5d208b2..455eafacc2 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +@@ -61,7 +61,7 @@ + #define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128) + #define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4)) + #define MAX_BUFFERED_PROG_ITERATIONS 10000000 +-#define BOUNDARY_OF_32_WORDS 0x7F ++#define BOUNDARY_OF_32_WORDS ((UINTN)0x7F) + + // CFI Addresses + #define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10 +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch b/edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch new file mode 100644 index 0000000..f30a257 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch @@ -0,0 +1,65 @@ +From 0193a89b0db837da31301bc1edb8382927842978 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:03 +0100 +Subject: [PATCH 14/18] OvmfPkg/VirtNorFlashDxe: allow larger writes without + block erase + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [16/20] 27ac63b90eb5e6fdc00cbc5a9105c3178ee559cd + +Raise the limit for writes without block erase from two to four +P30_MAX_BUFFER_SIZE_IN_BYTES blocks. With this in place almost all efi +variable updates are handled without block erase. With the old limit +some variable updates (with device paths) took the block erase code +path. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-Id: <20240116171105.37831-5-kraxel@redhat.com> +(cherry picked from commit b25733c97442513890ae6bb8e10fd340f13844a7) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 3d1343b381..3d1d20daa1 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -550,13 +550,15 @@ NorFlashWriteSingleBlock ( + return EFI_BAD_BUFFER_SIZE; + } + +- // Pick P30_MAX_BUFFER_SIZE_IN_BYTES (== 128 bytes) as a good start for word +- // operations as opposed to erasing the block and writing the data regardless +- // if an erase is really needed. It looks like most individual NV variable +- // writes are smaller than 128 bytes. +- // To avoid pathological cases were a 2 byte write is disregarded because it +- // occurs right at a 128 byte buffered write alignment boundary, permit up to +- // twice the max buffer size, and perform two writes if needed. ++ // Pick 4 * P30_MAX_BUFFER_SIZE_IN_BYTES (== 512 bytes) as a good ++ // start for word operations as opposed to erasing the block and ++ // writing the data regardless if an erase is really needed. ++ // ++ // Many NV variable updates are small enough for a a single ++ // P30_MAX_BUFFER_SIZE_IN_BYTES block write. In case the update is ++ // larger than a single block, or the update crosses a ++ // P30_MAX_BUFFER_SIZE_IN_BYTES boundary (as shown in the diagram ++ // below), or both, we might have to write two or more blocks. + // + // 0 128 256 + // [----------------|----------------] +@@ -578,7 +580,7 @@ NorFlashWriteSingleBlock ( + Start = Offset & ~BOUNDARY_OF_32_WORDS; + End = ALIGN_VALUE (Offset + *NumBytes, P30_MAX_BUFFER_SIZE_IN_BYTES); + +- if ((End - Start) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) { ++ if ((End - Start) <= (4 * P30_MAX_BUFFER_SIZE_IN_BYTES)) { + // Check to see if we need to erase before programming the data into NOR. + // If the destination bits are only changing from 1s to 0s we can just write. + // After a block is erased all bits in the block is set to 1. +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-avoid-array-mode-switch-afte.patch b/edk2-OvmfPkg-VirtNorFlashDxe-avoid-array-mode-switch-afte.patch new file mode 100644 index 0000000..fc64a93 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-avoid-array-mode-switch-afte.patch @@ -0,0 +1,89 @@ +From 20ba071dabad6b0f5663083a017799b7a6e684c5 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 24 Oct 2022 17:34:09 +0200 +Subject: [PATCH 05/18] OvmfPkg/VirtNorFlashDxe: avoid array mode switch after + each word write + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [7/20] 274f2ed71a6d5d3f6497129ee3c62f494cc2f067 + +NorFlashWriteSingleWord() switches into programming mode and back into +array mode for every single word that it writes. Under KVM, this +involves tearing down the read-only memslot, and setting it up again, +which is costly and unnecessary. + +Instead, move the array mode switch into the callers, and only make the +switch when the writing is done. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Sunil V L +(cherry picked from commit ca01e6216a8d1a26c69018e216d1dc3f88a819a4) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 12 +++--------- + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 3 +++ + 2 files changed, 6 insertions(+), 9 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index f41d9d372f..0a5c5d48c7 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -205,9 +205,6 @@ NorFlashWriteSingleWord ( + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER); + } + +- // Put device back into Read Array mode +- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); +- + return Status; + } + +@@ -286,8 +283,7 @@ NorFlashWriteBuffer ( + + // The buffer was not available for writing + if (WaitForBuffer == 0) { +- Status = EFI_DEVICE_ERROR; +- goto EXIT; ++ return EFI_DEVICE_ERROR; + } + + // From now on we work in 32-bit words +@@ -337,10 +333,6 @@ NorFlashWriteBuffer ( + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER); + } + +-EXIT: +- // Put device back into Read Array mode +- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); +- + return Status; + } + +@@ -739,6 +731,8 @@ NorFlashWriteSingleBlock ( + } + + TempStatus = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite); ++ // Put device back into Read Array mode ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); + if (EFI_ERROR (TempStatus)) { + return EFI_DEVICE_ERROR; + } +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +index 2ceda22635..f9a41f6aab 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +@@ -280,6 +280,9 @@ NorFlashWriteFullBlock ( + } + + EXIT: ++ // Put device back into Read Array mode ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); ++ + if (!EfiAtRuntime ()) { + // Interruptions can resume. + gBS->RestoreTPL (OriginalTPL); +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-avoid-switching-between-mode.patch b/edk2-OvmfPkg-VirtNorFlashDxe-avoid-switching-between-mode.patch new file mode 100644 index 0000000..783b96f --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-avoid-switching-between-mode.patch @@ -0,0 +1,303 @@ +From 67e26db39c0ec90c164634251da761f649546529 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 24 Oct 2022 17:58:07 +0200 +Subject: [PATCH 06/18] OvmfPkg/VirtNorFlashDxe: avoid switching between modes + in a tight loop + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [8/20] 4923b0fb1586d7955be466b90dce5f790da704ff + +Currently, when dealing with small updates that can be written out +directly (i.e., if they only involve clearing bits and not setting bits, +as the latter requires a block level erase), we iterate over the data +one word at a time, read the old value, compare it, write the new value, +and repeat, unless we encountered a value that we cannot write (0->1 +transition), in which case we fall back to a block level operation. + +This is inefficient for two reasons: +- reading and writing a word at a time involves switching between array +and programming mode for every word of data, which is +disproportionately costly when running under KVM; +- we end up writing some data twice, as we may not notice that a block +erase is needed until after some data has been written to flash. + +So replace this sequence with a single read of up to twice the buffered +write maximum size, followed by one or two buffered writes if the data +can be written directly. Otherwise, fall back to the existing block +level sequence, but without writing out part of the data twice. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Sunil V L +(cherry picked from commit 25589c4a76e7e3668fd6f794dd1827e958b6719c) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 214 +++++++++---------------- + 1 file changed, 76 insertions(+), 138 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 0a5c5d48c7..0343131a54 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -576,23 +576,20 @@ NorFlashWriteSingleBlock ( + IN UINT8 *Buffer + ) + { +- EFI_STATUS TempStatus; +- UINT32 Tmp; +- UINT32 TmpBuf; +- UINT32 WordToWrite; +- UINT32 Mask; +- BOOLEAN DoErase; +- UINTN BytesToWrite; ++ EFI_STATUS Status; + UINTN CurOffset; +- UINTN WordAddr; + UINTN BlockSize; + UINTN BlockAddress; +- UINTN PrevBlockAddress; +- +- PrevBlockAddress = 0; ++ UINT8 *OrigData; + + DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer)); + ++ // Check we did get some memory. Buffer is BlockSize. ++ if (Instance->ShadowBuffer == NULL) { ++ DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ + // Cache the block size to avoid de-referencing pointers all the time + BlockSize = Instance->BlockSize; + +@@ -612,148 +609,89 @@ NorFlashWriteSingleBlock ( + return EFI_BAD_BUFFER_SIZE; + } + +- // Pick 128bytes as a good start for word operations as opposed to erasing the +- // block and writing the data regardless if an erase is really needed. +- // It looks like most individual NV variable writes are smaller than 128bytes. +- if (*NumBytes <= 128) { ++ // Pick P30_MAX_BUFFER_SIZE_IN_BYTES (== 128 bytes) as a good start for word ++ // operations as opposed to erasing the block and writing the data regardless ++ // if an erase is really needed. It looks like most individual NV variable ++ // writes are smaller than 128 bytes. ++ // To avoid pathological cases were a 2 byte write is disregarded because it ++ // occurs right at a 128 byte buffered write alignment boundary, permit up to ++ // twice the max buffer size, and perform two writes if needed. ++ if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) { + // Check to see if we need to erase before programming the data into NOR. + // If the destination bits are only changing from 1s to 0s we can just write. + // After a block is erased all bits in the block is set to 1. + // If any byte requires us to erase we just give up and rewrite all of it. +- DoErase = FALSE; +- BytesToWrite = *NumBytes; +- CurOffset = Offset; +- +- while (BytesToWrite > 0) { +- // Read full word from NOR, splice as required. A word is the smallest +- // unit we can write. +- TempStatus = NorFlashRead (Instance, Lba, CurOffset & ~(0x3), sizeof (Tmp), &Tmp); +- if (EFI_ERROR (TempStatus)) { +- return EFI_DEVICE_ERROR; +- } + +- // Physical address of word in NOR to write. +- WordAddr = (CurOffset & ~(0x3)) + GET_NOR_BLOCK_ADDRESS ( +- Instance->RegionBaseAddress, +- Lba, +- BlockSize +- ); +- // The word of data that is to be written. +- TmpBuf = *((UINT32 *)(Buffer + (*NumBytes - BytesToWrite))); +- +- // First do word aligned chunks. +- if ((CurOffset & 0x3) == 0) { +- if (BytesToWrite >= 4) { +- // Is the destination still in 'erased' state? +- if (~Tmp != 0) { +- // Check to see if we are only changing bits to zero. +- if ((Tmp ^ TmpBuf) & TmpBuf) { +- DoErase = TRUE; +- break; +- } +- } +- +- // Write this word to NOR +- WordToWrite = TmpBuf; +- CurOffset += sizeof (TmpBuf); +- BytesToWrite -= sizeof (TmpBuf); +- } else { +- // BytesToWrite < 4. Do small writes and left-overs +- Mask = ~((~0) << (BytesToWrite * 8)); +- // Mask out the bytes we want. +- TmpBuf &= Mask; +- // Is the destination still in 'erased' state? +- if ((Tmp & Mask) != Mask) { +- // Check to see if we are only changing bits to zero. +- if ((Tmp ^ TmpBuf) & TmpBuf) { +- DoErase = TRUE; +- break; +- } +- } +- +- // Merge old and new data. Write merged word to NOR +- WordToWrite = (Tmp & ~Mask) | TmpBuf; +- CurOffset += BytesToWrite; +- BytesToWrite = 0; +- } +- } else { +- // Do multiple words, but starting unaligned. +- if (BytesToWrite > (4 - (CurOffset & 0x3))) { +- Mask = ((~0) << ((CurOffset & 0x3) * 8)); +- // Mask out the bytes we want. +- TmpBuf &= Mask; +- // Is the destination still in 'erased' state? +- if ((Tmp & Mask) != Mask) { +- // Check to see if we are only changing bits to zero. +- if ((Tmp ^ TmpBuf) & TmpBuf) { +- DoErase = TRUE; +- break; +- } +- } +- +- // Merge old and new data. Write merged word to NOR +- WordToWrite = (Tmp & ~Mask) | TmpBuf; +- BytesToWrite -= (4 - (CurOffset & 0x3)); +- CurOffset += (4 - (CurOffset & 0x3)); +- } else { +- // Unaligned and fits in one word. +- Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8); +- // Mask out the bytes we want. +- TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask; +- // Is the destination still in 'erased' state? +- if ((Tmp & Mask) != Mask) { +- // Check to see if we are only changing bits to zero. +- if ((Tmp ^ TmpBuf) & TmpBuf) { +- DoErase = TRUE; +- break; +- } +- } +- +- // Merge old and new data. Write merged word to NOR +- WordToWrite = (Tmp & ~Mask) | TmpBuf; +- CurOffset += BytesToWrite; +- BytesToWrite = 0; +- } ++ // Read the old version of the data into the shadow buffer ++ Status = NorFlashRead ( ++ Instance, ++ Lba, ++ Offset & ~BOUNDARY_OF_32_WORDS, ++ (*NumBytes | BOUNDARY_OF_32_WORDS) + 1, ++ Instance->ShadowBuffer ++ ); ++ if (EFI_ERROR (Status)) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // Make OrigData point to the start of the old version of the data inside ++ // the word aligned buffer ++ OrigData = Instance->ShadowBuffer + (Offset & BOUNDARY_OF_32_WORDS); ++ ++ // Update the buffer containing the old version of the data with the new ++ // contents, while checking whether the old version had any bits cleared ++ // that we want to set. In that case, we will need to erase the block first. ++ for (CurOffset = 0; CurOffset < *NumBytes; CurOffset++) { ++ if (~OrigData[CurOffset] & Buffer[CurOffset]) { ++ goto DoErase; + } + +- // +- // Write the word to NOR. +- // ++ OrigData[CurOffset] = Buffer[CurOffset]; ++ } + +- BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize); +- if (BlockAddress != PrevBlockAddress) { +- TempStatus = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress); +- if (EFI_ERROR (TempStatus)) { +- return EFI_DEVICE_ERROR; +- } ++ // ++ // Write the updated buffer to NOR. ++ // ++ BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize); + +- PrevBlockAddress = BlockAddress; +- } ++ // Unlock the block if we have to ++ Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress); ++ if (EFI_ERROR (Status)) { ++ goto Exit; ++ } + +- TempStatus = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite); +- // Put device back into Read Array mode +- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); +- if (EFI_ERROR (TempStatus)) { +- return EFI_DEVICE_ERROR; +- } ++ Status = NorFlashWriteBuffer ( ++ Instance, ++ BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS), ++ P30_MAX_BUFFER_SIZE_IN_BYTES, ++ Instance->ShadowBuffer ++ ); ++ if (EFI_ERROR (Status)) { ++ goto Exit; + } + +- // Exit if we got here and could write all the data. Otherwise do the +- // Erase-Write cycle. +- if (!DoErase) { +- return EFI_SUCCESS; ++ if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) > P30_MAX_BUFFER_SIZE_IN_BYTES) { ++ BlockAddress += P30_MAX_BUFFER_SIZE_IN_BYTES; ++ ++ Status = NorFlashWriteBuffer ( ++ Instance, ++ BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS), ++ P30_MAX_BUFFER_SIZE_IN_BYTES, ++ Instance->ShadowBuffer + P30_MAX_BUFFER_SIZE_IN_BYTES ++ ); + } +- } + +- // Check we did get some memory. Buffer is BlockSize. +- if (Instance->ShadowBuffer == NULL) { +- DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n")); +- return EFI_DEVICE_ERROR; ++Exit: ++ // Put device back into Read Array mode ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); ++ ++ return Status; + } + ++DoErase: + // Read NOR Flash data into shadow buffer +- TempStatus = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); +- if (EFI_ERROR (TempStatus)) { ++ Status = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); ++ if (EFI_ERROR (Status)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } +@@ -762,8 +700,8 @@ NorFlashWriteSingleBlock ( + CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes); + + // Write the modified buffer back to the NorFlash +- TempStatus = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); +- if (EFI_ERROR (TempStatus)) { ++ Status = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); ++ if (EFI_ERROR (Status)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch b/edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch new file mode 100644 index 0000000..0ac5c14 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch @@ -0,0 +1,110 @@ +From f136d4895b1477a56b916a76448ba76e67b08163 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:01 +0100 +Subject: [PATCH 12/18] OvmfPkg/VirtNorFlashDxe: clarify block write logic & + fix shadowbuffer reads + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [14/20] 38009625e5f189166f7a93e236576140a7ccb393 + +Introduce 'Start' and 'End' variables to make it easier to follow the +logic and code flow. Also add a ascii art diagram (based on a +suggestion by Laszlo). + +This also fixes the 'Size' calculation for the NorFlashRead() call. +Without this patch the code will read only one instead of two +P30_MAX_BUFFER_SIZE_IN_BYTES blocks in case '*NumBytes' is smaller than +P30_MAX_BUFFER_SIZE_IN_BYTES but 'Offset + *NumBytes' is not, i.e. the +update range crosses a P30_MAX_BUFFER_SIZE_IN_BYTES boundary. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-Id: <20240116171105.37831-3-kraxel@redhat.com> +(cherry picked from commit 35d8ea8097794b522149688b5cfaf8364bc44d54) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 36 ++++++++++++++++++++------ + 1 file changed, 28 insertions(+), 8 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 7f4743b003..88a4d2c23f 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -520,6 +520,7 @@ NorFlashWriteSingleBlock ( + UINTN BlockSize; + UINTN BlockAddress; + UINT8 *OrigData; ++ UINTN Start, End; + + DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer)); + +@@ -555,7 +556,28 @@ NorFlashWriteSingleBlock ( + // To avoid pathological cases were a 2 byte write is disregarded because it + // occurs right at a 128 byte buffered write alignment boundary, permit up to + // twice the max buffer size, and perform two writes if needed. +- if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) { ++ // ++ // 0 128 256 ++ // [----------------|----------------] ++ // ^ ^ ^ ^ ++ // | | | | ++ // | | | End, the next "word" boundary beyond ++ // | | | the (logical) update ++ // | | | ++ // | | (Offset & BOUNDARY_OF_32_WORDS) + NumBytes; ++ // | | i.e., the relative offset inside (or just past) ++ // | | the *double-word* such that it is the ++ // | | *exclusive* end of the (logical) update. ++ // | | ++ // | Offset & BOUNDARY_OF_32_WORDS; i.e., Offset within the "word"; ++ // | this is where the (logical) update is supposed to start ++ // | ++ // Start = Offset & ~BOUNDARY_OF_32_WORDS; i.e., Offset truncated to "word" boundary ++ ++ Start = Offset & ~BOUNDARY_OF_32_WORDS; ++ End = ALIGN_VALUE (Offset + *NumBytes, P30_MAX_BUFFER_SIZE_IN_BYTES); ++ ++ if ((End - Start) <= (2 * P30_MAX_BUFFER_SIZE_IN_BYTES)) { + // Check to see if we need to erase before programming the data into NOR. + // If the destination bits are only changing from 1s to 0s we can just write. + // After a block is erased all bits in the block is set to 1. +@@ -565,8 +587,8 @@ NorFlashWriteSingleBlock ( + Status = NorFlashRead ( + Instance, + Lba, +- Offset & ~BOUNDARY_OF_32_WORDS, +- (*NumBytes | BOUNDARY_OF_32_WORDS) + 1, ++ Start, ++ End - Start, + Instance->ShadowBuffer + ); + if (EFI_ERROR (Status)) { +@@ -601,7 +623,7 @@ NorFlashWriteSingleBlock ( + + Status = NorFlashWriteBuffer ( + Instance, +- BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS), ++ BlockAddress + Start, + P30_MAX_BUFFER_SIZE_IN_BYTES, + Instance->ShadowBuffer + ); +@@ -609,12 +631,10 @@ NorFlashWriteSingleBlock ( + goto Exit; + } + +- if ((*NumBytes + (Offset & BOUNDARY_OF_32_WORDS)) > P30_MAX_BUFFER_SIZE_IN_BYTES) { +- BlockAddress += P30_MAX_BUFFER_SIZE_IN_BYTES; +- ++ if ((End - Start) > P30_MAX_BUFFER_SIZE_IN_BYTES) { + Status = NorFlashWriteBuffer ( + Instance, +- BlockAddress + (Offset & ~BOUNDARY_OF_32_WORDS), ++ BlockAddress + Start + P30_MAX_BUFFER_SIZE_IN_BYTES, + P30_MAX_BUFFER_SIZE_IN_BYTES, + Instance->ShadowBuffer + P30_MAX_BUFFER_SIZE_IN_BYTES + ); +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-clone-ArmPlatformPkg-s-NOR-f.patch b/edk2-OvmfPkg-VirtNorFlashDxe-clone-ArmPlatformPkg-s-NOR-f.patch new file mode 100644 index 0000000..41975ab --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-clone-ArmPlatformPkg-s-NOR-f.patch @@ -0,0 +1,2973 @@ +From 3d6a0e0d3323c8b98a56e69ed01b6634dd480f25 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 24 Oct 2022 16:41:43 +0200 +Subject: [PATCH 01/18] OvmfPkg/VirtNorFlashDxe: clone ArmPlatformPkg's NOR + flash driver + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [3/20] f78caae529b7f943a5d4838cb906546373de4c54 + +QEMU's mach-virt is loosely based on ARM Versatile Express, and inherits +its NOR flash driver, which is now being used on other QEMU emulated +architectures as well. + +In order to permit ourselves the freedom to optimize this driver for +use under KVM emulation, let's clone it into OvmfPkg, so we have a +version we can hack without the risk of regressing bare metal platforms. + +The cloned version is mostly identical to the original, but it depends +on the newly added VirtNorFlashPlatformLib library class instead of the +original one from ArmPlatformPkg. Beyond that, only cosmetic changes +related to #include order etc were made. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Sunil V L +(cherry picked from commit c1ff81f7990be88c9e98ca3be65178057d8aae77) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 991 ++++++++++++++++++ + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h | 422 ++++++++ + .../VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c | 123 +++ + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 506 +++++++++ + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf | 72 ++ + OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c | 777 ++++++++++++++ + 6 files changed, 2891 insertions(+) + create mode 100644 OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c + create mode 100644 OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h + create mode 100644 OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c + create mode 100644 OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c + create mode 100644 OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf + create mode 100644 OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +new file mode 100644 +index 0000000000..12fa720dad +--- /dev/null ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -0,0 +1,991 @@ ++/** @file NorFlash.c ++ ++ Copyright (c) 2011 - 2020, Arm Limited. All rights reserved.
++ Copyright (c) 2020, Linaro, Ltd. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#include ++ ++#include "VirtNorFlash.h" ++ ++// ++// Global variable declarations ++// ++extern NOR_FLASH_INSTANCE **mNorFlashInstances; ++extern UINT32 mNorFlashDeviceCount; ++ ++UINT32 ++NorFlashReadStatusRegister ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN SR_Address ++ ) ++{ ++ // Prepare to read the status register ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_STATUS_REGISTER); ++ return MmioRead32 (Instance->DeviceBaseAddress); ++} ++ ++STATIC ++BOOLEAN ++NorFlashBlockIsLocked ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN BlockAddress ++ ) ++{ ++ UINT32 LockStatus; ++ ++ // Send command for reading device id ++ SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID); ++ ++ // Read block lock status ++ LockStatus = MmioRead32 (CREATE_NOR_ADDRESS (BlockAddress, 2)); ++ ++ // Decode block lock status ++ LockStatus = FOLD_32BIT_INTO_16BIT (LockStatus); ++ ++ if ((LockStatus & 0x2) != 0) { ++ DEBUG ((DEBUG_ERROR, "NorFlashBlockIsLocked: WARNING: Block LOCKED DOWN\n")); ++ } ++ ++ return ((LockStatus & 0x1) != 0); ++} ++ ++STATIC ++EFI_STATUS ++NorFlashUnlockSingleBlock ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN BlockAddress ++ ) ++{ ++ UINT32 LockStatus; ++ ++ // Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations ++ // and to protect shared data structures. ++ ++ if (FeaturePcdGet (PcdNorFlashCheckBlockLocked) == TRUE) { ++ do { ++ // Request a lock setup ++ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP); ++ ++ // Request an unlock ++ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK); ++ ++ // Send command for reading device id ++ SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID); ++ ++ // Read block lock status ++ LockStatus = MmioRead32 (CREATE_NOR_ADDRESS (BlockAddress, 2)); ++ ++ // Decode block lock status ++ LockStatus = FOLD_32BIT_INTO_16BIT (LockStatus); ++ } while ((LockStatus & 0x1) == 1); ++ } else { ++ // Request a lock setup ++ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP); ++ ++ // Request an unlock ++ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK); ++ ++ // Wait until the status register gives us the all clear ++ do { ++ LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress); ++ } while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE); ++ } ++ ++ // Put device back into Read Array mode ++ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_READ_ARRAY); ++ ++ DEBUG ((DEBUG_BLKIO, "UnlockSingleBlock: BlockAddress=0x%08x\n", BlockAddress)); ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++NorFlashUnlockSingleBlockIfNecessary ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN BlockAddress ++ ) ++{ ++ EFI_STATUS Status; ++ ++ Status = EFI_SUCCESS; ++ ++ if (NorFlashBlockIsLocked (Instance, BlockAddress)) { ++ Status = NorFlashUnlockSingleBlock (Instance, BlockAddress); ++ } ++ ++ return Status; ++} ++ ++/** ++ * The following function presumes that the block has already been unlocked. ++ **/ ++EFI_STATUS ++NorFlashEraseSingleBlock ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN BlockAddress ++ ) ++{ ++ EFI_STATUS Status; ++ UINT32 StatusRegister; ++ ++ Status = EFI_SUCCESS; ++ ++ // Request a block erase and then confirm it ++ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_SETUP); ++ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_CONFIRM); ++ ++ // Wait until the status register gives us the all clear ++ do { ++ StatusRegister = NorFlashReadStatusRegister (Instance, BlockAddress); ++ } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE); ++ ++ if (StatusRegister & P30_SR_BIT_VPP) { ++ DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: VPP Range Error\n", BlockAddress)); ++ Status = EFI_DEVICE_ERROR; ++ } ++ ++ if ((StatusRegister & (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) == (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) { ++ DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Command Sequence Error\n", BlockAddress)); ++ Status = EFI_DEVICE_ERROR; ++ } ++ ++ if (StatusRegister & P30_SR_BIT_ERASE) { ++ DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Erase Error StatusRegister:0x%X\n", BlockAddress, StatusRegister)); ++ Status = EFI_DEVICE_ERROR; ++ } ++ ++ if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) { ++ // The debug level message has been reduced because a device lock might happen. In this case we just retry it ... ++ DEBUG ((DEBUG_INFO, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error\n", BlockAddress)); ++ Status = EFI_WRITE_PROTECTED; ++ } ++ ++ if (EFI_ERROR (Status)) { ++ // Clear the Status Register ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER); ++ } ++ ++ // Put device back into Read Array mode ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); ++ ++ return Status; ++} ++ ++EFI_STATUS ++NorFlashWriteSingleWord ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN WordAddress, ++ IN UINT32 WriteData ++ ) ++{ ++ EFI_STATUS Status; ++ UINT32 StatusRegister; ++ ++ Status = EFI_SUCCESS; ++ ++ // Request a write single word command ++ SEND_NOR_COMMAND (WordAddress, 0, P30_CMD_WORD_PROGRAM_SETUP); ++ ++ // Store the word into NOR Flash; ++ MmioWrite32 (WordAddress, WriteData); ++ ++ // Wait for the write to complete and then check for any errors; i.e. check the Status Register ++ do { ++ // Prepare to read the status register ++ StatusRegister = NorFlashReadStatusRegister (Instance, WordAddress); ++ // The chip is busy while the WRITE bit is not asserted ++ } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE); ++ ++ // Perform a full status check: ++ // Mask the relevant bits of Status Register. ++ // Everything should be zero, if not, we have a problem ++ ++ if (StatusRegister & P30_SR_BIT_VPP) { ++ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): VPP Range Error\n", WordAddress)); ++ Status = EFI_DEVICE_ERROR; ++ } ++ ++ if (StatusRegister & P30_SR_BIT_PROGRAM) { ++ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): Program Error\n", WordAddress)); ++ Status = EFI_DEVICE_ERROR; ++ } ++ ++ if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) { ++ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): Device Protect Error\n", WordAddress)); ++ Status = EFI_DEVICE_ERROR; ++ } ++ ++ if (!EFI_ERROR (Status)) { ++ // Clear the Status Register ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER); ++ } ++ ++ // Put device back into Read Array mode ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); ++ ++ return Status; ++} ++ ++/* ++ * Writes data to the NOR Flash using the Buffered Programming method. ++ * ++ * The maximum size of the on-chip buffer is 32-words, because of hardware restrictions. ++ * Therefore this function will only handle buffers up to 32 words or 128 bytes. ++ * To deal with larger buffers, call this function again. ++ * ++ * This function presumes that both the TargetAddress and the TargetAddress+BufferSize ++ * exist entirely within the NOR Flash. Therefore these conditions will not be checked here. ++ * ++ * In buffered programming, if the target address not at the beginning of a 32-bit word boundary, ++ * then programming time is doubled and power consumption is increased. ++ * Therefore, it is a requirement to align buffer writes to 32-bit word boundaries. ++ * i.e. the last 4 bits of the target start address must be zero: 0x......00 ++ */ ++EFI_STATUS ++NorFlashWriteBuffer ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN TargetAddress, ++ IN UINTN BufferSizeInBytes, ++ IN UINT32 *Buffer ++ ) ++{ ++ EFI_STATUS Status; ++ UINTN BufferSizeInWords; ++ UINTN Count; ++ volatile UINT32 *Data; ++ UINTN WaitForBuffer; ++ BOOLEAN BufferAvailable; ++ UINT32 StatusRegister; ++ ++ WaitForBuffer = MAX_BUFFERED_PROG_ITERATIONS; ++ BufferAvailable = FALSE; ++ ++ // Check that the target address does not cross a 32-word boundary. ++ if ((TargetAddress & BOUNDARY_OF_32_WORDS) != 0) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // Check there are some data to program ++ if (BufferSizeInBytes == 0) { ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ ++ // Check that the buffer size does not exceed the maximum hardware buffer size on chip. ++ if (BufferSizeInBytes > P30_MAX_BUFFER_SIZE_IN_BYTES) { ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // Check that the buffer size is a multiple of 32-bit words ++ if ((BufferSizeInBytes % 4) != 0) { ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // Pre-programming conditions checked, now start the algorithm. ++ ++ // Prepare the data destination address ++ Data = (UINT32 *)TargetAddress; ++ ++ // Check the availability of the buffer ++ do { ++ // Issue the Buffered Program Setup command ++ SEND_NOR_COMMAND (TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_SETUP); ++ ++ // Read back the status register bit#7 from the same address ++ if (((*Data) & P30_SR_BIT_WRITE) == P30_SR_BIT_WRITE) { ++ BufferAvailable = TRUE; ++ } ++ ++ // Update the loop counter ++ WaitForBuffer--; ++ } while ((WaitForBuffer > 0) && (BufferAvailable == FALSE)); ++ ++ // The buffer was not available for writing ++ if (WaitForBuffer == 0) { ++ Status = EFI_DEVICE_ERROR; ++ goto EXIT; ++ } ++ ++ // From now on we work in 32-bit words ++ BufferSizeInWords = BufferSizeInBytes / (UINTN)4; ++ ++ // Write the word count, which is (buffer_size_in_words - 1), ++ // because word count 0 means one word. ++ SEND_NOR_COMMAND (TargetAddress, 0, (BufferSizeInWords - 1)); ++ ++ // Write the data to the NOR Flash, advancing each address by 4 bytes ++ for (Count = 0; Count < BufferSizeInWords; Count++, Data++, Buffer++) { ++ MmioWrite32 ((UINTN)Data, *Buffer); ++ } ++ ++ // Issue the Buffered Program Confirm command, to start the programming operation ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM); ++ ++ // Wait for the write to complete and then check for any errors; i.e. check the Status Register ++ do { ++ StatusRegister = NorFlashReadStatusRegister (Instance, TargetAddress); ++ // The chip is busy while the WRITE bit is not asserted ++ } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE); ++ ++ // Perform a full status check: ++ // Mask the relevant bits of Status Register. ++ // Everything should be zero, if not, we have a problem ++ ++ Status = EFI_SUCCESS; ++ ++ if (StatusRegister & P30_SR_BIT_VPP) { ++ DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): VPP Range Error\n", TargetAddress)); ++ Status = EFI_DEVICE_ERROR; ++ } ++ ++ if (StatusRegister & P30_SR_BIT_PROGRAM) { ++ DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): Program Error\n", TargetAddress)); ++ Status = EFI_DEVICE_ERROR; ++ } ++ ++ if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) { ++ DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): Device Protect Error\n", TargetAddress)); ++ Status = EFI_DEVICE_ERROR; ++ } ++ ++ if (!EFI_ERROR (Status)) { ++ // Clear the Status Register ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER); ++ } ++ ++EXIT: ++ // Put device back into Read Array mode ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); ++ ++ return Status; ++} ++ ++EFI_STATUS ++NorFlashWriteBlocks ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINTN BufferSizeInBytes, ++ IN VOID *Buffer ++ ) ++{ ++ UINT32 *pWriteBuffer; ++ EFI_STATUS Status; ++ EFI_LBA CurrentBlock; ++ UINT32 BlockSizeInWords; ++ UINT32 NumBlocks; ++ UINT32 BlockCount; ++ ++ Status = EFI_SUCCESS; ++ ++ // The buffer must be valid ++ if (Buffer == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (Instance->Media.ReadOnly == TRUE) { ++ return EFI_WRITE_PROTECTED; ++ } ++ ++ // We must have some bytes to read ++ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", BufferSizeInBytes)); ++ if (BufferSizeInBytes == 0) { ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // The size of the buffer must be a multiple of the block size ++ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->Media.BlockSize)); ++ if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) { ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // All blocks must be within the device ++ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize; ++ ++ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba)); ++ ++ if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) { ++ DEBUG ((DEBUG_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ BlockSizeInWords = Instance->Media.BlockSize / 4; ++ ++ // Because the target *Buffer is a pointer to VOID, we must put all the data into a pointer ++ // to a proper data type, so use *ReadBuffer ++ pWriteBuffer = (UINT32 *)Buffer; ++ ++ CurrentBlock = Lba; ++ for (BlockCount = 0; BlockCount < NumBlocks; BlockCount++, CurrentBlock++, pWriteBuffer = pWriteBuffer + BlockSizeInWords) { ++ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UINTN)CurrentBlock)); ++ ++ Status = NorFlashWriteFullBlock (Instance, CurrentBlock, pWriteBuffer, BlockSizeInWords); ++ ++ if (EFI_ERROR (Status)) { ++ break; ++ } ++ } ++ ++ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Exit Status = \"%r\".\n", Status)); ++ return Status; ++} ++ ++#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align) - 1)) == 0) ++ ++/** ++ Copy Length bytes from Source to Destination, using aligned accesses only. ++ Note that this implementation uses memcpy() semantics rather then memmove() ++ semantics, i.e., SourceBuffer and DestinationBuffer should not overlap. ++ ++ @param DestinationBuffer The target of the copy request. ++ @param SourceBuffer The place to copy from. ++ @param Length The number of bytes to copy. ++ ++ @return Destination ++ ++**/ ++STATIC ++VOID * ++AlignedCopyMem ( ++ OUT VOID *DestinationBuffer, ++ IN CONST VOID *SourceBuffer, ++ IN UINTN Length ++ ) ++{ ++ UINT8 *Destination8; ++ CONST UINT8 *Source8; ++ UINT32 *Destination32; ++ CONST UINT32 *Source32; ++ UINT64 *Destination64; ++ CONST UINT64 *Source64; ++ ++ if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 8) && (Length >= 8)) { ++ Destination64 = DestinationBuffer; ++ Source64 = SourceBuffer; ++ while (Length >= 8) { ++ *Destination64++ = *Source64++; ++ Length -= 8; ++ } ++ ++ Destination8 = (UINT8 *)Destination64; ++ Source8 = (CONST UINT8 *)Source64; ++ } else if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 4) && (Length >= 4)) { ++ Destination32 = DestinationBuffer; ++ Source32 = SourceBuffer; ++ while (Length >= 4) { ++ *Destination32++ = *Source32++; ++ Length -= 4; ++ } ++ ++ Destination8 = (UINT8 *)Destination32; ++ Source8 = (CONST UINT8 *)Source32; ++ } else { ++ Destination8 = DestinationBuffer; ++ Source8 = SourceBuffer; ++ } ++ ++ while (Length-- != 0) { ++ *Destination8++ = *Source8++; ++ } ++ ++ return DestinationBuffer; ++} ++ ++EFI_STATUS ++NorFlashReadBlocks ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINTN BufferSizeInBytes, ++ OUT VOID *Buffer ++ ) ++{ ++ UINT32 NumBlocks; ++ UINTN StartAddress; ++ ++ DEBUG (( ++ DEBUG_BLKIO, ++ "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n", ++ BufferSizeInBytes, ++ Instance->Media.BlockSize, ++ Instance->Media.LastBlock, ++ Lba ++ )); ++ ++ // The buffer must be valid ++ if (Buffer == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // Return if we have not any byte to read ++ if (BufferSizeInBytes == 0) { ++ return EFI_SUCCESS; ++ } ++ ++ // The size of the buffer must be a multiple of the block size ++ if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) { ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // All blocks must be within the device ++ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize; ++ ++ if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) { ++ DEBUG ((DEBUG_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed last block\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // Get the address to start reading from ++ StartAddress = GET_NOR_BLOCK_ADDRESS ( ++ Instance->RegionBaseAddress, ++ Lba, ++ Instance->Media.BlockSize ++ ); ++ ++ // Put the device into Read Array mode ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); ++ ++ // Readout the data ++ AlignedCopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes); ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++NorFlashRead ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINTN Offset, ++ IN UINTN BufferSizeInBytes, ++ OUT VOID *Buffer ++ ) ++{ ++ UINTN StartAddress; ++ ++ // The buffer must be valid ++ if (Buffer == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // Return if we have not any byte to read ++ if (BufferSizeInBytes == 0) { ++ return EFI_SUCCESS; ++ } ++ ++ if (((Lba * Instance->Media.BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) { ++ DEBUG ((DEBUG_ERROR, "NorFlashRead: ERROR - Read will exceed device size.\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // Get the address to start reading from ++ StartAddress = GET_NOR_BLOCK_ADDRESS ( ++ Instance->RegionBaseAddress, ++ Lba, ++ Instance->Media.BlockSize ++ ); ++ ++ // Put the device into Read Array mode ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); ++ ++ // Readout the data ++ AlignedCopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes); ++ ++ return EFI_SUCCESS; ++} ++ ++/* ++ Write a full or portion of a block. It must not span block boundaries; that is, ++ Offset + *NumBytes <= Instance->Media.BlockSize. ++*/ ++EFI_STATUS ++NorFlashWriteSingleBlock ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINTN Offset, ++ IN OUT UINTN *NumBytes, ++ IN UINT8 *Buffer ++ ) ++{ ++ EFI_STATUS TempStatus; ++ UINT32 Tmp; ++ UINT32 TmpBuf; ++ UINT32 WordToWrite; ++ UINT32 Mask; ++ BOOLEAN DoErase; ++ UINTN BytesToWrite; ++ UINTN CurOffset; ++ UINTN WordAddr; ++ UINTN BlockSize; ++ UINTN BlockAddress; ++ UINTN PrevBlockAddress; ++ ++ PrevBlockAddress = 0; ++ ++ DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer)); ++ ++ // Detect WriteDisabled state ++ if (Instance->Media.ReadOnly == TRUE) { ++ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - Can not write: Device is in WriteDisabled state.\n")); ++ // It is in WriteDisabled state, return an error right away ++ return EFI_ACCESS_DENIED; ++ } ++ ++ // Cache the block size to avoid de-referencing pointers all the time ++ BlockSize = Instance->Media.BlockSize; ++ ++ // The write must not span block boundaries. ++ // We need to check each variable individually because adding two large values together overflows. ++ if ((Offset >= BlockSize) || ++ (*NumBytes > BlockSize) || ++ ((Offset + *NumBytes) > BlockSize)) ++ { ++ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize)); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // We must have some bytes to write ++ if (*NumBytes == 0) { ++ DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize)); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // Pick 128bytes as a good start for word operations as opposed to erasing the ++ // block and writing the data regardless if an erase is really needed. ++ // It looks like most individual NV variable writes are smaller than 128bytes. ++ if (*NumBytes <= 128) { ++ // Check to see if we need to erase before programming the data into NOR. ++ // If the destination bits are only changing from 1s to 0s we can just write. ++ // After a block is erased all bits in the block is set to 1. ++ // If any byte requires us to erase we just give up and rewrite all of it. ++ DoErase = FALSE; ++ BytesToWrite = *NumBytes; ++ CurOffset = Offset; ++ ++ while (BytesToWrite > 0) { ++ // Read full word from NOR, splice as required. A word is the smallest ++ // unit we can write. ++ TempStatus = NorFlashRead (Instance, Lba, CurOffset & ~(0x3), sizeof (Tmp), &Tmp); ++ if (EFI_ERROR (TempStatus)) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // Physical address of word in NOR to write. ++ WordAddr = (CurOffset & ~(0x3)) + GET_NOR_BLOCK_ADDRESS ( ++ Instance->RegionBaseAddress, ++ Lba, ++ BlockSize ++ ); ++ // The word of data that is to be written. ++ TmpBuf = *((UINT32 *)(Buffer + (*NumBytes - BytesToWrite))); ++ ++ // First do word aligned chunks. ++ if ((CurOffset & 0x3) == 0) { ++ if (BytesToWrite >= 4) { ++ // Is the destination still in 'erased' state? ++ if (~Tmp != 0) { ++ // Check to see if we are only changing bits to zero. ++ if ((Tmp ^ TmpBuf) & TmpBuf) { ++ DoErase = TRUE; ++ break; ++ } ++ } ++ ++ // Write this word to NOR ++ WordToWrite = TmpBuf; ++ CurOffset += sizeof (TmpBuf); ++ BytesToWrite -= sizeof (TmpBuf); ++ } else { ++ // BytesToWrite < 4. Do small writes and left-overs ++ Mask = ~((~0) << (BytesToWrite * 8)); ++ // Mask out the bytes we want. ++ TmpBuf &= Mask; ++ // Is the destination still in 'erased' state? ++ if ((Tmp & Mask) != Mask) { ++ // Check to see if we are only changing bits to zero. ++ if ((Tmp ^ TmpBuf) & TmpBuf) { ++ DoErase = TRUE; ++ break; ++ } ++ } ++ ++ // Merge old and new data. Write merged word to NOR ++ WordToWrite = (Tmp & ~Mask) | TmpBuf; ++ CurOffset += BytesToWrite; ++ BytesToWrite = 0; ++ } ++ } else { ++ // Do multiple words, but starting unaligned. ++ if (BytesToWrite > (4 - (CurOffset & 0x3))) { ++ Mask = ((~0) << ((CurOffset & 0x3) * 8)); ++ // Mask out the bytes we want. ++ TmpBuf &= Mask; ++ // Is the destination still in 'erased' state? ++ if ((Tmp & Mask) != Mask) { ++ // Check to see if we are only changing bits to zero. ++ if ((Tmp ^ TmpBuf) & TmpBuf) { ++ DoErase = TRUE; ++ break; ++ } ++ } ++ ++ // Merge old and new data. Write merged word to NOR ++ WordToWrite = (Tmp & ~Mask) | TmpBuf; ++ BytesToWrite -= (4 - (CurOffset & 0x3)); ++ CurOffset += (4 - (CurOffset & 0x3)); ++ } else { ++ // Unaligned and fits in one word. ++ Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8); ++ // Mask out the bytes we want. ++ TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask; ++ // Is the destination still in 'erased' state? ++ if ((Tmp & Mask) != Mask) { ++ // Check to see if we are only changing bits to zero. ++ if ((Tmp ^ TmpBuf) & TmpBuf) { ++ DoErase = TRUE; ++ break; ++ } ++ } ++ ++ // Merge old and new data. Write merged word to NOR ++ WordToWrite = (Tmp & ~Mask) | TmpBuf; ++ CurOffset += BytesToWrite; ++ BytesToWrite = 0; ++ } ++ } ++ ++ // ++ // Write the word to NOR. ++ // ++ ++ BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize); ++ if (BlockAddress != PrevBlockAddress) { ++ TempStatus = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress); ++ if (EFI_ERROR (TempStatus)) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ PrevBlockAddress = BlockAddress; ++ } ++ ++ TempStatus = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite); ++ if (EFI_ERROR (TempStatus)) { ++ return EFI_DEVICE_ERROR; ++ } ++ } ++ ++ // Exit if we got here and could write all the data. Otherwise do the ++ // Erase-Write cycle. ++ if (!DoErase) { ++ return EFI_SUCCESS; ++ } ++ } ++ ++ // Check we did get some memory. Buffer is BlockSize. ++ if (Instance->ShadowBuffer == NULL) { ++ DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // Read NOR Flash data into shadow buffer ++ TempStatus = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); ++ if (EFI_ERROR (TempStatus)) { ++ // Return one of the pre-approved error statuses ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // Put the data at the appropriate location inside the buffer area ++ CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes); ++ ++ // Write the modified buffer back to the NorFlash ++ TempStatus = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); ++ if (EFI_ERROR (TempStatus)) { ++ // Return one of the pre-approved error statuses ++ return EFI_DEVICE_ERROR; ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++/* ++ Although DiskIoDxe will automatically install the DiskIO protocol whenever ++ we install the BlockIO protocol, its implementation is sub-optimal as it reads ++ and writes entire blocks using the BlockIO protocol. In fact we can access ++ NOR flash with a finer granularity than that, so we can improve performance ++ by directly producing the DiskIO protocol. ++*/ ++ ++/** ++ Read BufferSize bytes from Offset into Buffer. ++ ++ @param This Protocol instance pointer. ++ @param MediaId Id of the media, changes every time the media is replaced. ++ @param Offset The starting byte offset to read from ++ @param BufferSize Size of Buffer ++ @param Buffer Buffer containing read data ++ ++ @retval EFI_SUCCESS The data was read correctly from the device. ++ @retval EFI_DEVICE_ERROR The device reported an error while performing the read. ++ @retval EFI_NO_MEDIA There is no media in the device. ++ @retval EFI_MEDIA_CHANGED The MediaId does not match the current device. ++ @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not ++ valid for the device. ++ ++**/ ++EFI_STATUS ++EFIAPI ++NorFlashDiskIoReadDisk ( ++ IN EFI_DISK_IO_PROTOCOL *This, ++ IN UINT32 MediaId, ++ IN UINT64 DiskOffset, ++ IN UINTN BufferSize, ++ OUT VOID *Buffer ++ ) ++{ ++ NOR_FLASH_INSTANCE *Instance; ++ UINT32 BlockSize; ++ UINT32 BlockOffset; ++ EFI_LBA Lba; ++ ++ Instance = INSTANCE_FROM_DISKIO_THIS (This); ++ ++ if (MediaId != Instance->Media.MediaId) { ++ return EFI_MEDIA_CHANGED; ++ } ++ ++ BlockSize = Instance->Media.BlockSize; ++ Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset); ++ ++ return NorFlashRead (Instance, Lba, BlockOffset, BufferSize, Buffer); ++} ++ ++/** ++ Writes a specified number of bytes to a device. ++ ++ @param This Indicates a pointer to the calling context. ++ @param MediaId ID of the medium to be written. ++ @param Offset The starting byte offset on the logical block I/O device to write. ++ @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device. ++ @param Buffer A pointer to the buffer containing the data to be written. ++ ++ @retval EFI_SUCCESS The data was written correctly to the device. ++ @retval EFI_WRITE_PROTECTED The device can not be written to. ++ @retval EFI_DEVICE_ERROR The device reported an error while performing the write. ++ @retval EFI_NO_MEDIA There is no media in the device. ++ @retval EFI_MEDIA_CHANGED The MediaId does not match the current device. ++ @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not ++ valid for the device. ++ ++**/ ++EFI_STATUS ++EFIAPI ++NorFlashDiskIoWriteDisk ( ++ IN EFI_DISK_IO_PROTOCOL *This, ++ IN UINT32 MediaId, ++ IN UINT64 DiskOffset, ++ IN UINTN BufferSize, ++ IN VOID *Buffer ++ ) ++{ ++ NOR_FLASH_INSTANCE *Instance; ++ UINT32 BlockSize; ++ UINT32 BlockOffset; ++ EFI_LBA Lba; ++ UINTN RemainingBytes; ++ UINTN WriteSize; ++ EFI_STATUS Status; ++ ++ Instance = INSTANCE_FROM_DISKIO_THIS (This); ++ ++ if (MediaId != Instance->Media.MediaId) { ++ return EFI_MEDIA_CHANGED; ++ } ++ ++ BlockSize = Instance->Media.BlockSize; ++ Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset); ++ ++ RemainingBytes = BufferSize; ++ ++ // Write either all the remaining bytes, or the number of bytes that bring ++ // us up to a block boundary, whichever is less. ++ // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next ++ // block boundary (even if it is already on one). ++ WriteSize = MIN (RemainingBytes, ((DiskOffset | (BlockSize - 1)) + 1) - DiskOffset); ++ ++ do { ++ if (WriteSize == BlockSize) { ++ // Write a full block ++ Status = NorFlashWriteFullBlock (Instance, Lba, Buffer, BlockSize / sizeof (UINT32)); ++ } else { ++ // Write a partial block ++ Status = NorFlashWriteSingleBlock (Instance, Lba, BlockOffset, &WriteSize, Buffer); ++ } ++ ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } ++ ++ // Now continue writing either all the remaining bytes or single blocks. ++ RemainingBytes -= WriteSize; ++ Buffer = (UINT8 *)Buffer + WriteSize; ++ Lba++; ++ BlockOffset = 0; ++ WriteSize = MIN (RemainingBytes, BlockSize); ++ } while (RemainingBytes); ++ ++ return Status; ++} ++ ++EFI_STATUS ++NorFlashReset ( ++ IN NOR_FLASH_INSTANCE *Instance ++ ) ++{ ++ // As there is no specific RESET to perform, ensure that the devices is in the default Read Array mode ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); ++ return EFI_SUCCESS; ++} ++ ++/** ++ Fixup internal data so that EFI can be call in virtual mode. ++ Call the passed in Child Notify event and convert any pointers in ++ lib to virtual mode. ++ ++ @param[in] Event The Event that is being processed ++ @param[in] Context Event Context ++**/ ++VOID ++EFIAPI ++NorFlashVirtualNotifyEvent ( ++ IN EFI_EVENT Event, ++ IN VOID *Context ++ ) ++{ ++ UINTN Index; ++ ++ for (Index = 0; Index < mNorFlashDeviceCount; Index++) { ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->DeviceBaseAddress); ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->RegionBaseAddress); ++ ++ // Convert BlockIo protocol ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.FlushBlocks); ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.ReadBlocks); ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.Reset); ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.WriteBlocks); ++ ++ // Convert Fvb ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks); ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes); ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize); ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress); ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Read); ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes); ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Write); ++ ++ if (mNorFlashInstances[Index]->ShadowBuffer != NULL) { ++ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->ShadowBuffer); ++ } ++ } ++ ++ return; ++} +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +new file mode 100644 +index 0000000000..e46522a198 +--- /dev/null ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +@@ -0,0 +1,422 @@ ++/** @file NorFlash.h ++ ++ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#ifndef __VIRT_NOR_FLASH__ ++#define __VIRT_NOR_FLASH__ ++ ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define NOR_FLASH_ERASE_RETRY 10 ++ ++// Device access macros ++// These are necessary because we use 2 x 16bit parts to make up 32bit data ++ ++#define HIGH_16_BITS 0xFFFF0000 ++#define LOW_16_BITS 0x0000FFFF ++#define LOW_8_BITS 0x000000FF ++ ++#define FOLD_32BIT_INTO_16BIT(value) ( ( value >> 16 ) | ( value & LOW_16_BITS ) ) ++ ++#define GET_LOW_BYTE(value) ( value & LOW_8_BITS ) ++#define GET_HIGH_BYTE(value) ( GET_LOW_BYTE( value >> 16 ) ) ++ ++// Each command must be sent simultaneously to both chips, ++// i.e. at the lower 16 bits AND at the higher 16 bits ++#define CREATE_NOR_ADDRESS(BaseAddr, OffsetAddr) ((BaseAddr) + ((OffsetAddr) << 2)) ++#define CREATE_DUAL_CMD(Cmd) ( ( Cmd << 16) | ( Cmd & LOW_16_BITS) ) ++#define SEND_NOR_COMMAND(BaseAddr, Offset, Cmd) MmioWrite32 (CREATE_NOR_ADDRESS(BaseAddr,Offset), CREATE_DUAL_CMD(Cmd)) ++#define GET_NOR_BLOCK_ADDRESS(BaseAddr, Lba, LbaSize) ( BaseAddr + (UINTN)((Lba) * LbaSize) ) ++ ++// Status Register Bits ++#define P30_SR_BIT_WRITE (BIT7 << 16 | BIT7) ++#define P30_SR_BIT_ERASE_SUSPEND (BIT6 << 16 | BIT6) ++#define P30_SR_BIT_ERASE (BIT5 << 16 | BIT5) ++#define P30_SR_BIT_PROGRAM (BIT4 << 16 | BIT4) ++#define P30_SR_BIT_VPP (BIT3 << 16 | BIT3) ++#define P30_SR_BIT_PROGRAM_SUSPEND (BIT2 << 16 | BIT2) ++#define P30_SR_BIT_BLOCK_LOCKED (BIT1 << 16 | BIT1) ++#define P30_SR_BIT_BEFP (BIT0 << 16 | BIT0) ++ ++// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family ++ ++// On chip buffer size for buffered programming operations ++// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and each word is 2 bytes. ++// Therefore the total size of the buffer is 2 x 32 x 2 = 128 bytes ++#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128) ++#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4)) ++#define MAX_BUFFERED_PROG_ITERATIONS 10000000 ++#define BOUNDARY_OF_32_WORDS 0x7F ++ ++// CFI Addresses ++#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10 ++#define P30_CFI_ADDR_VENDOR_ID 0x13 ++ ++// CFI Data ++#define CFI_QRY 0x00595251 ++ ++// READ Commands ++#define P30_CMD_READ_DEVICE_ID 0x0090 ++#define P30_CMD_READ_STATUS_REGISTER 0x0070 ++#define P30_CMD_CLEAR_STATUS_REGISTER 0x0050 ++#define P30_CMD_READ_ARRAY 0x00FF ++#define P30_CMD_READ_CFI_QUERY 0x0098 ++ ++// WRITE Commands ++#define P30_CMD_WORD_PROGRAM_SETUP 0x0040 ++#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP 0x0010 ++#define P30_CMD_BUFFERED_PROGRAM_SETUP 0x00E8 ++#define P30_CMD_BUFFERED_PROGRAM_CONFIRM 0x00D0 ++#define P30_CMD_BEFP_SETUP 0x0080 ++#define P30_CMD_BEFP_CONFIRM 0x00D0 ++ ++// ERASE Commands ++#define P30_CMD_BLOCK_ERASE_SETUP 0x0020 ++#define P30_CMD_BLOCK_ERASE_CONFIRM 0x00D0 ++ ++// SUSPEND Commands ++#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND 0x00B0 ++#define P30_CMD_SUSPEND_RESUME 0x00D0 ++ ++// BLOCK LOCKING / UNLOCKING Commands ++#define P30_CMD_LOCK_BLOCK_SETUP 0x0060 ++#define P30_CMD_LOCK_BLOCK 0x0001 ++#define P30_CMD_UNLOCK_BLOCK 0x00D0 ++#define P30_CMD_LOCK_DOWN_BLOCK 0x002F ++ ++// PROTECTION Commands ++#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0 ++ ++// CONFIGURATION Commands ++#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060 ++#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003 ++ ++#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0') ++#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE) ++#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE) ++#define INSTANCE_FROM_DISKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, DiskIoProtocol, NOR_FLASH_SIGNATURE) ++ ++typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE; ++ ++#pragma pack (1) ++typedef struct { ++ VENDOR_DEVICE_PATH Vendor; ++ UINT8 Index; ++ EFI_DEVICE_PATH_PROTOCOL End; ++} NOR_FLASH_DEVICE_PATH; ++#pragma pack () ++ ++struct _NOR_FLASH_INSTANCE { ++ UINT32 Signature; ++ EFI_HANDLE Handle; ++ ++ UINTN DeviceBaseAddress; ++ UINTN RegionBaseAddress; ++ UINTN Size; ++ EFI_LBA StartLba; ++ ++ EFI_BLOCK_IO_PROTOCOL BlockIoProtocol; ++ EFI_BLOCK_IO_MEDIA Media; ++ EFI_DISK_IO_PROTOCOL DiskIoProtocol; ++ ++ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; ++ VOID *ShadowBuffer; ++ ++ NOR_FLASH_DEVICE_PATH DevicePath; ++}; ++ ++EFI_STATUS ++NorFlashReadCfiData ( ++ IN UINTN DeviceBaseAddress, ++ IN UINTN CFI_Offset, ++ IN UINT32 NumberOfBytes, ++ OUT UINT32 *Data ++ ); ++ ++EFI_STATUS ++NorFlashWriteBuffer ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN TargetAddress, ++ IN UINTN BufferSizeInBytes, ++ IN UINT32 *Buffer ++ ); ++ ++// ++// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset ++// ++EFI_STATUS ++EFIAPI ++NorFlashBlockIoReset ( ++ IN EFI_BLOCK_IO_PROTOCOL *This, ++ IN BOOLEAN ExtendedVerification ++ ); ++ ++// ++// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks ++// ++EFI_STATUS ++EFIAPI ++NorFlashBlockIoReadBlocks ( ++ IN EFI_BLOCK_IO_PROTOCOL *This, ++ IN UINT32 MediaId, ++ IN EFI_LBA Lba, ++ IN UINTN BufferSizeInBytes, ++ OUT VOID *Buffer ++ ); ++ ++// ++// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks ++// ++EFI_STATUS ++EFIAPI ++NorFlashBlockIoWriteBlocks ( ++ IN EFI_BLOCK_IO_PROTOCOL *This, ++ IN UINT32 MediaId, ++ IN EFI_LBA Lba, ++ IN UINTN BufferSizeInBytes, ++ IN VOID *Buffer ++ ); ++ ++// ++// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks ++// ++EFI_STATUS ++EFIAPI ++NorFlashBlockIoFlushBlocks ( ++ IN EFI_BLOCK_IO_PROTOCOL *This ++ ); ++ ++// ++// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.ReadDisk ++// ++EFI_STATUS ++EFIAPI ++NorFlashDiskIoReadDisk ( ++ IN EFI_DISK_IO_PROTOCOL *This, ++ IN UINT32 MediaId, ++ IN UINT64 Offset, ++ IN UINTN BufferSize, ++ OUT VOID *Buffer ++ ); ++ ++// ++// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.WriteDisk ++// ++EFI_STATUS ++EFIAPI ++NorFlashDiskIoWriteDisk ( ++ IN EFI_DISK_IO_PROTOCOL *This, ++ IN UINT32 MediaId, ++ IN UINT64 Offset, ++ IN UINTN BufferSize, ++ IN VOID *Buffer ++ ); ++ ++// ++// NorFlashFvbDxe.c ++// ++ ++EFI_STATUS ++EFIAPI ++FvbGetAttributes ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ OUT EFI_FVB_ATTRIBUTES_2 *Attributes ++ ); ++ ++EFI_STATUS ++EFIAPI ++FvbSetAttributes ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes ++ ); ++ ++EFI_STATUS ++EFIAPI ++FvbGetPhysicalAddress ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ OUT EFI_PHYSICAL_ADDRESS *Address ++ ); ++ ++EFI_STATUS ++EFIAPI ++FvbGetBlockSize ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ IN EFI_LBA Lba, ++ OUT UINTN *BlockSize, ++ OUT UINTN *NumberOfBlocks ++ ); ++ ++EFI_STATUS ++EFIAPI ++FvbRead ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ IN EFI_LBA Lba, ++ IN UINTN Offset, ++ IN OUT UINTN *NumBytes, ++ IN OUT UINT8 *Buffer ++ ); ++ ++EFI_STATUS ++EFIAPI ++FvbWrite ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ IN EFI_LBA Lba, ++ IN UINTN Offset, ++ IN OUT UINTN *NumBytes, ++ IN UINT8 *Buffer ++ ); ++ ++EFI_STATUS ++EFIAPI ++FvbEraseBlocks ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ ... ++ ); ++ ++EFI_STATUS ++ValidateFvHeader ( ++ IN NOR_FLASH_INSTANCE *Instance ++ ); ++ ++EFI_STATUS ++InitializeFvAndVariableStoreHeaders ( ++ IN NOR_FLASH_INSTANCE *Instance ++ ); ++ ++VOID ++EFIAPI ++FvbVirtualNotifyEvent ( ++ IN EFI_EVENT Event, ++ IN VOID *Context ++ ); ++ ++// ++// NorFlashDxe.c ++// ++ ++EFI_STATUS ++NorFlashWriteFullBlock ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINT32 *DataBuffer, ++ IN UINT32 BlockSizeInWords ++ ); ++ ++EFI_STATUS ++NorFlashUnlockAndEraseSingleBlock ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN BlockAddress ++ ); ++ ++EFI_STATUS ++NorFlashCreateInstance ( ++ IN UINTN NorFlashDeviceBase, ++ IN UINTN NorFlashRegionBase, ++ IN UINTN NorFlashSize, ++ IN UINT32 Index, ++ IN UINT32 BlockSize, ++ IN BOOLEAN SupportFvb, ++ OUT NOR_FLASH_INSTANCE **NorFlashInstance ++ ); ++ ++EFI_STATUS ++EFIAPI ++NorFlashFvbInitialize ( ++ IN NOR_FLASH_INSTANCE *Instance ++ ); ++ ++// ++// NorFlash.c ++// ++EFI_STATUS ++NorFlashWriteSingleBlock ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINTN Offset, ++ IN OUT UINTN *NumBytes, ++ IN UINT8 *Buffer ++ ); ++ ++EFI_STATUS ++NorFlashWriteBlocks ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINTN BufferSizeInBytes, ++ IN VOID *Buffer ++ ); ++ ++EFI_STATUS ++NorFlashReadBlocks ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINTN BufferSizeInBytes, ++ OUT VOID *Buffer ++ ); ++ ++EFI_STATUS ++NorFlashRead ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINTN Offset, ++ IN UINTN BufferSizeInBytes, ++ OUT VOID *Buffer ++ ); ++ ++EFI_STATUS ++NorFlashWrite ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINTN Offset, ++ IN OUT UINTN *NumBytes, ++ IN UINT8 *Buffer ++ ); ++ ++EFI_STATUS ++NorFlashReset ( ++ IN NOR_FLASH_INSTANCE *Instance ++ ); ++ ++EFI_STATUS ++NorFlashEraseSingleBlock ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN BlockAddress ++ ); ++ ++EFI_STATUS ++NorFlashUnlockSingleBlockIfNecessary ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN BlockAddress ++ ); ++ ++EFI_STATUS ++NorFlashWriteSingleWord ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN WordAddress, ++ IN UINT32 WriteData ++ ); ++ ++VOID ++EFIAPI ++NorFlashVirtualNotifyEvent ( ++ IN EFI_EVENT Event, ++ IN VOID *Context ++ ); ++ ++#endif /* __VIRT_NOR_FLASH__ */ +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c +new file mode 100644 +index 0000000000..ecf152e355 +--- /dev/null ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c +@@ -0,0 +1,123 @@ ++/** @file NorFlashBlockIoDxe.c ++ ++ Copyright (c) 2011-2013, ARM Ltd. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#include ++#include ++ ++#include "VirtNorFlash.h" ++ ++// ++// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset ++// ++EFI_STATUS ++EFIAPI ++NorFlashBlockIoReset ( ++ IN EFI_BLOCK_IO_PROTOCOL *This, ++ IN BOOLEAN ExtendedVerification ++ ) ++{ ++ NOR_FLASH_INSTANCE *Instance; ++ ++ Instance = INSTANCE_FROM_BLKIO_THIS (This); ++ ++ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId)); ++ ++ return NorFlashReset (Instance); ++} ++ ++// ++// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks ++// ++EFI_STATUS ++EFIAPI ++NorFlashBlockIoReadBlocks ( ++ IN EFI_BLOCK_IO_PROTOCOL *This, ++ IN UINT32 MediaId, ++ IN EFI_LBA Lba, ++ IN UINTN BufferSizeInBytes, ++ OUT VOID *Buffer ++ ) ++{ ++ NOR_FLASH_INSTANCE *Instance; ++ EFI_STATUS Status; ++ EFI_BLOCK_IO_MEDIA *Media; ++ ++ if (This == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ Instance = INSTANCE_FROM_BLKIO_THIS (This); ++ Media = This->Media; ++ ++ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, BufferSizeInBytes, Buffer)); ++ ++ if (!Media) { ++ Status = EFI_INVALID_PARAMETER; ++ } else if (!Media->MediaPresent) { ++ Status = EFI_NO_MEDIA; ++ } else if (Media->MediaId != MediaId) { ++ Status = EFI_MEDIA_CHANGED; ++ } else if ((Media->IoAlign > 2) && (((UINTN)Buffer & (Media->IoAlign - 1)) != 0)) { ++ Status = EFI_INVALID_PARAMETER; ++ } else { ++ Status = NorFlashReadBlocks (Instance, Lba, BufferSizeInBytes, Buffer); ++ } ++ ++ return Status; ++} ++ ++// ++// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks ++// ++EFI_STATUS ++EFIAPI ++NorFlashBlockIoWriteBlocks ( ++ IN EFI_BLOCK_IO_PROTOCOL *This, ++ IN UINT32 MediaId, ++ IN EFI_LBA Lba, ++ IN UINTN BufferSizeInBytes, ++ IN VOID *Buffer ++ ) ++{ ++ NOR_FLASH_INSTANCE *Instance; ++ EFI_STATUS Status; ++ ++ Instance = INSTANCE_FROM_BLKIO_THIS (This); ++ ++ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes, BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer)); ++ ++ if ( !This->Media->MediaPresent ) { ++ Status = EFI_NO_MEDIA; ++ } else if ( This->Media->MediaId != MediaId ) { ++ Status = EFI_MEDIA_CHANGED; ++ } else if ( This->Media->ReadOnly ) { ++ Status = EFI_WRITE_PROTECTED; ++ } else { ++ Status = NorFlashWriteBlocks (Instance, Lba, BufferSizeInBytes, Buffer); ++ } ++ ++ return Status; ++} ++ ++// ++// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks ++// ++EFI_STATUS ++EFIAPI ++NorFlashBlockIoFlushBlocks ( ++ IN EFI_BLOCK_IO_PROTOCOL *This ++ ) ++{ ++ // No Flush required for the NOR Flash driver ++ // because cache operations are not permitted. ++ ++ DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoFlushBlocks: Function NOT IMPLEMENTED (not required).\n")); ++ ++ // Nothing to do so just return without error ++ return EFI_SUCCESS; ++} +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +new file mode 100644 +index 0000000000..819425545e +--- /dev/null ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +@@ -0,0 +1,506 @@ ++/** @file NorFlashDxe.c ++ ++ Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "VirtNorFlash.h" ++ ++STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent; ++ ++// ++// Global variable declarations ++// ++NOR_FLASH_INSTANCE **mNorFlashInstances; ++UINT32 mNorFlashDeviceCount; ++UINTN mFlashNvStorageVariableBase; ++EFI_EVENT mFvbVirtualAddrChangeEvent; ++ ++NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = { ++ NOR_FLASH_SIGNATURE, // Signature ++ NULL, // Handle ... NEED TO BE FILLED ++ ++ 0, // DeviceBaseAddress ... NEED TO BE FILLED ++ 0, // RegionBaseAddress ... NEED TO BE FILLED ++ 0, // Size ... NEED TO BE FILLED ++ 0, // StartLba ++ ++ { ++ EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision ++ NULL, // Media ... NEED TO BE FILLED ++ NorFlashBlockIoReset, // Reset; ++ NorFlashBlockIoReadBlocks, // ReadBlocks ++ NorFlashBlockIoWriteBlocks, // WriteBlocks ++ NorFlashBlockIoFlushBlocks // FlushBlocks ++ }, // BlockIoProtocol ++ ++ { ++ 0, // MediaId ... NEED TO BE FILLED ++ FALSE, // RemovableMedia ++ TRUE, // MediaPresent ++ FALSE, // LogicalPartition ++ FALSE, // ReadOnly ++ FALSE, // WriteCaching; ++ 0, // BlockSize ... NEED TO BE FILLED ++ 4, // IoAlign ++ 0, // LastBlock ... NEED TO BE FILLED ++ 0, // LowestAlignedLba ++ 1, // LogicalBlocksPerPhysicalBlock ++ }, // Media; ++ ++ { ++ EFI_DISK_IO_PROTOCOL_REVISION, // Revision ++ NorFlashDiskIoReadDisk, // ReadDisk ++ NorFlashDiskIoWriteDisk // WriteDisk ++ }, ++ ++ { ++ FvbGetAttributes, // GetAttributes ++ FvbSetAttributes, // SetAttributes ++ FvbGetPhysicalAddress, // GetPhysicalAddress ++ FvbGetBlockSize, // GetBlockSize ++ FvbRead, // Read ++ FvbWrite, // Write ++ FvbEraseBlocks, // EraseBlocks ++ NULL, // ParentHandle ++ }, // FvbProtoccol; ++ NULL, // ShadowBuffer ++ { ++ { ++ { ++ HARDWARE_DEVICE_PATH, ++ HW_VENDOR_DP, ++ { ++ (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)), ++ (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8) ++ } ++ }, ++ { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } ++ }, // GUID ... NEED TO BE FILLED ++ }, ++ 0, // Index ++ { ++ END_DEVICE_PATH_TYPE, ++ END_ENTIRE_DEVICE_PATH_SUBTYPE, ++ { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } ++ } ++ } // DevicePath ++}; ++ ++EFI_STATUS ++NorFlashCreateInstance ( ++ IN UINTN NorFlashDeviceBase, ++ IN UINTN NorFlashRegionBase, ++ IN UINTN NorFlashSize, ++ IN UINT32 Index, ++ IN UINT32 BlockSize, ++ IN BOOLEAN SupportFvb, ++ OUT NOR_FLASH_INSTANCE **NorFlashInstance ++ ) ++{ ++ EFI_STATUS Status; ++ NOR_FLASH_INSTANCE *Instance; ++ ++ ASSERT (NorFlashInstance != NULL); ++ ++ Instance = AllocateRuntimeCopyPool (sizeof (NOR_FLASH_INSTANCE), &mNorFlashInstanceTemplate); ++ if (Instance == NULL) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ Instance->DeviceBaseAddress = NorFlashDeviceBase; ++ Instance->RegionBaseAddress = NorFlashRegionBase; ++ Instance->Size = NorFlashSize; ++ ++ Instance->BlockIoProtocol.Media = &Instance->Media; ++ Instance->Media.MediaId = Index; ++ Instance->Media.BlockSize = BlockSize; ++ Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1; ++ ++ CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid); ++ Instance->DevicePath.Index = (UINT8)Index; ++ ++ Instance->ShadowBuffer = AllocateRuntimePool (BlockSize); ++ if (Instance->ShadowBuffer == NULL) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ if (SupportFvb) { ++ NorFlashFvbInitialize (Instance); ++ ++ Status = gBS->InstallMultipleProtocolInterfaces ( ++ &Instance->Handle, ++ &gEfiDevicePathProtocolGuid, ++ &Instance->DevicePath, ++ &gEfiBlockIoProtocolGuid, ++ &Instance->BlockIoProtocol, ++ &gEfiFirmwareVolumeBlockProtocolGuid, ++ &Instance->FvbProtocol, ++ NULL ++ ); ++ if (EFI_ERROR (Status)) { ++ FreePool (Instance); ++ return Status; ++ } ++ } else { ++ Status = gBS->InstallMultipleProtocolInterfaces ( ++ &Instance->Handle, ++ &gEfiDevicePathProtocolGuid, ++ &Instance->DevicePath, ++ &gEfiBlockIoProtocolGuid, ++ &Instance->BlockIoProtocol, ++ &gEfiDiskIoProtocolGuid, ++ &Instance->DiskIoProtocol, ++ NULL ++ ); ++ if (EFI_ERROR (Status)) { ++ FreePool (Instance); ++ return Status; ++ } ++ } ++ ++ *NorFlashInstance = Instance; ++ return Status; ++} ++ ++/** ++ * This function unlock and erase an entire NOR Flash block. ++ **/ ++EFI_STATUS ++NorFlashUnlockAndEraseSingleBlock ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN UINTN BlockAddress ++ ) ++{ ++ EFI_STATUS Status; ++ UINTN Index; ++ EFI_TPL OriginalTPL; ++ ++ if (!EfiAtRuntime ()) { ++ // Raise TPL to TPL_HIGH to stop anyone from interrupting us. ++ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); ++ } else { ++ // This initialization is only to prevent the compiler to complain about the ++ // use of uninitialized variables ++ OriginalTPL = TPL_HIGH_LEVEL; ++ } ++ ++ Index = 0; ++ // The block erase might fail a first time (SW bug ?). Retry it ... ++ do { ++ // Unlock the block if we have to ++ Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress); ++ if (EFI_ERROR (Status)) { ++ break; ++ } ++ ++ Status = NorFlashEraseSingleBlock (Instance, BlockAddress); ++ Index++; ++ } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED)); ++ ++ if (Index == NOR_FLASH_ERASE_RETRY) { ++ DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index)); ++ } ++ ++ if (!EfiAtRuntime ()) { ++ // Interruptions can resume. ++ gBS->RestoreTPL (OriginalTPL); ++ } ++ ++ return Status; ++} ++ ++EFI_STATUS ++NorFlashWriteFullBlock ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINT32 *DataBuffer, ++ IN UINT32 BlockSizeInWords ++ ) ++{ ++ EFI_STATUS Status; ++ UINTN WordAddress; ++ UINT32 WordIndex; ++ UINTN BufferIndex; ++ UINTN BlockAddress; ++ UINTN BuffersInBlock; ++ UINTN RemainingWords; ++ EFI_TPL OriginalTPL; ++ UINTN Cnt; ++ ++ Status = EFI_SUCCESS; ++ ++ // Get the physical address of the block ++ BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSizeInWords * 4); ++ ++ // Start writing from the first address at the start of the block ++ WordAddress = BlockAddress; ++ ++ if (!EfiAtRuntime ()) { ++ // Raise TPL to TPL_HIGH to stop anyone from interrupting us. ++ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); ++ } else { ++ // This initialization is only to prevent the compiler to complain about the ++ // use of uninitialized variables ++ OriginalTPL = TPL_HIGH_LEVEL; ++ } ++ ++ Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress)); ++ goto EXIT; ++ } ++ ++ // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method. ++ ++ // Check that the address starts at a 32-word boundary, i.e. last 7 bits must be zero ++ if ((WordAddress & BOUNDARY_OF_32_WORDS) == 0x00) { ++ // First, break the entire block into buffer-sized chunks. ++ BuffersInBlock = (UINTN)(BlockSizeInWords * 4) / P30_MAX_BUFFER_SIZE_IN_BYTES; ++ ++ // Then feed each buffer chunk to the NOR Flash ++ // If a buffer does not contain any data, don't write it. ++ for (BufferIndex = 0; ++ BufferIndex < BuffersInBlock; ++ BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS ++ ) ++ { ++ // Check the buffer to see if it contains any data (not set all 1s). ++ for (Cnt = 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) { ++ if (~DataBuffer[Cnt] != 0 ) { ++ // Some data found, write the buffer. ++ Status = NorFlashWriteBuffer ( ++ Instance, ++ WordAddress, ++ P30_MAX_BUFFER_SIZE_IN_BYTES, ++ DataBuffer ++ ); ++ if (EFI_ERROR (Status)) { ++ goto EXIT; ++ } ++ ++ break; ++ } ++ } ++ } ++ ++ // Finally, finish off any remaining words that are less than the maximum size of the buffer ++ RemainingWords = BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS; ++ ++ if (RemainingWords != 0) { ++ Status = NorFlashWriteBuffer (Instance, WordAddress, (RemainingWords * 4), DataBuffer); ++ if (EFI_ERROR (Status)) { ++ goto EXIT; ++ } ++ } ++ } else { ++ // For now, use the single word programming algorithm ++ // It is unlikely that the NOR Flash will exist in an address which falls within a 32 word boundary range, ++ // i.e. which ends in the range 0x......01 - 0x......7F. ++ for (WordIndex = 0; WordIndex < BlockSizeInWords; WordIndex++, DataBuffer++, WordAddress = WordAddress + 4) { ++ Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer); ++ if (EFI_ERROR (Status)) { ++ goto EXIT; ++ } ++ } ++ } ++ ++EXIT: ++ if (!EfiAtRuntime ()) { ++ // Interruptions can resume. ++ gBS->RestoreTPL (OriginalTPL); ++ } ++ ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status)); ++ } ++ ++ return Status; ++} ++ ++EFI_STATUS ++EFIAPI ++NorFlashInitialise ( ++ IN EFI_HANDLE ImageHandle, ++ IN EFI_SYSTEM_TABLE *SystemTable ++ ) ++{ ++ EFI_STATUS Status; ++ UINT32 Index; ++ VIRT_NOR_FLASH_DESCRIPTION *NorFlashDevices; ++ BOOLEAN ContainVariableStorage; ++ ++ Status = VirtNorFlashPlatformInitialization (); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to initialize Nor Flash devices\n")); ++ return Status; ++ } ++ ++ Status = VirtNorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to get Nor Flash devices\n")); ++ return Status; ++ } ++ ++ mNorFlashInstances = AllocateRuntimePool (sizeof (NOR_FLASH_INSTANCE *) * mNorFlashDeviceCount); ++ ++ for (Index = 0; Index < mNorFlashDeviceCount; Index++) { ++ // Check if this NOR Flash device contain the variable storage region ++ ++ if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) { ++ ContainVariableStorage = ++ (NorFlashDevices[Index].RegionBaseAddress <= PcdGet64 (PcdFlashNvStorageVariableBase64)) && ++ (PcdGet64 (PcdFlashNvStorageVariableBase64) + PcdGet32 (PcdFlashNvStorageVariableSize) <= ++ NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size); ++ } else { ++ ContainVariableStorage = ++ (NorFlashDevices[Index].RegionBaseAddress <= PcdGet32 (PcdFlashNvStorageVariableBase)) && ++ (PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvStorageVariableSize) <= ++ NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size); ++ } ++ ++ Status = NorFlashCreateInstance ( ++ NorFlashDevices[Index].DeviceBaseAddress, ++ NorFlashDevices[Index].RegionBaseAddress, ++ NorFlashDevices[Index].Size, ++ Index, ++ NorFlashDevices[Index].BlockSize, ++ ContainVariableStorage, ++ &mNorFlashInstances[Index] ++ ); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to create instance for NorFlash[%d]\n", Index)); ++ } ++ } ++ ++ // ++ // Register for the virtual address change event ++ // ++ Status = gBS->CreateEventEx ( ++ EVT_NOTIFY_SIGNAL, ++ TPL_NOTIFY, ++ NorFlashVirtualNotifyEvent, ++ NULL, ++ &gEfiEventVirtualAddressChangeGuid, ++ &mNorFlashVirtualAddrChangeEvent ++ ); ++ ASSERT_EFI_ERROR (Status); ++ ++ return Status; ++} ++ ++EFI_STATUS ++EFIAPI ++NorFlashFvbInitialize ( ++ IN NOR_FLASH_INSTANCE *Instance ++ ) ++{ ++ EFI_STATUS Status; ++ UINT32 FvbNumLba; ++ EFI_BOOT_MODE BootMode; ++ UINTN RuntimeMmioRegionSize; ++ ++ DEBUG ((DEBUG_BLKIO, "NorFlashFvbInitialize\n")); ++ ASSERT ((Instance != NULL)); ++ ++ // ++ // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME ++ // ++ ++ // Note: all the NOR Flash region needs to be reserved into the UEFI Runtime memory; ++ // even if we only use the small block region at the top of the NOR Flash. ++ // The reason is when the NOR Flash memory is set into program mode, the command ++ // is written as the base of the flash region (ie: Instance->DeviceBaseAddress) ++ RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size; ++ ++ Status = gDS->AddMemorySpace ( ++ EfiGcdMemoryTypeMemoryMappedIo, ++ Instance->DeviceBaseAddress, ++ RuntimeMmioRegionSize, ++ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME ++ ); ++ ASSERT_EFI_ERROR (Status); ++ ++ Status = gDS->SetMemorySpaceAttributes ( ++ Instance->DeviceBaseAddress, ++ RuntimeMmioRegionSize, ++ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME ++ ); ++ ASSERT_EFI_ERROR (Status); ++ ++ mFlashNvStorageVariableBase = (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ? ++ PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase); ++ ++ // Set the index of the first LBA for the FVB ++ Instance->StartLba = (mFlashNvStorageVariableBase - Instance->RegionBaseAddress) / Instance->Media.BlockSize; ++ ++ BootMode = GetBootModeHob (); ++ if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) { ++ Status = EFI_INVALID_PARAMETER; ++ } else { ++ // Determine if there is a valid header at the beginning of the NorFlash ++ Status = ValidateFvHeader (Instance); ++ } ++ ++ // Install the Default FVB header if required ++ if (EFI_ERROR (Status)) { ++ // There is no valid header, so time to install one. ++ DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__)); ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: Installing a correct one for this volume.\n", ++ __FUNCTION__ ++ )); ++ ++ // Erase all the NorFlash that is reserved for variable storage ++ FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize; ++ ++ Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } ++ ++ // Install all appropriate headers ++ Status = InitializeFvAndVariableStoreHeaders (Instance); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } ++ } ++ ++ // ++ // The driver implementing the variable read service can now be dispatched; ++ // the varstore headers are in place. ++ // ++ Status = gBS->InstallProtocolInterface ( ++ &gImageHandle, ++ &gEdkiiNvVarStoreFormattedGuid, ++ EFI_NATIVE_INTERFACE, ++ NULL ++ ); ++ ASSERT_EFI_ERROR (Status); ++ ++ // ++ // Register for the virtual address change event ++ // ++ Status = gBS->CreateEventEx ( ++ EVT_NOTIFY_SIGNAL, ++ TPL_NOTIFY, ++ FvbVirtualNotifyEvent, ++ NULL, ++ &gEfiEventVirtualAddressChangeGuid, ++ &mFvbVirtualAddrChangeEvent ++ ); ++ ASSERT_EFI_ERROR (Status); ++ ++ return Status; ++} +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf +new file mode 100644 +index 0000000000..1bf50e4823 +--- /dev/null ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf +@@ -0,0 +1,72 @@ ++#/** @file ++# ++# Component description file for NorFlashDxe module ++# ++# Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.
++# ++# SPDX-License-Identifier: BSD-2-Clause-Patent ++# ++#**/ ++ ++[Defines] ++ INF_VERSION = 1.29 ++ BASE_NAME = VirtNorFlashDxe ++ FILE_GUID = e452cabd-5fe1-4d97-8161-e80ed6a409a8 ++ MODULE_TYPE = DXE_RUNTIME_DRIVER ++ VERSION_STRING = 1.0 ++ ENTRY_POINT = NorFlashInitialise ++ ++[Sources.common] ++ VirtNorFlash.c ++ VirtNorFlash.h ++ VirtNorFlashBlockIoDxe.c ++ VirtNorFlashDxe.c ++ VirtNorFlashFvb.c ++ ++[Packages] ++ ArmPlatformPkg/ArmPlatformPkg.dec ++ EmbeddedPkg/EmbeddedPkg.dec ++ MdePkg/MdePkg.dec ++ MdeModulePkg/MdeModulePkg.dec ++ OvmfPkg/OvmfPkg.dec ++ ++[LibraryClasses] ++ BaseLib ++ DebugLib ++ DxeServicesTableLib ++ HobLib ++ IoLib ++ UefiBootServicesTableLib ++ UefiDriverEntryPoint ++ UefiLib ++ UefiRuntimeLib ++ VirtNorFlashPlatformLib ++ ++[Guids] ++ gEdkiiNvVarStoreFormattedGuid ## PRODUCES ## PROTOCOL ++ gEfiAuthenticatedVariableGuid ++ gEfiEventVirtualAddressChangeGuid ++ gEfiSystemNvDataFvGuid ++ gEfiVariableGuid ++ ++[Protocols] ++ gEfiBlockIoProtocolGuid ++ gEfiDevicePathProtocolGuid ++ gEfiDiskIoProtocolGuid ++ gEfiFirmwareVolumeBlockProtocolGuid ++ ++[Pcd.common] ++ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 ++ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ++ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ++ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 ++ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase ++ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize ++ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 ++ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase ++ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize ++ ++ gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked ++ ++[Depex] ++ gEfiCpuArchProtocolGuid +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +new file mode 100644 +index 0000000000..c824e0a0fb +--- /dev/null ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +@@ -0,0 +1,777 @@ ++/*++ @file NorFlashFvbDxe.c ++ ++ Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++ --*/ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "VirtNorFlash.h" ++ ++extern UINTN mFlashNvStorageVariableBase; ++/// ++/// The Firmware Volume Block Protocol is the low-level interface ++/// to a firmware volume. File-level access to a firmware volume ++/// should not be done using the Firmware Volume Block Protocol. ++/// Normal access to a firmware volume must use the Firmware ++/// Volume Protocol. Typically, only the file system driver that ++/// produces the Firmware Volume Protocol will bind to the ++/// Firmware Volume Block Protocol. ++/// ++ ++/** ++ Initialises the FV Header and Variable Store Header ++ to support variable operations. ++ ++ @param[in] Ptr - Location to initialise the headers ++ ++**/ ++EFI_STATUS ++InitializeFvAndVariableStoreHeaders ( ++ IN NOR_FLASH_INSTANCE *Instance ++ ) ++{ ++ EFI_STATUS Status; ++ VOID *Headers; ++ UINTN HeadersLength; ++ EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader; ++ VARIABLE_STORE_HEADER *VariableStoreHeader; ++ UINT32 NvStorageFtwSpareSize; ++ UINT32 NvStorageFtwWorkingSize; ++ UINT32 NvStorageVariableSize; ++ UINT64 NvStorageFtwSpareBase; ++ UINT64 NvStorageFtwWorkingBase; ++ UINT64 NvStorageVariableBase; ++ ++ HeadersLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY) + sizeof (VARIABLE_STORE_HEADER); ++ Headers = AllocateZeroPool (HeadersLength); ++ ++ NvStorageFtwWorkingSize = PcdGet32 (PcdFlashNvStorageFtwWorkingSize); ++ NvStorageFtwSpareSize = PcdGet32 (PcdFlashNvStorageFtwSpareSize); ++ NvStorageVariableSize = PcdGet32 (PcdFlashNvStorageVariableSize); ++ ++ NvStorageFtwSpareBase = (PcdGet64 (PcdFlashNvStorageFtwSpareBase64) != 0) ? ++ PcdGet64 (PcdFlashNvStorageFtwSpareBase64) : PcdGet32 (PcdFlashNvStorageFtwSpareBase); ++ NvStorageFtwWorkingBase = (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) != 0) ? ++ PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) : PcdGet32 (PcdFlashNvStorageFtwWorkingBase); ++ NvStorageVariableBase = (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ? ++ PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase); ++ ++ // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous. ++ if ((NvStorageVariableBase + NvStorageVariableSize) != NvStorageFtwWorkingBase) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: NvStorageFtwWorkingBase is not contiguous with NvStorageVariableBase region\n", ++ __FUNCTION__ ++ )); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((NvStorageFtwWorkingBase + NvStorageFtwWorkingSize) != NvStorageFtwSpareBase) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: NvStorageFtwSpareBase is not contiguous with NvStorageFtwWorkingBase region\n", ++ __FUNCTION__ ++ )); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // Check if the size of the area is at least one block size ++ if ((NvStorageVariableSize <= 0) || (NvStorageVariableSize / Instance->Media.BlockSize <= 0)) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: NvStorageVariableSize is 0x%x, should be atleast one block size\n", ++ __FUNCTION__, ++ NvStorageVariableSize ++ )); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((NvStorageFtwWorkingSize <= 0) || (NvStorageFtwWorkingSize / Instance->Media.BlockSize <= 0)) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: NvStorageFtwWorkingSize is 0x%x, should be atleast one block size\n", ++ __FUNCTION__, ++ NvStorageFtwWorkingSize ++ )); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((NvStorageFtwSpareSize <= 0) || (NvStorageFtwSpareSize / Instance->Media.BlockSize <= 0)) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: NvStorageFtwSpareSize is 0x%x, should be atleast one block size\n", ++ __FUNCTION__, ++ NvStorageFtwSpareSize ++ )); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // Ensure the Variable area Base Addresses are aligned on a block size boundaries ++ if ((NvStorageVariableBase % Instance->Media.BlockSize != 0) || ++ (NvStorageFtwWorkingBase % Instance->Media.BlockSize != 0) || ++ (NvStorageFtwSpareBase % Instance->Media.BlockSize != 0)) ++ { ++ DEBUG ((DEBUG_ERROR, "%a: NvStorage Base addresses must be aligned to block size boundaries", __FUNCTION__)); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // EFI_FIRMWARE_VOLUME_HEADER ++ // ++ FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Headers; ++ CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid); ++ FirmwareVolumeHeader->FvLength = ++ PcdGet32 (PcdFlashNvStorageVariableSize) + ++ PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + ++ PcdGet32 (PcdFlashNvStorageFtwSpareSize); ++ FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE; ++ FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2)( ++ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled ++ EFI_FVB2_READ_STATUS | // Reads are currently enabled ++ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY ++ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped ++ EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1') ++ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled ++ EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled ++ ); ++ FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY); ++ FirmwareVolumeHeader->Revision = EFI_FVH_REVISION; ++ FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1; ++ FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize; ++ FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0; ++ FirmwareVolumeHeader->BlockMap[1].Length = 0; ++ FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16 *)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength); ++ ++ // ++ // VARIABLE_STORE_HEADER ++ // ++ VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength); ++ CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid); ++ VariableStoreHeader->Size = PcdGet32 (PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength; ++ VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED; ++ VariableStoreHeader->State = VARIABLE_STORE_HEALTHY; ++ ++ // Install the combined super-header in the NorFlash ++ Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers); ++ ++ FreePool (Headers); ++ return Status; ++} ++ ++/** ++ Check the integrity of firmware volume header. ++ ++ @param[in] FwVolHeader - A pointer to a firmware volume header ++ ++ @retval EFI_SUCCESS - The firmware volume is consistent ++ @retval EFI_NOT_FOUND - The firmware volume has been corrupted. ++ ++**/ ++EFI_STATUS ++ValidateFvHeader ( ++ IN NOR_FLASH_INSTANCE *Instance ++ ) ++{ ++ UINT16 Checksum; ++ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; ++ VARIABLE_STORE_HEADER *VariableStoreHeader; ++ UINTN VariableStoreLength; ++ UINTN FvLength; ++ ++ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Instance->RegionBaseAddress; ++ ++ FvLength = PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + ++ PcdGet32 (PcdFlashNvStorageFtwSpareSize); ++ ++ // ++ // Verify the header revision, header signature, length ++ // Length of FvBlock cannot be 2**64-1 ++ // HeaderLength cannot be an odd number ++ // ++ if ( (FwVolHeader->Revision != EFI_FVH_REVISION) ++ || (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ++ || (FwVolHeader->FvLength != FvLength) ++ ) ++ { ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: No Firmware Volume header present\n", ++ __FUNCTION__ ++ )); ++ return EFI_NOT_FOUND; ++ } ++ ++ // Check the Firmware Volume Guid ++ if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) { ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: Firmware Volume Guid non-compatible\n", ++ __FUNCTION__ ++ )); ++ return EFI_NOT_FOUND; ++ } ++ ++ // Verify the header checksum ++ Checksum = CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength); ++ if (Checksum != 0) { ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: FV checksum is invalid (Checksum:0x%X)\n", ++ __FUNCTION__, ++ Checksum ++ )); ++ return EFI_NOT_FOUND; ++ } ++ ++ VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)FwVolHeader + FwVolHeader->HeaderLength); ++ ++ // Check the Variable Store Guid ++ if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) && ++ !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) ++ { ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: Variable Store Guid non-compatible\n", ++ __FUNCTION__ ++ )); ++ return EFI_NOT_FOUND; ++ } ++ ++ VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength; ++ if (VariableStoreHeader->Size != VariableStoreLength) { ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: Variable Store Length does not match\n", ++ __FUNCTION__ ++ )); ++ return EFI_NOT_FOUND; ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ The GetAttributes() function retrieves the attributes and ++ current settings of the block. ++ ++ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. ++ ++ @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and ++ current settings are returned. ++ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER. ++ ++ @retval EFI_SUCCESS The firmware volume attributes were returned. ++ ++ **/ ++EFI_STATUS ++EFIAPI ++FvbGetAttributes ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ OUT EFI_FVB_ATTRIBUTES_2 *Attributes ++ ) ++{ ++ EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes; ++ NOR_FLASH_INSTANCE *Instance; ++ ++ Instance = INSTANCE_FROM_FVB_THIS (This); ++ ++ FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2)( ++ ++ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled ++ EFI_FVB2_READ_STATUS | // Reads are currently enabled ++ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY ++ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped ++ EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1') ++ ++ ); ++ ++ // Check if it is write protected ++ if (Instance->Media.ReadOnly != TRUE) { ++ FlashFvbAttributes = FlashFvbAttributes | ++ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled ++ EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled ++ } ++ ++ *Attributes = FlashFvbAttributes; ++ ++ DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes)); ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ The SetAttributes() function sets configurable firmware volume attributes ++ and returns the new settings of the firmware volume. ++ ++ ++ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. ++ ++ @param Attributes On input, Attributes is a pointer to EFI_FVB_ATTRIBUTES_2 ++ that contains the desired firmware volume settings. ++ On successful return, it contains the new settings of ++ the firmware volume. ++ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER. ++ ++ @retval EFI_SUCCESS The firmware volume attributes were returned. ++ ++ @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with the capabilities ++ as declared in the firmware volume header. ++ ++ **/ ++EFI_STATUS ++EFIAPI ++FvbSetAttributes ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes ++ ) ++{ ++ DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n", *Attributes)); ++ return EFI_UNSUPPORTED; ++} ++ ++/** ++ The GetPhysicalAddress() function retrieves the base address of ++ a memory-mapped firmware volume. This function should be called ++ only for memory-mapped firmware volumes. ++ ++ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. ++ ++ @param Address Pointer to a caller-allocated ++ EFI_PHYSICAL_ADDRESS that, on successful ++ return from GetPhysicalAddress(), contains the ++ base address of the firmware volume. ++ ++ @retval EFI_SUCCESS The firmware volume base address was returned. ++ ++ @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped. ++ ++ **/ ++EFI_STATUS ++EFIAPI ++FvbGetPhysicalAddress ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ OUT EFI_PHYSICAL_ADDRESS *Address ++ ) ++{ ++ NOR_FLASH_INSTANCE *Instance; ++ ++ Instance = INSTANCE_FROM_FVB_THIS (This); ++ ++ DEBUG ((DEBUG_BLKIO, "FvbGetPhysicalAddress(BaseAddress=0x%08x)\n", Instance->RegionBaseAddress)); ++ ++ ASSERT (Address != NULL); ++ ++ *Address = mFlashNvStorageVariableBase; ++ return EFI_SUCCESS; ++} ++ ++/** ++ The GetBlockSize() function retrieves the size of the requested ++ block. It also returns the number of additional blocks with ++ the identical size. The GetBlockSize() function is used to ++ retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER). ++ ++ ++ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. ++ ++ @param Lba Indicates the block for which to return the size. ++ ++ @param BlockSize Pointer to a caller-allocated UINTN in which ++ the size of the block is returned. ++ ++ @param NumberOfBlocks Pointer to a caller-allocated UINTN in ++ which the number of consecutive blocks, ++ starting with Lba, is returned. All ++ blocks in this range have a size of ++ BlockSize. ++ ++ ++ @retval EFI_SUCCESS The firmware volume base address was returned. ++ ++ @retval EFI_INVALID_PARAMETER The requested LBA is out of range. ++ ++ **/ ++EFI_STATUS ++EFIAPI ++FvbGetBlockSize ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ IN EFI_LBA Lba, ++ OUT UINTN *BlockSize, ++ OUT UINTN *NumberOfBlocks ++ ) ++{ ++ EFI_STATUS Status; ++ NOR_FLASH_INSTANCE *Instance; ++ ++ Instance = INSTANCE_FROM_FVB_THIS (This); ++ ++ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->Media.BlockSize, Instance->Media.LastBlock)); ++ ++ if (Lba > Instance->Media.LastBlock) { ++ DEBUG ((DEBUG_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->Media.LastBlock)); ++ Status = EFI_INVALID_PARAMETER; ++ } else { ++ // This is easy because in this platform each NorFlash device has equal sized blocks. ++ *BlockSize = (UINTN)Instance->Media.BlockSize; ++ *NumberOfBlocks = (UINTN)(Instance->Media.LastBlock - Lba + 1); ++ ++ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize, *NumberOfBlocks)); ++ ++ Status = EFI_SUCCESS; ++ } ++ ++ return Status; ++} ++ ++/** ++ Reads the specified number of bytes into a buffer from the specified block. ++ ++ The Read() function reads the requested number of bytes from the ++ requested block and stores them in the provided buffer. ++ Implementations should be mindful that the firmware volume ++ might be in the ReadDisabled state. If it is in this state, ++ the Read() function must return the status code ++ EFI_ACCESS_DENIED without modifying the contents of the ++ buffer. The Read() function must also prevent spanning block ++ boundaries. If a read is requested that would span a block ++ boundary, the read must read up to the boundary but not ++ beyond. The output parameter NumBytes must be set to correctly ++ indicate the number of bytes actually read. The caller must be ++ aware that a read may be partially completed. ++ ++ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. ++ ++ @param Lba The starting logical block index from which to read. ++ ++ @param Offset Offset into the block at which to begin reading. ++ ++ @param NumBytes Pointer to a UINTN. ++ At entry, *NumBytes contains the total size of the buffer. ++ At exit, *NumBytes contains the total number of bytes read. ++ ++ @param Buffer Pointer to a caller-allocated buffer that will be used ++ to hold the data that is read. ++ ++ @retval EFI_SUCCESS The firmware volume was read successfully, and contents are ++ in Buffer. ++ ++ @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary. ++ On output, NumBytes contains the total number of bytes ++ returned in Buffer. ++ ++ @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state. ++ ++ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be read. ++ ++ **/ ++EFI_STATUS ++EFIAPI ++FvbRead ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ IN EFI_LBA Lba, ++ IN UINTN Offset, ++ IN OUT UINTN *NumBytes, ++ IN OUT UINT8 *Buffer ++ ) ++{ ++ EFI_STATUS TempStatus; ++ UINTN BlockSize; ++ NOR_FLASH_INSTANCE *Instance; ++ ++ Instance = INSTANCE_FROM_FVB_THIS (This); ++ ++ DEBUG ((DEBUG_BLKIO, "FvbRead(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Instance->StartLba + Lba, Offset, *NumBytes, Buffer)); ++ ++ TempStatus = EFI_SUCCESS; ++ ++ // Cache the block size to avoid de-referencing pointers all the time ++ BlockSize = Instance->Media.BlockSize; ++ ++ DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", Offset, *NumBytes, BlockSize)); ++ ++ // The read must not span block boundaries. ++ // We need to check each variable individually because adding two large values together overflows. ++ if ((Offset >= BlockSize) || ++ (*NumBytes > BlockSize) || ++ ((Offset + *NumBytes) > BlockSize)) ++ { ++ DEBUG ((DEBUG_ERROR, "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize)); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // We must have some bytes to read ++ if (*NumBytes == 0) { ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // Decide if we are doing full block reads or not. ++ if (*NumBytes % BlockSize != 0) { ++ TempStatus = NorFlashRead (Instance, Instance->StartLba + Lba, Offset, *NumBytes, Buffer); ++ if (EFI_ERROR (TempStatus)) { ++ return EFI_DEVICE_ERROR; ++ } ++ } else { ++ // Read NOR Flash data into shadow buffer ++ TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Buffer); ++ if (EFI_ERROR (TempStatus)) { ++ // Return one of the pre-approved error statuses ++ return EFI_DEVICE_ERROR; ++ } ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ Writes the specified number of bytes from the input buffer to the block. ++ ++ The Write() function writes the specified number of bytes from ++ the provided buffer to the specified block and offset. If the ++ firmware volume is sticky write, the caller must ensure that ++ all the bits of the specified range to write are in the ++ EFI_FVB_ERASE_POLARITY state before calling the Write() ++ function, or else the result will be unpredictable. This ++ unpredictability arises because, for a sticky-write firmware ++ volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY ++ state but cannot flip it back again. Before calling the ++ Write() function, it is recommended for the caller to first call ++ the EraseBlocks() function to erase the specified block to ++ write. A block erase cycle will transition bits from the ++ (NOT)EFI_FVB_ERASE_POLARITY state back to the ++ EFI_FVB_ERASE_POLARITY state. Implementations should be ++ mindful that the firmware volume might be in the WriteDisabled ++ state. If it is in this state, the Write() function must ++ return the status code EFI_ACCESS_DENIED without modifying the ++ contents of the firmware volume. The Write() function must ++ also prevent spanning block boundaries. If a write is ++ requested that spans a block boundary, the write must store up ++ to the boundary but not beyond. The output parameter NumBytes ++ must be set to correctly indicate the number of bytes actually ++ written. The caller must be aware that a write may be ++ partially completed. All writes, partial or otherwise, must be ++ fully flushed to the hardware before the Write() service ++ returns. ++ ++ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. ++ ++ @param Lba The starting logical block index to write to. ++ ++ @param Offset Offset into the block at which to begin writing. ++ ++ @param NumBytes The pointer to a UINTN. ++ At entry, *NumBytes contains the total size of the buffer. ++ At exit, *NumBytes contains the total number of bytes actually written. ++ ++ @param Buffer The pointer to a caller-allocated buffer that contains the source for the write. ++ ++ @retval EFI_SUCCESS The firmware volume was written successfully. ++ ++ @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary. ++ On output, NumBytes contains the total number of bytes ++ actually written. ++ ++ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state. ++ ++ @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be written. ++ ++ ++ **/ ++EFI_STATUS ++EFIAPI ++FvbWrite ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ IN EFI_LBA Lba, ++ IN UINTN Offset, ++ IN OUT UINTN *NumBytes, ++ IN UINT8 *Buffer ++ ) ++{ ++ NOR_FLASH_INSTANCE *Instance; ++ ++ Instance = INSTANCE_FROM_FVB_THIS (This); ++ ++ return NorFlashWriteSingleBlock (Instance, Instance->StartLba + Lba, Offset, NumBytes, Buffer); ++} ++ ++/** ++ Erases and initialises a firmware volume block. ++ ++ The EraseBlocks() function erases one or more blocks as denoted ++ by the variable argument list. The entire parameter list of ++ blocks must be verified before erasing any blocks. If a block is ++ requested that does not exist within the associated firmware ++ volume (it has a larger index than the last block of the ++ firmware volume), the EraseBlocks() function must return the ++ status code EFI_INVALID_PARAMETER without modifying the contents ++ of the firmware volume. Implementations should be mindful that ++ the firmware volume might be in the WriteDisabled state. If it ++ is in this state, the EraseBlocks() function must return the ++ status code EFI_ACCESS_DENIED without modifying the contents of ++ the firmware volume. All calls to EraseBlocks() must be fully ++ flushed to the hardware before the EraseBlocks() service ++ returns. ++ ++ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL ++ instance. ++ ++ @param ... The variable argument list is a list of tuples. ++ Each tuple describes a range of LBAs to erase ++ and consists of the following: ++ - An EFI_LBA that indicates the starting LBA ++ - A UINTN that indicates the number of blocks to erase. ++ ++ The list is terminated with an EFI_LBA_LIST_TERMINATOR. ++ For example, the following indicates that two ranges of blocks ++ (5-7 and 10-11) are to be erased: ++ EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR); ++ ++ @retval EFI_SUCCESS The erase request successfully completed. ++ ++ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state. ++ ++ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written. ++ The firmware device may have been partially erased. ++ ++ @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable argument list do ++ not exist in the firmware volume. ++ ++ **/ ++EFI_STATUS ++EFIAPI ++FvbEraseBlocks ( ++ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ++ ... ++ ) ++{ ++ EFI_STATUS Status; ++ VA_LIST Args; ++ UINTN BlockAddress; // Physical address of Lba to erase ++ EFI_LBA StartingLba; // Lba from which we start erasing ++ UINTN NumOfLba; // Number of Lba blocks to erase ++ NOR_FLASH_INSTANCE *Instance; ++ ++ Instance = INSTANCE_FROM_FVB_THIS (This); ++ ++ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks()\n")); ++ ++ Status = EFI_SUCCESS; ++ ++ // Detect WriteDisabled state ++ if (Instance->Media.ReadOnly == TRUE) { ++ // Firmware volume is in WriteDisabled state ++ DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n")); ++ return EFI_ACCESS_DENIED; ++ } ++ ++ // Before erasing, check the entire list of parameters to ensure all specified blocks are valid ++ ++ VA_START (Args, This); ++ do { ++ // Get the Lba from which we start erasing ++ StartingLba = VA_ARG (Args, EFI_LBA); ++ ++ // Have we reached the end of the list? ++ if (StartingLba == EFI_LBA_LIST_TERMINATOR) { ++ // Exit the while loop ++ break; ++ } ++ ++ // How many Lba blocks are we requested to erase? ++ NumOfLba = VA_ARG (Args, UINTN); ++ ++ // All blocks must be within range ++ DEBUG (( ++ DEBUG_BLKIO, ++ "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%Lu - 1 ) > LastBlock=%ld.\n", ++ Instance->StartLba + StartingLba, ++ (UINT64)NumOfLba, ++ Instance->Media.LastBlock ++ )); ++ if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->Media.LastBlock)) { ++ VA_END (Args); ++ DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n")); ++ Status = EFI_INVALID_PARAMETER; ++ goto EXIT; ++ } ++ } while (TRUE); ++ ++ VA_END (Args); ++ ++ // ++ // To get here, all must be ok, so start erasing ++ // ++ VA_START (Args, This); ++ do { ++ // Get the Lba from which we start erasing ++ StartingLba = VA_ARG (Args, EFI_LBA); ++ ++ // Have we reached the end of the list? ++ if (StartingLba == EFI_LBA_LIST_TERMINATOR) { ++ // Exit the while loop ++ break; ++ } ++ ++ // How many Lba blocks are we requested to erase? ++ NumOfLba = VA_ARG (Args, UINTN); ++ ++ // Go through each one and erase it ++ while (NumOfLba > 0) { ++ // Get the physical address of Lba to erase ++ BlockAddress = GET_NOR_BLOCK_ADDRESS ( ++ Instance->RegionBaseAddress, ++ Instance->StartLba + StartingLba, ++ Instance->Media.BlockSize ++ ); ++ ++ // Erase it ++ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", Instance->StartLba + StartingLba, BlockAddress)); ++ Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress); ++ if (EFI_ERROR (Status)) { ++ VA_END (Args); ++ Status = EFI_DEVICE_ERROR; ++ goto EXIT; ++ } ++ ++ // Move to the next Lba ++ StartingLba++; ++ NumOfLba--; ++ } ++ } while (TRUE); ++ ++ VA_END (Args); ++ ++EXIT: ++ return Status; ++} ++ ++/** ++ Fixup internal data so that EFI can be call in virtual mode. ++ Call the passed in Child Notify event and convert any pointers in ++ lib to virtual mode. ++ ++ @param[in] Event The Event that is being processed ++ @param[in] Context Event Context ++**/ ++VOID ++EFIAPI ++FvbVirtualNotifyEvent ( ++ IN EFI_EVENT Event, ++ IN VOID *Context ++ ) ++{ ++ EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase); ++ return; ++} +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-drop-block-I-O-protocol-impl.patch b/edk2-OvmfPkg-VirtNorFlashDxe-drop-block-I-O-protocol-impl.patch new file mode 100644 index 0000000..e8c0128 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-drop-block-I-O-protocol-impl.patch @@ -0,0 +1,504 @@ +From 8cf16599ade30de07c9b51f90d2208046f74fee6 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 24 Oct 2022 17:12:08 +0200 +Subject: [PATCH 04/18] OvmfPkg/VirtNorFlashDxe: drop block I/O protocol + implementation + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [6/20] 6843078997a30c2818e0d53a90fb7f6accb89aaf + +We never boot from NOR flash, and generally rely on the firmware volume +PI protocols to expose the contents. So drop the block I/O protocol +implementation from VirtNorFlashDxe. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Sunil V L +(cherry picked from commit 83f11f957240ead9b135a778316330762b0a3acb) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 49 ++++++------------ + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h | 54 ++------------------ + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 40 +++------------ + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf | 1 - + OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c | 55 ++++++++------------- + 5 files changed, 45 insertions(+), 154 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 1094d48f7d..f41d9d372f 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -366,10 +366,6 @@ NorFlashWriteBlocks ( + return EFI_INVALID_PARAMETER; + } + +- if (Instance->Media.ReadOnly == TRUE) { +- return EFI_WRITE_PROTECTED; +- } +- + // We must have some bytes to read + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", BufferSizeInBytes)); + if (BufferSizeInBytes == 0) { +@@ -377,22 +373,22 @@ NorFlashWriteBlocks ( + } + + // The size of the buffer must be a multiple of the block size +- DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->Media.BlockSize)); +- if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) { ++ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->BlockSize)); ++ if ((BufferSizeInBytes % Instance->BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + // All blocks must be within the device +- NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize; ++ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize; + +- DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba)); ++ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->LastBlock, Lba)); + +- if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) { ++ if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) { + DEBUG ((DEBUG_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n")); + return EFI_INVALID_PARAMETER; + } + +- BlockSizeInWords = Instance->Media.BlockSize / 4; ++ BlockSizeInWords = Instance->BlockSize / 4; + + // Because the target *Buffer is a pointer to VOID, we must put all the data into a pointer + // to a proper data type, so use *ReadBuffer +@@ -489,8 +485,8 @@ NorFlashReadBlocks ( + DEBUG_BLKIO, + "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n", + BufferSizeInBytes, +- Instance->Media.BlockSize, +- Instance->Media.LastBlock, ++ Instance->BlockSize, ++ Instance->LastBlock, + Lba + )); + +@@ -505,14 +501,14 @@ NorFlashReadBlocks ( + } + + // The size of the buffer must be a multiple of the block size +- if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) { ++ if ((BufferSizeInBytes % Instance->BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + // All blocks must be within the device +- NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize; ++ NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize; + +- if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) { ++ if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) { + DEBUG ((DEBUG_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed last block\n")); + return EFI_INVALID_PARAMETER; + } +@@ -521,7 +517,7 @@ NorFlashReadBlocks ( + StartAddress = GET_NOR_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + Lba, +- Instance->Media.BlockSize ++ Instance->BlockSize + ); + + // Put the device into Read Array mode +@@ -554,7 +550,7 @@ NorFlashRead ( + return EFI_SUCCESS; + } + +- if (((Lba * Instance->Media.BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) { ++ if (((Lba * Instance->BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) { + DEBUG ((DEBUG_ERROR, "NorFlashRead: ERROR - Read will exceed device size.\n")); + return EFI_INVALID_PARAMETER; + } +@@ -563,7 +559,7 @@ NorFlashRead ( + StartAddress = GET_NOR_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + Lba, +- Instance->Media.BlockSize ++ Instance->BlockSize + ); + + // Put the device into Read Array mode +@@ -577,7 +573,7 @@ NorFlashRead ( + + /* + Write a full or portion of a block. It must not span block boundaries; that is, +- Offset + *NumBytes <= Instance->Media.BlockSize. ++ Offset + *NumBytes <= Instance->BlockSize. + */ + EFI_STATUS + NorFlashWriteSingleBlock ( +@@ -605,15 +601,8 @@ NorFlashWriteSingleBlock ( + + DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer)); + +- // Detect WriteDisabled state +- if (Instance->Media.ReadOnly == TRUE) { +- DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - Can not write: Device is in WriteDisabled state.\n")); +- // It is in WriteDisabled state, return an error right away +- return EFI_ACCESS_DENIED; +- } +- + // Cache the block size to avoid de-referencing pointers all the time +- BlockSize = Instance->Media.BlockSize; ++ BlockSize = Instance->BlockSize; + + // The write must not span block boundaries. + // We need to check each variable individually because adding two large values together overflows. +@@ -819,12 +808,6 @@ NorFlashVirtualNotifyEvent ( + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->DeviceBaseAddress); + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->RegionBaseAddress); + +- // Convert BlockIo protocol +- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.FlushBlocks); +- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.ReadBlocks); +- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.Reset); +- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->BlockIoProtocol.WriteBlocks); +- + // Convert Fvb + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks); + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes); +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +index 7733ee02ee..b7f5d208b2 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +@@ -14,7 +14,6 @@ + + #include + +-#include + #include + + #include +@@ -108,8 +107,7 @@ + #define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003 + + #define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0') +-#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE) +-#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE) ++#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE) + + typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE; + +@@ -129,9 +127,8 @@ struct _NOR_FLASH_INSTANCE { + UINTN RegionBaseAddress; + UINTN Size; + EFI_LBA StartLba; +- +- EFI_BLOCK_IO_PROTOCOL BlockIoProtocol; +- EFI_BLOCK_IO_MEDIA Media; ++ EFI_LBA LastBlock; ++ UINT32 BlockSize; + + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; + VOID *ShadowBuffer; +@@ -155,51 +152,6 @@ NorFlashWriteBuffer ( + IN UINT32 *Buffer + ); + +-// +-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset +-// +-EFI_STATUS +-EFIAPI +-NorFlashBlockIoReset ( +- IN EFI_BLOCK_IO_PROTOCOL *This, +- IN BOOLEAN ExtendedVerification +- ); +- +-// +-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks +-// +-EFI_STATUS +-EFIAPI +-NorFlashBlockIoReadBlocks ( +- IN EFI_BLOCK_IO_PROTOCOL *This, +- IN UINT32 MediaId, +- IN EFI_LBA Lba, +- IN UINTN BufferSizeInBytes, +- OUT VOID *Buffer +- ); +- +-// +-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks +-// +-EFI_STATUS +-EFIAPI +-NorFlashBlockIoWriteBlocks ( +- IN EFI_BLOCK_IO_PROTOCOL *This, +- IN UINT32 MediaId, +- IN EFI_LBA Lba, +- IN UINTN BufferSizeInBytes, +- IN VOID *Buffer +- ); +- +-// +-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks +-// +-EFI_STATUS +-EFIAPI +-NorFlashBlockIoFlushBlocks ( +- IN EFI_BLOCK_IO_PROTOCOL *This +- ); +- + // + // NorFlashFvbDxe.c + // +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +index 4875b057d5..2ceda22635 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +@@ -34,29 +34,8 @@ NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = { + 0, // RegionBaseAddress ... NEED TO BE FILLED + 0, // Size ... NEED TO BE FILLED + 0, // StartLba +- +- { +- EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision +- NULL, // Media ... NEED TO BE FILLED +- NorFlashBlockIoReset, // Reset; +- NorFlashBlockIoReadBlocks, // ReadBlocks +- NorFlashBlockIoWriteBlocks, // WriteBlocks +- NorFlashBlockIoFlushBlocks // FlushBlocks +- }, // BlockIoProtocol +- +- { +- 0, // MediaId ... NEED TO BE FILLED +- FALSE, // RemovableMedia +- TRUE, // MediaPresent +- FALSE, // LogicalPartition +- FALSE, // ReadOnly +- FALSE, // WriteCaching; +- 0, // BlockSize ... NEED TO BE FILLED +- 4, // IoAlign +- 0, // LastBlock ... NEED TO BE FILLED +- 0, // LowestAlignedLba +- 1, // LogicalBlocksPerPhysicalBlock +- }, // Media; ++ 0, // LastBlock ++ 0, // BlockSize + + { + FvbGetAttributes, // GetAttributes +@@ -115,11 +94,8 @@ NorFlashCreateInstance ( + Instance->DeviceBaseAddress = NorFlashDeviceBase; + Instance->RegionBaseAddress = NorFlashRegionBase; + Instance->Size = NorFlashSize; +- +- Instance->BlockIoProtocol.Media = &Instance->Media; +- Instance->Media.MediaId = Index; +- Instance->Media.BlockSize = BlockSize; +- Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1; ++ Instance->BlockSize = BlockSize; ++ Instance->LastBlock = (NorFlashSize / BlockSize) - 1; + + CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid); + Instance->DevicePath.Index = (UINT8)Index; +@@ -136,8 +112,6 @@ NorFlashCreateInstance ( + &Instance->Handle, + &gEfiDevicePathProtocolGuid, + &Instance->DevicePath, +- &gEfiBlockIoProtocolGuid, +- &Instance->BlockIoProtocol, + &gEfiFirmwareVolumeBlockProtocolGuid, + &Instance->FvbProtocol, + NULL +@@ -151,8 +125,6 @@ NorFlashCreateInstance ( + &Instance->Handle, + &gEfiDevicePathProtocolGuid, + &Instance->DevicePath, +- &gEfiBlockIoProtocolGuid, +- &Instance->BlockIoProtocol, + NULL + ); + if (EFI_ERROR (Status)) { +@@ -434,7 +406,7 @@ NorFlashFvbInitialize ( + PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase); + + // Set the index of the first LBA for the FVB +- Instance->StartLba = (mFlashNvStorageVariableBase - Instance->RegionBaseAddress) / Instance->Media.BlockSize; ++ Instance->StartLba = (mFlashNvStorageVariableBase - Instance->RegionBaseAddress) / Instance->BlockSize; + + BootMode = GetBootModeHob (); + if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) { +@@ -455,7 +427,7 @@ NorFlashFvbInitialize ( + )); + + // Erase all the NorFlash that is reserved for variable storage +- FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize; ++ FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->BlockSize; + + Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR); + if (EFI_ERROR (Status)) { +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf +index 53e9d58204..2a3d4a218e 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf +@@ -19,7 +19,6 @@ + [Sources.common] + VirtNorFlash.c + VirtNorFlash.h +- VirtNorFlashBlockIoDxe.c + VirtNorFlashDxe.c + VirtNorFlashFvb.c + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +index c824e0a0fb..cc5eefaaf3 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +@@ -89,7 +89,7 @@ InitializeFvAndVariableStoreHeaders ( + } + + // Check if the size of the area is at least one block size +- if ((NvStorageVariableSize <= 0) || (NvStorageVariableSize / Instance->Media.BlockSize <= 0)) { ++ if ((NvStorageVariableSize <= 0) || (NvStorageVariableSize / Instance->BlockSize <= 0)) { + DEBUG (( + DEBUG_ERROR, + "%a: NvStorageVariableSize is 0x%x, should be atleast one block size\n", +@@ -99,7 +99,7 @@ InitializeFvAndVariableStoreHeaders ( + return EFI_INVALID_PARAMETER; + } + +- if ((NvStorageFtwWorkingSize <= 0) || (NvStorageFtwWorkingSize / Instance->Media.BlockSize <= 0)) { ++ if ((NvStorageFtwWorkingSize <= 0) || (NvStorageFtwWorkingSize / Instance->BlockSize <= 0)) { + DEBUG (( + DEBUG_ERROR, + "%a: NvStorageFtwWorkingSize is 0x%x, should be atleast one block size\n", +@@ -109,7 +109,7 @@ InitializeFvAndVariableStoreHeaders ( + return EFI_INVALID_PARAMETER; + } + +- if ((NvStorageFtwSpareSize <= 0) || (NvStorageFtwSpareSize / Instance->Media.BlockSize <= 0)) { ++ if ((NvStorageFtwSpareSize <= 0) || (NvStorageFtwSpareSize / Instance->BlockSize <= 0)) { + DEBUG (( + DEBUG_ERROR, + "%a: NvStorageFtwSpareSize is 0x%x, should be atleast one block size\n", +@@ -120,9 +120,9 @@ InitializeFvAndVariableStoreHeaders ( + } + + // Ensure the Variable area Base Addresses are aligned on a block size boundaries +- if ((NvStorageVariableBase % Instance->Media.BlockSize != 0) || +- (NvStorageFtwWorkingBase % Instance->Media.BlockSize != 0) || +- (NvStorageFtwSpareBase % Instance->Media.BlockSize != 0)) ++ if ((NvStorageVariableBase % Instance->BlockSize != 0) || ++ (NvStorageFtwWorkingBase % Instance->BlockSize != 0) || ++ (NvStorageFtwSpareBase % Instance->BlockSize != 0)) + { + DEBUG ((DEBUG_ERROR, "%a: NvStorage Base addresses must be aligned to block size boundaries", __FUNCTION__)); + return EFI_INVALID_PARAMETER; +@@ -149,8 +149,8 @@ InitializeFvAndVariableStoreHeaders ( + ); + FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY); + FirmwareVolumeHeader->Revision = EFI_FVH_REVISION; +- FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1; +- FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize; ++ FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->LastBlock + 1; ++ FirmwareVolumeHeader->BlockMap[0].Length = Instance->BlockSize; + FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0; + FirmwareVolumeHeader->BlockMap[1].Length = 0; + FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16 *)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength); +@@ -284,9 +284,6 @@ FvbGetAttributes ( + ) + { + EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes; +- NOR_FLASH_INSTANCE *Instance; +- +- Instance = INSTANCE_FROM_FVB_THIS (This); + + FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2)( + +@@ -294,17 +291,12 @@ FvbGetAttributes ( + EFI_FVB2_READ_STATUS | // Reads are currently enabled + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped +- EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1') ++ EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1') ++ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled ++ EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled + + ); + +- // Check if it is write protected +- if (Instance->Media.ReadOnly != TRUE) { +- FlashFvbAttributes = FlashFvbAttributes | +- EFI_FVB2_WRITE_STATUS | // Writes are currently enabled +- EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled +- } +- + *Attributes = FlashFvbAttributes; + + DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes)); +@@ -418,15 +410,15 @@ FvbGetBlockSize ( + + Instance = INSTANCE_FROM_FVB_THIS (This); + +- DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->Media.BlockSize, Instance->Media.LastBlock)); ++ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->BlockSize, Instance->LastBlock)); + +- if (Lba > Instance->Media.LastBlock) { +- DEBUG ((DEBUG_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->Media.LastBlock)); ++ if (Lba > Instance->LastBlock) { ++ DEBUG ((DEBUG_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->LastBlock)); + Status = EFI_INVALID_PARAMETER; + } else { + // This is easy because in this platform each NorFlash device has equal sized blocks. +- *BlockSize = (UINTN)Instance->Media.BlockSize; +- *NumberOfBlocks = (UINTN)(Instance->Media.LastBlock - Lba + 1); ++ *BlockSize = (UINTN)Instance->BlockSize; ++ *NumberOfBlocks = (UINTN)(Instance->LastBlock - Lba + 1); + + DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize, *NumberOfBlocks)); + +@@ -498,7 +490,7 @@ FvbRead ( + TempStatus = EFI_SUCCESS; + + // Cache the block size to avoid de-referencing pointers all the time +- BlockSize = Instance->Media.BlockSize; ++ BlockSize = Instance->BlockSize; + + DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", Offset, *NumBytes, BlockSize)); + +@@ -669,13 +661,6 @@ FvbEraseBlocks ( + + Status = EFI_SUCCESS; + +- // Detect WriteDisabled state +- if (Instance->Media.ReadOnly == TRUE) { +- // Firmware volume is in WriteDisabled state +- DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n")); +- return EFI_ACCESS_DENIED; +- } +- + // Before erasing, check the entire list of parameters to ensure all specified blocks are valid + + VA_START (Args, This); +@@ -698,9 +683,9 @@ FvbEraseBlocks ( + "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%Lu - 1 ) > LastBlock=%ld.\n", + Instance->StartLba + StartingLba, + (UINT64)NumOfLba, +- Instance->Media.LastBlock ++ Instance->LastBlock + )); +- if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->Media.LastBlock)) { ++ if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->LastBlock)) { + VA_END (Args); + DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n")); + Status = EFI_INVALID_PARAMETER; +@@ -733,7 +718,7 @@ FvbEraseBlocks ( + BlockAddress = GET_NOR_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + Instance->StartLba + StartingLba, +- Instance->Media.BlockSize ++ Instance->BlockSize + ); + + // Erase it +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-map-flash-memory-as-uncachea.patch b/edk2-OvmfPkg-VirtNorFlashDxe-map-flash-memory-as-uncachea.patch new file mode 100644 index 0000000..8eff08e --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-map-flash-memory-as-uncachea.patch @@ -0,0 +1,67 @@ +From 15415de9a228e74ff1847777a29f1531754b03b0 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 11 Jan 2023 19:00:23 +0100 +Subject: [PATCH 08/18] OvmfPkg/VirtNorFlashDxe: map flash memory as + uncacheable + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [10/20] 40ca967bead9ec5c98c528bfe0757f75f3d3352f + +Switching from the ArmPlatformPkg/NorFlashDxe driver to the +OvmfPkg/VirtNorFlashDxe driver had the side effect that flash address +space got registered as EFI_MEMORY_WC instead of EFI_MEMORY_UC. + +That confuses the linux kernel's numa code, seems this makes kernel +consider the flash being node memory. "lsmem" changes from ... + + RANGE SIZE STATE REMOVABLE BLOCK + 0x0000000040000000-0x000000013fffffff 4G online yes 8-39 + +... to ... + + RANGE SIZE STATE REMOVABLE BLOCK + 0x0000000000000000-0x0000000007ffffff 128M online yes 0 + 0x0000000040000000-0x000000013fffffff 4G online yes 8-39 + +... and in the kernel log got new error lines: + + NUMA: Warning: invalid memblk node 512 [mem 0x0000000004000000-0x0000000007ffffff] + NUMA: Faking a node at [mem 0x0000000004000000-0x000000013fffffff] + +Changing the attributes back to EFI_MEMORY_UC fixes this. + +Fixes: b92298af8218 ("ArmVirtPkg/ArmVirtQemu: migrate to OVMF's VirtNorFlashDxe") +Signed-off-by: Gerd Hoffmann +Reviewed-by: Ard Biesheuvel +(cherry picked from commit e5ec3ba409b5baa9cf429cc25fdf3c8d1b8dcef0) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +index ff3121af2a..f9a41f6aab 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +@@ -394,14 +394,14 @@ NorFlashFvbInitialize ( + EfiGcdMemoryTypeMemoryMappedIo, + Instance->DeviceBaseAddress, + RuntimeMmioRegionSize, +- EFI_MEMORY_WC | EFI_MEMORY_RUNTIME ++ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + Status = gDS->SetMemorySpaceAttributes ( + Instance->DeviceBaseAddress, + RuntimeMmioRegionSize, +- EFI_MEMORY_WC | EFI_MEMORY_RUNTIME ++ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch b/edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch new file mode 100644 index 0000000..da9eafb --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch @@ -0,0 +1,131 @@ +From 791c26a4a172b4a609a708db8018411ab653de4a Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 16 Jan 2024 18:11:05 +0100 +Subject: [PATCH 16/18] OvmfPkg/VirtNorFlashDxe: move DoErase code block into + new function + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [18/20] 10f4685bfcb0c5423e392b4cf0e8633cd25b46b4 + +Move the DoErase code block into a separate function, call the function +instead of jumping around with goto. + +Signed-off-by: Gerd Hoffmann +Message-Id: <20240116171105.37831-7-kraxel@redhat.com> +Reviewed-by: Laszlo Ersek +(cherry picked from commit b481b00f593ef37695ee14271453320ed02a1256) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 76 ++++++++++++++++++-------- + 1 file changed, 52 insertions(+), 24 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 3d1d20daa1..e6aaed27ce 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -502,6 +502,38 @@ NorFlashRead ( + return EFI_SUCCESS; + } + ++STATIC ++EFI_STATUS ++NorFlashWriteSingleBlockWithErase ( ++ IN NOR_FLASH_INSTANCE *Instance, ++ IN EFI_LBA Lba, ++ IN UINTN Offset, ++ IN OUT UINTN *NumBytes, ++ IN UINT8 *Buffer ++ ) ++{ ++ EFI_STATUS Status; ++ ++ // Read NOR Flash data into shadow buffer ++ Status = NorFlashReadBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer); ++ if (EFI_ERROR (Status)) { ++ // Return one of the pre-approved error statuses ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // Put the data at the appropriate location inside the buffer area ++ CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes); ++ ++ // Write the modified buffer back to the NorFlash ++ Status = NorFlashWriteBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer); ++ if (EFI_ERROR (Status)) { ++ // Return one of the pre-approved error statuses ++ return EFI_DEVICE_ERROR; ++ } ++ ++ return EFI_SUCCESS; ++} ++ + /* + Write a full or portion of a block. It must not span block boundaries; that is, + Offset + *NumBytes <= Instance->BlockSize. +@@ -607,7 +639,14 @@ NorFlashWriteSingleBlock ( + // that we want to set. In that case, we will need to erase the block first. + for (CurOffset = 0; CurOffset < *NumBytes; CurOffset++) { + if (~(UINT32)OrigData[CurOffset] & (UINT32)Buffer[CurOffset]) { +- goto DoErase; ++ Status = NorFlashWriteSingleBlockWithErase ( ++ Instance, ++ Lba, ++ Offset, ++ NumBytes, ++ Buffer ++ ); ++ return Status; + } + + OrigData[CurOffset] = Buffer[CurOffset]; +@@ -636,33 +675,22 @@ NorFlashWriteSingleBlock ( + goto Exit; + } + } +- +-Exit: +- // Put device back into Read Array mode +- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); +- ++ } else { ++ Status = NorFlashWriteSingleBlockWithErase ( ++ Instance, ++ Lba, ++ Offset, ++ NumBytes, ++ Buffer ++ ); + return Status; + } + +-DoErase: +- // Read NOR Flash data into shadow buffer +- Status = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); +- if (EFI_ERROR (Status)) { +- // Return one of the pre-approved error statuses +- return EFI_DEVICE_ERROR; +- } +- +- // Put the data at the appropriate location inside the buffer area +- CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes); +- +- // Write the modified buffer back to the NorFlash +- Status = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer); +- if (EFI_ERROR (Status)) { +- // Return one of the pre-approved error statuses +- return EFI_DEVICE_ERROR; +- } ++Exit: ++ // Put device back into Read Array mode ++ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); + +- return EFI_SUCCESS; ++ return Status; + } + + EFI_STATUS +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-remove-CheckBlockLocked-feat.patch b/edk2-OvmfPkg-VirtNorFlashDxe-remove-CheckBlockLocked-feat.patch new file mode 100644 index 0000000..2fdee8e --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-remove-CheckBlockLocked-feat.patch @@ -0,0 +1,94 @@ +From 03e0a729a5c3ebcab8806d136cd8908627bd91c9 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 24 Oct 2022 16:45:02 +0200 +Subject: [PATCH 02/18] OvmfPkg/VirtNorFlashDxe: remove CheckBlockLocked + feature + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [4/20] 990bdf373801df8107d8a6ec4db3fb93e5a6ad68 + +We inherited a feature from the ArmPlatformPkg version of this driver +that never gets enabled. Let's remove it. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Sunil V L +(cherry picked from commit 0a64106c566273ff8ef951d56ddfa972fe65bd6c) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 35 +++++---------------- + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf | 3 -- + 2 files changed, 8 insertions(+), 30 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 12fa720dad..59a562efdf 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -65,35 +65,16 @@ NorFlashUnlockSingleBlock ( + // Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations + // and to protect shared data structures. + +- if (FeaturePcdGet (PcdNorFlashCheckBlockLocked) == TRUE) { +- do { +- // Request a lock setup +- SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP); ++ // Request a lock setup ++ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP); + +- // Request an unlock +- SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK); ++ // Request an unlock ++ SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK); + +- // Send command for reading device id +- SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID); +- +- // Read block lock status +- LockStatus = MmioRead32 (CREATE_NOR_ADDRESS (BlockAddress, 2)); +- +- // Decode block lock status +- LockStatus = FOLD_32BIT_INTO_16BIT (LockStatus); +- } while ((LockStatus & 0x1) == 1); +- } else { +- // Request a lock setup +- SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP); +- +- // Request an unlock +- SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK); +- +- // Wait until the status register gives us the all clear +- do { +- LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress); +- } while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE); +- } ++ // Wait until the status register gives us the all clear ++ do { ++ LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress); ++ } while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE); + + // Put device back into Read Array mode + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_READ_ARRAY); +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf +index 1bf50e4823..53e9d58204 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf +@@ -24,7 +24,6 @@ + VirtNorFlashFvb.c + + [Packages] +- ArmPlatformPkg/ArmPlatformPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec +@@ -66,7 +65,5 @@ + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + +- gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked +- + [Depex] + gEfiCpuArchProtocolGuid +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-remove-disk-I-O-protocol-imp.patch b/edk2-OvmfPkg-VirtNorFlashDxe-remove-disk-I-O-protocol-imp.patch new file mode 100644 index 0000000..9319925 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-remove-disk-I-O-protocol-imp.patch @@ -0,0 +1,386 @@ +From 56041232238e4e4d3c8d703b27f51b0bc70fd5c8 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 24 Oct 2022 16:50:05 +0200 +Subject: [PATCH 03/18] OvmfPkg/VirtNorFlashDxe: remove disk I/O protocol + implementation + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [5/20] 0551c3f56f43396cfdc380127565e89d69eb29a3 + +We only use NOR flash for firmware volumes, either for executable images +or for the variable store. So we have no need for exposing disk I/O on +top of the NOR flash partitions so let's remove it. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Sunil V L +(cherry picked from commit 68d234989b2d6bd8f255577e08bf8be0b1d197bb) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 129 ------------------ + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h | 29 ---- + .../VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c | 123 ----------------- + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 8 -- + 4 files changed, 289 deletions(-) + delete mode 100644 OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 59a562efdf..1094d48f7d 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -788,135 +788,6 @@ NorFlashWriteSingleBlock ( + return EFI_SUCCESS; + } + +-/* +- Although DiskIoDxe will automatically install the DiskIO protocol whenever +- we install the BlockIO protocol, its implementation is sub-optimal as it reads +- and writes entire blocks using the BlockIO protocol. In fact we can access +- NOR flash with a finer granularity than that, so we can improve performance +- by directly producing the DiskIO protocol. +-*/ +- +-/** +- Read BufferSize bytes from Offset into Buffer. +- +- @param This Protocol instance pointer. +- @param MediaId Id of the media, changes every time the media is replaced. +- @param Offset The starting byte offset to read from +- @param BufferSize Size of Buffer +- @param Buffer Buffer containing read data +- +- @retval EFI_SUCCESS The data was read correctly from the device. +- @retval EFI_DEVICE_ERROR The device reported an error while performing the read. +- @retval EFI_NO_MEDIA There is no media in the device. +- @retval EFI_MEDIA_CHANGED The MediaId does not match the current device. +- @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not +- valid for the device. +- +-**/ +-EFI_STATUS +-EFIAPI +-NorFlashDiskIoReadDisk ( +- IN EFI_DISK_IO_PROTOCOL *This, +- IN UINT32 MediaId, +- IN UINT64 DiskOffset, +- IN UINTN BufferSize, +- OUT VOID *Buffer +- ) +-{ +- NOR_FLASH_INSTANCE *Instance; +- UINT32 BlockSize; +- UINT32 BlockOffset; +- EFI_LBA Lba; +- +- Instance = INSTANCE_FROM_DISKIO_THIS (This); +- +- if (MediaId != Instance->Media.MediaId) { +- return EFI_MEDIA_CHANGED; +- } +- +- BlockSize = Instance->Media.BlockSize; +- Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset); +- +- return NorFlashRead (Instance, Lba, BlockOffset, BufferSize, Buffer); +-} +- +-/** +- Writes a specified number of bytes to a device. +- +- @param This Indicates a pointer to the calling context. +- @param MediaId ID of the medium to be written. +- @param Offset The starting byte offset on the logical block I/O device to write. +- @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device. +- @param Buffer A pointer to the buffer containing the data to be written. +- +- @retval EFI_SUCCESS The data was written correctly to the device. +- @retval EFI_WRITE_PROTECTED The device can not be written to. +- @retval EFI_DEVICE_ERROR The device reported an error while performing the write. +- @retval EFI_NO_MEDIA There is no media in the device. +- @retval EFI_MEDIA_CHANGED The MediaId does not match the current device. +- @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not +- valid for the device. +- +-**/ +-EFI_STATUS +-EFIAPI +-NorFlashDiskIoWriteDisk ( +- IN EFI_DISK_IO_PROTOCOL *This, +- IN UINT32 MediaId, +- IN UINT64 DiskOffset, +- IN UINTN BufferSize, +- IN VOID *Buffer +- ) +-{ +- NOR_FLASH_INSTANCE *Instance; +- UINT32 BlockSize; +- UINT32 BlockOffset; +- EFI_LBA Lba; +- UINTN RemainingBytes; +- UINTN WriteSize; +- EFI_STATUS Status; +- +- Instance = INSTANCE_FROM_DISKIO_THIS (This); +- +- if (MediaId != Instance->Media.MediaId) { +- return EFI_MEDIA_CHANGED; +- } +- +- BlockSize = Instance->Media.BlockSize; +- Lba = (EFI_LBA)DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffset); +- +- RemainingBytes = BufferSize; +- +- // Write either all the remaining bytes, or the number of bytes that bring +- // us up to a block boundary, whichever is less. +- // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next +- // block boundary (even if it is already on one). +- WriteSize = MIN (RemainingBytes, ((DiskOffset | (BlockSize - 1)) + 1) - DiskOffset); +- +- do { +- if (WriteSize == BlockSize) { +- // Write a full block +- Status = NorFlashWriteFullBlock (Instance, Lba, Buffer, BlockSize / sizeof (UINT32)); +- } else { +- // Write a partial block +- Status = NorFlashWriteSingleBlock (Instance, Lba, BlockOffset, &WriteSize, Buffer); +- } +- +- if (EFI_ERROR (Status)) { +- return Status; +- } +- +- // Now continue writing either all the remaining bytes or single blocks. +- RemainingBytes -= WriteSize; +- Buffer = (UINT8 *)Buffer + WriteSize; +- Lba++; +- BlockOffset = 0; +- WriteSize = MIN (RemainingBytes, BlockSize); +- } while (RemainingBytes); +- +- return Status; +-} +- + EFI_STATUS + NorFlashReset ( + IN NOR_FLASH_INSTANCE *Instance +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +index e46522a198..7733ee02ee 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +@@ -15,7 +15,6 @@ + #include + + #include +-#include + #include + + #include +@@ -111,7 +110,6 @@ + #define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0') + #define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE) + #define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE) +-#define INSTANCE_FROM_DISKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, DiskIoProtocol, NOR_FLASH_SIGNATURE) + + typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE; + +@@ -134,7 +132,6 @@ struct _NOR_FLASH_INSTANCE { + + EFI_BLOCK_IO_PROTOCOL BlockIoProtocol; + EFI_BLOCK_IO_MEDIA Media; +- EFI_DISK_IO_PROTOCOL DiskIoProtocol; + + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; + VOID *ShadowBuffer; +@@ -203,32 +200,6 @@ NorFlashBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +-// +-// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.ReadDisk +-// +-EFI_STATUS +-EFIAPI +-NorFlashDiskIoReadDisk ( +- IN EFI_DISK_IO_PROTOCOL *This, +- IN UINT32 MediaId, +- IN UINT64 Offset, +- IN UINTN BufferSize, +- OUT VOID *Buffer +- ); +- +-// +-// DiskIO Protocol function EFI_DISK_IO_PROTOCOL.WriteDisk +-// +-EFI_STATUS +-EFIAPI +-NorFlashDiskIoWriteDisk ( +- IN EFI_DISK_IO_PROTOCOL *This, +- IN UINT32 MediaId, +- IN UINT64 Offset, +- IN UINTN BufferSize, +- IN VOID *Buffer +- ); +- + // + // NorFlashFvbDxe.c + // +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c +deleted file mode 100644 +index ecf152e355..0000000000 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashBlockIoDxe.c ++++ /dev/null +@@ -1,123 +0,0 @@ +-/** @file NorFlashBlockIoDxe.c +- +- Copyright (c) 2011-2013, ARM Ltd. All rights reserved.
+- +- SPDX-License-Identifier: BSD-2-Clause-Patent +- +-**/ +- +-#include +-#include +- +-#include "VirtNorFlash.h" +- +-// +-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset +-// +-EFI_STATUS +-EFIAPI +-NorFlashBlockIoReset ( +- IN EFI_BLOCK_IO_PROTOCOL *This, +- IN BOOLEAN ExtendedVerification +- ) +-{ +- NOR_FLASH_INSTANCE *Instance; +- +- Instance = INSTANCE_FROM_BLKIO_THIS (This); +- +- DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId)); +- +- return NorFlashReset (Instance); +-} +- +-// +-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks +-// +-EFI_STATUS +-EFIAPI +-NorFlashBlockIoReadBlocks ( +- IN EFI_BLOCK_IO_PROTOCOL *This, +- IN UINT32 MediaId, +- IN EFI_LBA Lba, +- IN UINTN BufferSizeInBytes, +- OUT VOID *Buffer +- ) +-{ +- NOR_FLASH_INSTANCE *Instance; +- EFI_STATUS Status; +- EFI_BLOCK_IO_MEDIA *Media; +- +- if (This == NULL) { +- return EFI_INVALID_PARAMETER; +- } +- +- Instance = INSTANCE_FROM_BLKIO_THIS (This); +- Media = This->Media; +- +- DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, BufferSizeInBytes, Buffer)); +- +- if (!Media) { +- Status = EFI_INVALID_PARAMETER; +- } else if (!Media->MediaPresent) { +- Status = EFI_NO_MEDIA; +- } else if (Media->MediaId != MediaId) { +- Status = EFI_MEDIA_CHANGED; +- } else if ((Media->IoAlign > 2) && (((UINTN)Buffer & (Media->IoAlign - 1)) != 0)) { +- Status = EFI_INVALID_PARAMETER; +- } else { +- Status = NorFlashReadBlocks (Instance, Lba, BufferSizeInBytes, Buffer); +- } +- +- return Status; +-} +- +-// +-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks +-// +-EFI_STATUS +-EFIAPI +-NorFlashBlockIoWriteBlocks ( +- IN EFI_BLOCK_IO_PROTOCOL *This, +- IN UINT32 MediaId, +- IN EFI_LBA Lba, +- IN UINTN BufferSizeInBytes, +- IN VOID *Buffer +- ) +-{ +- NOR_FLASH_INSTANCE *Instance; +- EFI_STATUS Status; +- +- Instance = INSTANCE_FROM_BLKIO_THIS (This); +- +- DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes, BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer)); +- +- if ( !This->Media->MediaPresent ) { +- Status = EFI_NO_MEDIA; +- } else if ( This->Media->MediaId != MediaId ) { +- Status = EFI_MEDIA_CHANGED; +- } else if ( This->Media->ReadOnly ) { +- Status = EFI_WRITE_PROTECTED; +- } else { +- Status = NorFlashWriteBlocks (Instance, Lba, BufferSizeInBytes, Buffer); +- } +- +- return Status; +-} +- +-// +-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks +-// +-EFI_STATUS +-EFIAPI +-NorFlashBlockIoFlushBlocks ( +- IN EFI_BLOCK_IO_PROTOCOL *This +- ) +-{ +- // No Flush required for the NOR Flash driver +- // because cache operations are not permitted. +- +- DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoFlushBlocks: Function NOT IMPLEMENTED (not required).\n")); +- +- // Nothing to do so just return without error +- return EFI_SUCCESS; +-} +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +index 819425545e..4875b057d5 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +@@ -58,12 +58,6 @@ NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = { + 1, // LogicalBlocksPerPhysicalBlock + }, // Media; + +- { +- EFI_DISK_IO_PROTOCOL_REVISION, // Revision +- NorFlashDiskIoReadDisk, // ReadDisk +- NorFlashDiskIoWriteDisk // WriteDisk +- }, +- + { + FvbGetAttributes, // GetAttributes + FvbSetAttributes, // SetAttributes +@@ -159,8 +153,6 @@ NorFlashCreateInstance ( + &Instance->DevicePath, + &gEfiBlockIoProtocolGuid, + &Instance->BlockIoProtocol, +- &gEfiDiskIoProtocolGuid, +- &Instance->DiskIoProtocol, + NULL + ); + if (EFI_ERROR (Status)) { +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variable2.patch b/edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variable2.patch new file mode 100644 index 0000000..106b9db --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variable2.patch @@ -0,0 +1,216 @@ +From c4d2144caff4eddb7021752fce6c2dec6d5e1632 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 9 Jan 2024 12:29:02 +0100 +Subject: [PATCH 10/18] OvmfPkg/VirtNorFlashDxe: sanity-check variables + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [12/20] 2ad3957478b82a4ca29249ceb9620f97c591a1fe + +Extend the ValidateFvHeader function, additionally to the header checks +walk over the list of variables and sanity check them. + +In case we find inconsistencies indicating variable store corruption +return EFI_NOT_FOUND so the variable store will be re-initialized. + +Signed-off-by: Gerd Hoffmann +Message-Id: <20240109112902.30002-4-kraxel@redhat.com> +Reviewed-by: Laszlo Ersek +[lersek@redhat.com: fix StartId initialization/assignment coding style] +(cherry picked from commit 4a443f73fd67ca8caaf0a3e1a01f8231b330d2e0) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf | 1 + + OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c | 149 +++++++++++++++++++- + 2 files changed, 145 insertions(+), 5 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf +index 2a3d4a218e..f549400280 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf +@@ -34,6 +34,7 @@ + DxeServicesTableLib + HobLib + IoLib ++ SafeIntLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +index c503272a2b..acc4a413ee 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -185,11 +186,12 @@ ValidateFvHeader ( + IN NOR_FLASH_INSTANCE *Instance + ) + { +- UINT16 Checksum; +- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; +- VARIABLE_STORE_HEADER *VariableStoreHeader; +- UINTN VariableStoreLength; +- UINTN FvLength; ++ UINT16 Checksum; ++ CONST EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; ++ CONST VARIABLE_STORE_HEADER *VariableStoreHeader; ++ UINTN VarOffset; ++ UINTN VariableStoreLength; ++ UINTN FvLength; + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Instance->RegionBaseAddress; + +@@ -258,6 +260,143 @@ ValidateFvHeader ( + return EFI_NOT_FOUND; + } + ++ // ++ // check variables ++ // ++ DEBUG ((DEBUG_INFO, "%a: checking variables\n", __func__)); ++ VarOffset = sizeof (*VariableStoreHeader); ++ for ( ; ;) { ++ UINTN VarHeaderEnd; ++ UINTN VarNameEnd; ++ UINTN VarEnd; ++ UINTN VarPadding; ++ CONST AUTHENTICATED_VARIABLE_HEADER *VarHeader; ++ CONST CHAR16 *VarName; ++ CONST CHAR8 *VarState; ++ RETURN_STATUS Status; ++ ++ Status = SafeUintnAdd (VarOffset, sizeof (*VarHeader), &VarHeaderEnd); ++ if (RETURN_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ ++ if (VarHeaderEnd >= VariableStoreHeader->Size) { ++ if (VarOffset <= VariableStoreHeader->Size - sizeof (UINT16)) { ++ CONST UINT16 *StartId; ++ ++ StartId = (VOID *)((UINTN)VariableStoreHeader + VarOffset); ++ if (*StartId == 0x55aa) { ++ DEBUG ((DEBUG_ERROR, "%a: startid at invalid location\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ } ++ ++ DEBUG ((DEBUG_INFO, "%a: end of var list (no space left)\n", __func__)); ++ break; ++ } ++ ++ VarHeader = (VOID *)((UINTN)VariableStoreHeader + VarOffset); ++ if (VarHeader->StartId != 0x55aa) { ++ DEBUG ((DEBUG_INFO, "%a: end of var list (no startid)\n", __func__)); ++ break; ++ } ++ ++ VarName = NULL; ++ switch (VarHeader->State) { ++ // usage: State = VAR_HEADER_VALID_ONLY ++ case VAR_HEADER_VALID_ONLY: ++ VarState = "header-ok"; ++ VarName = L""; ++ break; ++ ++ // usage: State = VAR_ADDED ++ case VAR_ADDED: ++ VarState = "ok"; ++ break; ++ ++ // usage: State &= VAR_IN_DELETED_TRANSITION ++ case VAR_ADDED &VAR_IN_DELETED_TRANSITION: ++ VarState = "del-in-transition"; ++ break; ++ ++ // usage: State &= VAR_DELETED ++ case VAR_ADDED &VAR_DELETED: ++ case VAR_ADDED &VAR_DELETED &VAR_IN_DELETED_TRANSITION: ++ VarState = "deleted"; ++ break; ++ ++ default: ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: invalid variable state: 0x%x\n", ++ __func__, ++ VarHeader->State ++ )); ++ return EFI_NOT_FOUND; ++ } ++ ++ Status = SafeUintnAdd (VarHeaderEnd, VarHeader->NameSize, &VarNameEnd); ++ if (RETURN_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ ++ Status = SafeUintnAdd (VarNameEnd, VarHeader->DataSize, &VarEnd); ++ if (RETURN_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ ++ if (VarEnd > VariableStoreHeader->Size) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: invalid variable size: 0x%Lx + 0x%Lx + 0x%x + 0x%x > 0x%x\n", ++ __func__, ++ (UINT64)VarOffset, ++ (UINT64)(sizeof (*VarHeader)), ++ VarHeader->NameSize, ++ VarHeader->DataSize, ++ VariableStoreHeader->Size ++ )); ++ return EFI_NOT_FOUND; ++ } ++ ++ if (((VarHeader->NameSize & 1) != 0) || ++ (VarHeader->NameSize < 4)) ++ { ++ DEBUG ((DEBUG_ERROR, "%a: invalid name size\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ ++ if (VarName == NULL) { ++ VarName = (VOID *)((UINTN)VariableStoreHeader + VarHeaderEnd); ++ if (VarName[VarHeader->NameSize / 2 - 1] != L'\0') { ++ DEBUG ((DEBUG_ERROR, "%a: name is not null terminated\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ } ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: +0x%04Lx: name=0x%x data=0x%x guid=%g '%s' (%a)\n", ++ __func__, ++ (UINT64)VarOffset, ++ VarHeader->NameSize, ++ VarHeader->DataSize, ++ &VarHeader->VendorGuid, ++ VarName, ++ VarState ++ )); ++ ++ VarPadding = (4 - (VarEnd & 3)) & 3; ++ Status = SafeUintnAdd (VarEnd, VarPadding, &VarOffset); ++ if (RETURN_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ } ++ + return EFI_SUCCESS; + } + +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variables.patch b/edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variables.patch new file mode 100644 index 0000000..f94ca10 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variables.patch @@ -0,0 +1,216 @@ +From c4eef747624d41aaa09dc64ccafdb84bf1fe656e Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 9 Jan 2024 12:29:02 +0100 +Subject: [PATCH 2/2] OvmfPkg/VirtNorFlashDxe: sanity-check variables + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 42: OvmfPkg/VirtNorFlashDxe: sanity-check variables +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [2/2] 56ff961f754d517c0e27ccf46a95b228efe7ab4b + +Extend the ValidateFvHeader function, additionally to the header checks +walk over the list of variables and sanity check them. + +In case we find inconsistencies indicating variable store corruption +return EFI_NOT_FOUND so the variable store will be re-initialized. + +Signed-off-by: Gerd Hoffmann +Message-Id: <20240109112902.30002-4-kraxel@redhat.com> +Reviewed-by: Laszlo Ersek +[lersek@redhat.com: fix StartId initialization/assignment coding style] +(cherry picked from commit 4a443f73fd67ca8caaf0a3e1a01f8231b330d2e0) +--- + .../Drivers/NorFlashDxe/NorFlashDxe.inf | 1 + + .../Drivers/NorFlashDxe/NorFlashFvb.c | 149 +++++++++++++++++- + 2 files changed, 145 insertions(+), 5 deletions(-) + +diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf +index f8d4c27031..10388880a1 100644 +--- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf ++++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf +@@ -35,6 +35,7 @@ + DebugLib + HobLib + NorFlashPlatformLib ++ SafeIntLib + UefiLib + UefiDriverEntryPoint + UefiBootServicesTableLib +diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvb.c b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvb.c +index 904605cbbc..2a166c94a6 100644 +--- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvb.c ++++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvb.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -166,11 +167,12 @@ ValidateFvHeader ( + IN NOR_FLASH_INSTANCE *Instance + ) + { +- UINT16 Checksum; +- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; +- VARIABLE_STORE_HEADER *VariableStoreHeader; +- UINTN VariableStoreLength; +- UINTN FvLength; ++ UINT16 Checksum; ++ CONST EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; ++ CONST VARIABLE_STORE_HEADER *VariableStoreHeader; ++ UINTN VarOffset; ++ UINTN VariableStoreLength; ++ UINTN FvLength; + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Instance->RegionBaseAddress; + +@@ -223,6 +225,143 @@ ValidateFvHeader ( + return EFI_NOT_FOUND; + } + ++ // ++ // check variables ++ // ++ DEBUG ((DEBUG_INFO, "%a: checking variables\n", __func__)); ++ VarOffset = sizeof (*VariableStoreHeader); ++ for ( ; ;) { ++ UINTN VarHeaderEnd; ++ UINTN VarNameEnd; ++ UINTN VarEnd; ++ UINTN VarPadding; ++ CONST AUTHENTICATED_VARIABLE_HEADER *VarHeader; ++ CONST CHAR16 *VarName; ++ CONST CHAR8 *VarState; ++ RETURN_STATUS Status; ++ ++ Status = SafeUintnAdd (VarOffset, sizeof (*VarHeader), &VarHeaderEnd); ++ if (RETURN_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ ++ if (VarHeaderEnd >= VariableStoreHeader->Size) { ++ if (VarOffset <= VariableStoreHeader->Size - sizeof (UINT16)) { ++ CONST UINT16 *StartId; ++ ++ StartId = (VOID *)((UINTN)VariableStoreHeader + VarOffset); ++ if (*StartId == 0x55aa) { ++ DEBUG ((DEBUG_ERROR, "%a: startid at invalid location\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ } ++ ++ DEBUG ((DEBUG_INFO, "%a: end of var list (no space left)\n", __func__)); ++ break; ++ } ++ ++ VarHeader = (VOID *)((UINTN)VariableStoreHeader + VarOffset); ++ if (VarHeader->StartId != 0x55aa) { ++ DEBUG ((DEBUG_INFO, "%a: end of var list (no startid)\n", __func__)); ++ break; ++ } ++ ++ VarName = NULL; ++ switch (VarHeader->State) { ++ // usage: State = VAR_HEADER_VALID_ONLY ++ case VAR_HEADER_VALID_ONLY: ++ VarState = "header-ok"; ++ VarName = L""; ++ break; ++ ++ // usage: State = VAR_ADDED ++ case VAR_ADDED: ++ VarState = "ok"; ++ break; ++ ++ // usage: State &= VAR_IN_DELETED_TRANSITION ++ case VAR_ADDED &VAR_IN_DELETED_TRANSITION: ++ VarState = "del-in-transition"; ++ break; ++ ++ // usage: State &= VAR_DELETED ++ case VAR_ADDED &VAR_DELETED: ++ case VAR_ADDED &VAR_DELETED &VAR_IN_DELETED_TRANSITION: ++ VarState = "deleted"; ++ break; ++ ++ default: ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: invalid variable state: 0x%x\n", ++ __func__, ++ VarHeader->State ++ )); ++ return EFI_NOT_FOUND; ++ } ++ ++ Status = SafeUintnAdd (VarHeaderEnd, VarHeader->NameSize, &VarNameEnd); ++ if (RETURN_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ ++ Status = SafeUintnAdd (VarNameEnd, VarHeader->DataSize, &VarEnd); ++ if (RETURN_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ ++ if (VarEnd > VariableStoreHeader->Size) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: invalid variable size: 0x%Lx + 0x%Lx + 0x%x + 0x%x > 0x%x\n", ++ __func__, ++ (UINT64)VarOffset, ++ (UINT64)(sizeof (*VarHeader)), ++ VarHeader->NameSize, ++ VarHeader->DataSize, ++ VariableStoreHeader->Size ++ )); ++ return EFI_NOT_FOUND; ++ } ++ ++ if (((VarHeader->NameSize & 1) != 0) || ++ (VarHeader->NameSize < 4)) ++ { ++ DEBUG ((DEBUG_ERROR, "%a: invalid name size\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ ++ if (VarName == NULL) { ++ VarName = (VOID *)((UINTN)VariableStoreHeader + VarHeaderEnd); ++ if (VarName[VarHeader->NameSize / 2 - 1] != L'\0') { ++ DEBUG ((DEBUG_ERROR, "%a: name is not null terminated\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ } ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: +0x%04Lx: name=0x%x data=0x%x guid=%g '%s' (%a)\n", ++ __func__, ++ (UINT64)VarOffset, ++ VarHeader->NameSize, ++ VarHeader->DataSize, ++ &VarHeader->VendorGuid, ++ VarName, ++ VarState ++ )); ++ ++ VarPadding = (4 - (VarEnd & 3)) & 3; ++ Status = SafeUintnAdd (VarEnd, VarPadding, &VarOffset); ++ if (RETURN_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__)); ++ return EFI_NOT_FOUND; ++ } ++ } ++ + return EFI_SUCCESS; + } + +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariable2.patch b/edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariable2.patch new file mode 100644 index 0000000..a735619 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariable2.patch @@ -0,0 +1,49 @@ +From 1444157aad1b98ce9c1193ef109011b084113890 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 9 Jan 2024 12:29:01 +0100 +Subject: [PATCH 09/18] OvmfPkg/VirtNorFlashDxe: stop accepting + gEfiVariableGuid +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [11/20] c7b9cd1b716e1b8163b8094fbea8117241901815 + +Only accept gEfiAuthenticatedVariableGuid when checking the variable +store header in ValidateFvHeader(). + +The edk2 code base has been switched to use the authenticated varstore +format unconditionally (even in case secure boot is not used or +supported) a few years ago. + +Suggested-by: László Érsek +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-Id: <20240109112902.30002-3-kraxel@redhat.com> +(cherry picked from commit ae22b2f136bcbd27135a5f4dd76d3a68a172d00e) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +index cc5eefaaf3..c503272a2b 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +@@ -239,9 +239,7 @@ ValidateFvHeader ( + VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)FwVolHeader + FwVolHeader->HeaderLength); + + // Check the Variable Store Guid +- if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) && +- !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) +- { ++ if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) { + DEBUG (( + DEBUG_INFO, + "%a: Variable Store Guid non-compatible\n", +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariableG.patch b/edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariableG.patch new file mode 100644 index 0000000..a3b6933 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariableG.patch @@ -0,0 +1,47 @@ +From abe5b633eaae333190fb742af3fa15968f02a92e Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 9 Jan 2024 12:29:01 +0100 +Subject: [PATCH 1/2] OvmfPkg/VirtNorFlashDxe: stop accepting gEfiVariableGuid +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 42: OvmfPkg/VirtNorFlashDxe: sanity-check variables +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [1/2] 790f895bd180bc2c4b957a7a3c7d07e9107dd74b + +Only accept gEfiAuthenticatedVariableGuid when checking the variable +store header in ValidateFvHeader(). + +The edk2 code base has been switched to use the authenticated varstore +format unconditionally (even in case secure boot is not used or +supported) a few years ago. + +Suggested-by: László Érsek +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Message-Id: <20240109112902.30002-3-kraxel@redhat.com> +(cherry picked from commit ae22b2f136bcbd27135a5f4dd76d3a68a172d00e) +--- + ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvb.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvb.c b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvb.c +index db8eb595f4..904605cbbc 100644 +--- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvb.c ++++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvb.c +@@ -210,8 +210,7 @@ ValidateFvHeader ( + VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader + FwVolHeader->HeaderLength); + + // Check the Variable Store Guid +- if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) && +- !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) { ++ if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) { + DEBUG ((EFI_D_INFO, "%a: Variable Store Guid non-compatible\n", + __FUNCTION__)); + return EFI_NOT_FOUND; +-- +2.41.0 + diff --git a/edk2-OvmfPkg-VirtNorFlashDxe-use-EFI_MEMORY_WC-and-drop-A.patch b/edk2-OvmfPkg-VirtNorFlashDxe-use-EFI_MEMORY_WC-and-drop-A.patch new file mode 100644 index 0000000..a61f223 --- /dev/null +++ b/edk2-OvmfPkg-VirtNorFlashDxe-use-EFI_MEMORY_WC-and-drop-A.patch @@ -0,0 +1,150 @@ +From e65da48afdabc9a5cba1c212b4323898b91ef2a4 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 24 Oct 2022 18:16:18 +0200 +Subject: [PATCH 07/18] OvmfPkg/VirtNorFlashDxe: use EFI_MEMORY_WC and drop + AlignedCopyMem() + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [9/20] 0c01619eff8282d08e05fae8c37175b944449f59 + +NOR flash emulation under KVM involves switching between two modes, +where array mode is backed by a read-only memslot, and programming mode +is fully emulated, i.e., the memory region is not backed by anything, +and the faulting accesses are forwarded to the VMM by the hypervisor, +which translates them into NOR flash programming commands. + +Normally, we are limited to the use of device attributes when mapping +such regions, given that the programming mode has MMIO semantics. +However, when running under KVM, the chosen memory attributes only take +effect when in array mode, since no memory mapping exists otherwise. + +This means we can tune the memory mapping so it behaves a bit more like +a ROM, by switching to EFI_MEMORY_WC attributes. This means we no longer +need a special CopyMem() implementation that avoids unaligned accesses +at all cost. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Sunil V L +(cherry picked from commit 789a723285533f35652ebd6029976e2ddc955655) +--- + OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c | 65 +---------------------- + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 4 +- + 2 files changed, 4 insertions(+), 65 deletions(-) + +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +index 0343131a54..1afd60ce66 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c +@@ -401,67 +401,6 @@ NorFlashWriteBlocks ( + return Status; + } + +-#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align) - 1)) == 0) +- +-/** +- Copy Length bytes from Source to Destination, using aligned accesses only. +- Note that this implementation uses memcpy() semantics rather then memmove() +- semantics, i.e., SourceBuffer and DestinationBuffer should not overlap. +- +- @param DestinationBuffer The target of the copy request. +- @param SourceBuffer The place to copy from. +- @param Length The number of bytes to copy. +- +- @return Destination +- +-**/ +-STATIC +-VOID * +-AlignedCopyMem ( +- OUT VOID *DestinationBuffer, +- IN CONST VOID *SourceBuffer, +- IN UINTN Length +- ) +-{ +- UINT8 *Destination8; +- CONST UINT8 *Source8; +- UINT32 *Destination32; +- CONST UINT32 *Source32; +- UINT64 *Destination64; +- CONST UINT64 *Source64; +- +- if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 8) && (Length >= 8)) { +- Destination64 = DestinationBuffer; +- Source64 = SourceBuffer; +- while (Length >= 8) { +- *Destination64++ = *Source64++; +- Length -= 8; +- } +- +- Destination8 = (UINT8 *)Destination64; +- Source8 = (CONST UINT8 *)Source64; +- } else if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 4) && (Length >= 4)) { +- Destination32 = DestinationBuffer; +- Source32 = SourceBuffer; +- while (Length >= 4) { +- *Destination32++ = *Source32++; +- Length -= 4; +- } +- +- Destination8 = (UINT8 *)Destination32; +- Source8 = (CONST UINT8 *)Source32; +- } else { +- Destination8 = DestinationBuffer; +- Source8 = SourceBuffer; +- } +- +- while (Length-- != 0) { +- *Destination8++ = *Source8++; +- } +- +- return DestinationBuffer; +-} +- + EFI_STATUS + NorFlashReadBlocks ( + IN NOR_FLASH_INSTANCE *Instance, +@@ -516,7 +455,7 @@ NorFlashReadBlocks ( + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); + + // Readout the data +- AlignedCopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes); ++ CopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes); + + return EFI_SUCCESS; + } +@@ -558,7 +497,7 @@ NorFlashRead ( + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); + + // Readout the data +- AlignedCopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes); ++ CopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes); + + return EFI_SUCCESS; + } +diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +index f9a41f6aab..ff3121af2a 100644 +--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c ++++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +@@ -394,14 +394,14 @@ NorFlashFvbInitialize ( + EfiGcdMemoryTypeMemoryMappedIo, + Instance->DeviceBaseAddress, + RuntimeMmioRegionSize, +- EFI_MEMORY_UC | EFI_MEMORY_RUNTIME ++ EFI_MEMORY_WC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + Status = gDS->SetMemorySpaceAttributes ( + Instance->DeviceBaseAddress, + RuntimeMmioRegionSize, +- EFI_MEMORY_UC | EFI_MEMORY_RUNTIME ++ EFI_MEMORY_WC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + +-- +2.41.0 + diff --git a/edk2-OvmfPkg-clone-NorFlashPlatformLib-into-VirtNorFlashP.patch b/edk2-OvmfPkg-clone-NorFlashPlatformLib-into-VirtNorFlashP.patch new file mode 100644 index 0000000..178b1e7 --- /dev/null +++ b/edk2-OvmfPkg-clone-NorFlashPlatformLib-into-VirtNorFlashP.patch @@ -0,0 +1,80 @@ +From 59fb955aa77b75345f7828bf9f83764adf4bed46 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 24 Oct 2022 18:35:10 +0200 +Subject: [PATCH 18/18] OvmfPkg: clone NorFlashPlatformLib into + VirtNorFlashPlatformLib + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 43: OvmfPkg/VirtNorFlashDxe backport +RH-Jira: RHEL-17587 +RH-Acked-by: Laszlo Ersek +RH-Commit: [20/20] 50ea104b99a997d7d08c1fdef617df1d930ffae6 + +Create a new library class in Ovmf that duplicates the existing +NorFlashPlatformLib, but which will be tied to the VirtNorFlashDxe +driver that will be introduced in a subsequent patch. This allows us to +retire the original from ArmPlatformPkg. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Sunil V L +(cherry picked from commit 16bf588b604a9f190accb71ada715b81756c94e2) +--- + .../Include/Library/VirtNorFlashPlatformLib.h | 30 +++++++++++++++++++ + OvmfPkg/OvmfPkg.dec | 4 +++ + 2 files changed, 34 insertions(+) + create mode 100644 OvmfPkg/Include/Library/VirtNorFlashPlatformLib.h + +diff --git a/OvmfPkg/Include/Library/VirtNorFlashPlatformLib.h b/OvmfPkg/Include/Library/VirtNorFlashPlatformLib.h +new file mode 100644 +index 0000000000..8f5b5e972d +--- /dev/null ++++ b/OvmfPkg/Include/Library/VirtNorFlashPlatformLib.h +@@ -0,0 +1,30 @@ ++/** @file ++ ++ Copyright (c) 2011-2012, ARM Ltd. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++ **/ ++ ++#ifndef __VIRT_NOR_FLASH_PLATFORM_LIB__ ++#define __VIRT_NOR_FLASH_PLATFORM_LIB__ ++ ++typedef struct { ++ UINTN DeviceBaseAddress; // Start address of the Device Base Address (DBA) ++ UINTN RegionBaseAddress; // Start address of one single region ++ UINTN Size; ++ UINTN BlockSize; ++} VIRT_NOR_FLASH_DESCRIPTION; ++ ++EFI_STATUS ++VirtNorFlashPlatformInitialization ( ++ VOID ++ ); ++ ++EFI_STATUS ++VirtNorFlashPlatformGetDevices ( ++ OUT VIRT_NOR_FLASH_DESCRIPTION **NorFlashDescriptions, ++ OUT UINT32 *Count ++ ); ++ ++#endif /* __VIRT_NOR_FLASH_PLATFORM_LIB__ */ +diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec +index 340d83f794..e65ebd81c8 100644 +--- a/OvmfPkg/OvmfPkg.dec ++++ b/OvmfPkg/OvmfPkg.dec +@@ -97,6 +97,10 @@ + # transports. + VirtioMmioDeviceLib|Include/Library/VirtioMmioDeviceLib.h + ++ ## @libraryclass Provides a Nor flash interface. ++ # ++ VirtNorFlashPlatformLib|Include/Library/VirtNorFlashPlatformLib.h ++ + ## @libraryclass Invoke Xen hypercalls + # + XenHypercallLib|Include/Library/XenHypercallLib.h +-- +2.41.0 + diff --git a/edk2-SecurityPkg-Adding-CVE-2022-36763-to-SecurityFixes.y.patch b/edk2-SecurityPkg-Adding-CVE-2022-36763-to-SecurityFixes.y.patch new file mode 100644 index 0000000..f2f31b7 --- /dev/null +++ b/edk2-SecurityPkg-Adding-CVE-2022-36763-to-SecurityFixes.y.patch @@ -0,0 +1,68 @@ +From 2794a967f43f2bbdfcd2cb5197ac8cad4b13c3de Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 17 Jan 2024 12:20:52 -0500 +Subject: [PATCH 08/17] SecurityPkg: Adding CVE 2022-36763 to + SecurityFixes.yaml + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [8/13] 74117caf760e403566f6511332b2c0f41483f28c (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21154 +Upstream: Merged +CVE: CVE-2022-36763 + +commit 1ddcb9fc6b4164e882687b031e8beacfcf7df29e +Author: Douglas Flick [MSFT] +Date: Fri Jan 12 02:16:03 2024 +0800 + + SecurityPkg: : Adding CVE 2022-36763 to SecurityFixes.yaml + + This creates / adds a security file that tracks the security fixes + found in this package and can be used to find the fixes that were + applied. + + Cc: Jiewen Yao + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Jiewen Yao + +Signed-off-by: Jon Maloy +--- + SecurityPkg/SecurityFixes.yaml | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + create mode 100644 SecurityPkg/SecurityFixes.yaml + +diff --git a/SecurityPkg/SecurityFixes.yaml b/SecurityPkg/SecurityFixes.yaml +new file mode 100644 +index 0000000000..f9e3e7be74 +--- /dev/null ++++ b/SecurityPkg/SecurityFixes.yaml +@@ -0,0 +1,22 @@ ++## @file ++# Security Fixes for SecurityPkg ++# ++# Copyright (c) Microsoft Corporation ++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++CVE_2022_36763: ++ commit_titles: ++ - "SecurityPkg: DxeTpm2Measurement: SECURITY PATCH 4117 - CVE 2022-36763" ++ - "SecurityPkg: DxeTpmMeasurement: SECURITY PATCH 4117 - CVE 2022-36763" ++ - "SecurityPkg: : Adding CVE 2022-36763 to SecurityFixes.yaml" ++ cve: CVE-2022-36763 ++ date_reported: 2022-10-25 11:31 UTC ++ description: (CVE-2022-36763) - Heap Buffer Overflow in Tcg2MeasureGptTable() ++ note: This patch is related to and supersedes TCBZ2168 ++ files_impacted: ++ - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c ++ - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4117 ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=2168 ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=1990 +-- +2.41.0 + diff --git a/edk2-SecurityPkg-Change-OPTIONAL-keyword-usage-style.patch b/edk2-SecurityPkg-Change-OPTIONAL-keyword-usage-style.patch new file mode 100644 index 0000000..bc3723f --- /dev/null +++ b/edk2-SecurityPkg-Change-OPTIONAL-keyword-usage-style.patch @@ -0,0 +1,403 @@ +From e2ccaef3baa2eb045019558c325bb94cabf65e1a Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 7 Feb 2024 11:56:37 -0500 +Subject: [PATCH 02/17] SecurityPkg: Change OPTIONAL keyword usage style + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [2/13] 6a2141d871e3efc3aeea1994ab9c325614ddce57 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21154 +CVE: CVE-2022-36763 +Upstream: Merged + +commit 948f4003ee399241a40dc147a738f05ad2e37375 +Author: Michael D Kinney +Date: Thu Dec 2 18:00:56 2021 -0800 + + SecurityPkg: Change OPTIONAL keyword usage style + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3760 + + Update all use of ', OPTIONAL' to ' OPTIONAL,' for function params. + + Cc: Andrew Fish + Cc: Leif Lindholm + Cc: Michael Kubacki + Signed-off-by: Michael D Kinney + Reviewed-by: Jian J Wang + +Signed-off-by: Jon Maloy +--- + SecurityPkg/Include/Library/Tcg2PpVendorLib.h | 2 +- + SecurityPkg/Include/Library/Tpm2CommandLib.h | 14 +++++++------- + SecurityPkg/Library/AuthVariableLib/AuthService.c | 6 +++--- + .../DxeImageAuthenticationStatusLib.c | 2 +- + .../DxeImageVerificationLib.c | 2 +- + .../DxeRsa2048Sha256GuidedSectionExtractLib.c | 2 +- + .../DxeTcg2PhysicalPresenceLib.c | 4 ++-- + .../DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c | 2 +- + .../DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c | 2 +- + .../PeiRsa2048Sha256GuidedSectionExtractLib.c | 2 +- + .../Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c | 2 +- + .../Tpm2CommandLib/Tpm2EnhancedAuthorization.c | 2 +- + SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c | 2 +- + SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c | 2 +- + SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c | 2 +- + SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c | 6 +++--- + .../RandomNumberGenerator/RngDxe/AArch64/RngDxe.c | 2 +- + .../RandomNumberGenerator/RngDxe/Rand/RngDxe.c | 2 +- + .../RandomNumberGenerator/RngDxe/RngDxeInternals.h | 2 +- + SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c | 2 +- + 20 files changed, 31 insertions(+), 31 deletions(-) + +diff --git a/SecurityPkg/Include/Library/Tcg2PpVendorLib.h b/SecurityPkg/Include/Library/Tcg2PpVendorLib.h +index 569eba6874..914517f034 100644 +--- a/SecurityPkg/Include/Library/Tcg2PpVendorLib.h ++++ b/SecurityPkg/Include/Library/Tcg2PpVendorLib.h +@@ -40,7 +40,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + UINT32 + EFIAPI + Tcg2PpVendorLibExecutePendingRequest ( +- IN TPM2B_AUTH *PlatformAuth, OPTIONAL ++ IN TPM2B_AUTH *PlatformAuth OPTIONAL, + IN UINT32 OperationRequest, + IN OUT UINT32 *ManagementFlags, + OUT BOOLEAN *ResetRequired +diff --git a/SecurityPkg/Include/Library/Tpm2CommandLib.h b/SecurityPkg/Include/Library/Tpm2CommandLib.h +index ee8eb62295..ad3b982d48 100644 +--- a/SecurityPkg/Include/Library/Tpm2CommandLib.h ++++ b/SecurityPkg/Include/Library/Tpm2CommandLib.h +@@ -186,7 +186,7 @@ EFI_STATUS + EFIAPI + Tpm2ClearControl ( + IN TPMI_RH_CLEAR AuthHandle, +- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN TPMI_YES_NO Disable + ); + +@@ -340,7 +340,7 @@ EFI_STATUS + EFIAPI + Tpm2NvDefineSpace ( + IN TPMI_RH_PROVISION AuthHandle, +- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN TPM2B_AUTH *Auth, + IN TPM2B_NV_PUBLIC *NvPublic + ); +@@ -383,7 +383,7 @@ EFIAPI + Tpm2NvRead ( + IN TPMI_RH_NV_AUTH AuthHandle, + IN TPMI_RH_NV_INDEX NvIndex, +- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN UINT16 Size, + IN UINT16 Offset, + IN OUT TPM2B_MAX_BUFFER *OutData +@@ -407,7 +407,7 @@ EFIAPI + Tpm2NvWrite ( + IN TPMI_RH_NV_AUTH AuthHandle, + IN TPMI_RH_NV_INDEX NvIndex, +- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN TPM2B_MAX_BUFFER *InData, + IN UINT16 Offset + ); +@@ -566,7 +566,7 @@ Tpm2PcrAllocate ( + EFI_STATUS + EFIAPI + Tpm2PcrAllocateBanks ( +- IN TPM2B_AUTH *PlatformAuth, OPTIONAL ++ IN TPM2B_AUTH *PlatformAuth OPTIONAL, + IN UINT32 SupportedPCRBanks, + IN UINT32 PCRBanks + ); +@@ -908,7 +908,7 @@ EFIAPI + Tpm2PolicySecret ( + IN TPMI_DH_ENTITY AuthHandle, + IN TPMI_SH_POLICY PolicySession, +- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN TPM2B_NONCE *NonceTPM, + IN TPM2B_DIGEST *CpHashA, + IN TPM2B_NONCE *PolicyRef, +@@ -1004,7 +1004,7 @@ Tpm2ReadPublic ( + UINT32 + EFIAPI + CopyAuthSessionCommand ( +- IN TPMS_AUTH_COMMAND *AuthSessionIn, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSessionIn OPTIONAL, + OUT UINT8 *AuthSessionOut + ); + +diff --git a/SecurityPkg/Library/AuthVariableLib/AuthService.c b/SecurityPkg/Library/AuthVariableLib/AuthService.c +index aa9ebaf3be..3059e5d256 100644 +--- a/SecurityPkg/Library/AuthVariableLib/AuthService.c ++++ b/SecurityPkg/Library/AuthVariableLib/AuthService.c +@@ -1183,9 +1183,9 @@ FindCertsFromDb ( + IN EFI_GUID *VendorGuid, + IN UINT8 *Data, + IN UINTN DataSize, +- OUT UINT32 *CertOffset, OPTIONAL +- OUT UINT32 *CertDataSize, OPTIONAL +- OUT UINT32 *CertNodeOffset,OPTIONAL ++ OUT UINT32 *CertOffset OPTIONAL, ++ OUT UINT32 *CertDataSize OPTIONAL, ++ OUT UINT32 *CertNodeOffset OPTIONAL, + OUT UINT32 *CertNodeSize OPTIONAL + ) + { +diff --git a/SecurityPkg/Library/DxeImageAuthenticationStatusLib/DxeImageAuthenticationStatusLib.c b/SecurityPkg/Library/DxeImageAuthenticationStatusLib/DxeImageAuthenticationStatusLib.c +index ec77151c9c..9acff2ae7d 100644 +--- a/SecurityPkg/Library/DxeImageAuthenticationStatusLib/DxeImageAuthenticationStatusLib.c ++++ b/SecurityPkg/Library/DxeImageAuthenticationStatusLib/DxeImageAuthenticationStatusLib.c +@@ -32,7 +32,7 @@ EFI_STATUS + EFIAPI + DxeImageAuthenticationStatusHandler ( + IN UINT32 AuthenticationStatus, +- IN CONST EFI_DEVICE_PATH_PROTOCOL *File, OPTIONAL ++ IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL, + IN VOID *FileBuffer, + IN UINTN FileSize, + IN BOOLEAN BootPolicy +diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +index 1252927664..0a12692454 100644 +--- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c ++++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +@@ -1636,7 +1636,7 @@ EFI_STATUS + EFIAPI + DxeImageVerificationHandler ( + IN UINT32 AuthenticationStatus, +- IN CONST EFI_DEVICE_PATH_PROTOCOL *File, OPTIONAL ++ IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL, + IN VOID *FileBuffer, + IN UINTN FileSize, + IN BOOLEAN BootPolicy +diff --git a/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c b/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c +index 28807d4d98..5124b884c9 100644 +--- a/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c ++++ b/SecurityPkg/Library/DxeRsa2048Sha256GuidedSectionExtractLib/DxeRsa2048Sha256GuidedSectionExtractLib.c +@@ -123,7 +123,7 @@ EFIAPI + Rsa2048Sha256GuidedSectionHandler ( + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, +- IN VOID *ScratchBuffer, OPTIONAL ++ IN VOID *ScratchBuffer OPTIONAL, + OUT UINT32 *AuthenticationStatus + ) + { +diff --git a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c +index fce5c0af50..d92658f80d 100644 +--- a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c ++++ b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c +@@ -147,7 +147,7 @@ Tpm2CommandChangeEps ( + **/ + UINT32 + Tcg2ExecutePhysicalPresence ( +- IN TPM2B_AUTH *PlatformAuth, OPTIONAL ++ IN TPM2B_AUTH *PlatformAuth OPTIONAL, + IN UINT32 CommandCode, + IN UINT32 CommandParameter, + IN OUT EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *PpiFlags +@@ -720,7 +720,7 @@ Tcg2HaveValidTpmRequest ( + **/ + VOID + Tcg2ExecutePendingTpmRequest ( +- IN TPM2B_AUTH *PlatformAuth, OPTIONAL ++ IN TPM2B_AUTH *PlatformAuth OPTIONAL, + IN OUT EFI_TCG2_PHYSICAL_PRESENCE *TcgPpData, + IN OUT EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *Flags + ) +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +index a531385f81..95682ac567 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +@@ -416,7 +416,7 @@ EFI_STATUS + EFIAPI + DxeTpm2MeasureBootHandler ( + IN UINT32 AuthenticationStatus, +- IN CONST EFI_DEVICE_PATH_PROTOCOL *File, OPTIONAL ++ IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL, + IN VOID *FileBuffer, + IN UINTN FileSize, + IN BOOLEAN BootPolicy +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +index 4e74cd9db6..27c0ea48ca 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +@@ -710,7 +710,7 @@ EFI_STATUS + EFIAPI + DxeTpmMeasureBootHandler ( + IN UINT32 AuthenticationStatus, +- IN CONST EFI_DEVICE_PATH_PROTOCOL *File, OPTIONAL ++ IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL, + IN VOID *FileBuffer, + IN UINTN FileSize, + IN BOOLEAN BootPolicy +diff --git a/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c b/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c +index a759183d20..96638e26aa 100644 +--- a/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c ++++ b/SecurityPkg/Library/PeiRsa2048Sha256GuidedSectionExtractLib/PeiRsa2048Sha256GuidedSectionExtractLib.c +@@ -121,7 +121,7 @@ EFIAPI + Rsa2048Sha256GuidedSectionHandler ( + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, +- IN VOID *ScratchBuffer, OPTIONAL ++ IN VOID *ScratchBuffer OPTIONAL, + OUT UINT32 *AuthenticationStatus + ) + { +diff --git a/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c b/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c +index 895d05a28d..aa3dcb6beb 100644 +--- a/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c ++++ b/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.c +@@ -30,7 +30,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + UINT32 + EFIAPI + Tcg2PpVendorLibExecutePendingRequest ( +- IN TPM2B_AUTH *PlatformAuth, OPTIONAL ++ IN TPM2B_AUTH *PlatformAuth OPTIONAL, + IN UINT32 OperationRequest, + IN OUT UINT32 *ManagementFlags, + OUT BOOLEAN *ResetRequired +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c +index 0404c0f321..53983d745b 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c +@@ -90,7 +90,7 @@ EFIAPI + Tpm2PolicySecret ( + IN TPMI_DH_ENTITY AuthHandle, + IN TPMI_SH_POLICY PolicySession, +- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN TPM2B_NONCE *NonceTPM, + IN TPM2B_DIGEST *CpHashA, + IN TPM2B_NONCE *PolicyRef, +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c +index 13eeb6ec18..44115cded3 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c +@@ -84,7 +84,7 @@ GetHashMaskFromAlgo ( + UINT32 + EFIAPI + CopyAuthSessionCommand ( +- IN TPMS_AUTH_COMMAND *AuthSessionIn, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSessionIn OPTIONAL, + OUT UINT8 *AuthSessionOut + ) + { +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c +index 043d358a06..957d694431 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c +@@ -305,7 +305,7 @@ EFI_STATUS + EFIAPI + Tpm2ClearControl ( + IN TPMI_RH_CLEAR AuthHandle, +- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN TPMI_YES_NO Disable + ) + { +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c +index 8c87de0b0c..d232fe725d 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c +@@ -566,7 +566,7 @@ Done: + EFI_STATUS + EFIAPI + Tpm2PcrAllocateBanks ( +- IN TPM2B_AUTH *PlatformAuth, OPTIONAL ++ IN TPM2B_AUTH *PlatformAuth OPTIONAL, + IN UINT32 SupportedPCRBanks, + IN UINT32 PCRBanks + ) +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c +index fb46af0fed..d9171fb9a0 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c +@@ -281,7 +281,7 @@ EFI_STATUS + EFIAPI + Tpm2NvDefineSpace ( + IN TPMI_RH_PROVISION AuthHandle, +- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN TPM2B_AUTH *Auth, + IN TPM2B_NV_PUBLIC *NvPublic + ) +@@ -525,7 +525,7 @@ EFIAPI + Tpm2NvRead ( + IN TPMI_RH_NV_AUTH AuthHandle, + IN TPMI_RH_NV_INDEX NvIndex, +- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN UINT16 Size, + IN UINT16 Offset, + IN OUT TPM2B_MAX_BUFFER *OutData +@@ -670,7 +670,7 @@ EFIAPI + Tpm2NvWrite ( + IN TPMI_RH_NV_AUTH AuthHandle, + IN TPMI_RH_NV_INDEX NvIndex, +- IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL ++ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN TPM2B_MAX_BUFFER *InData, + IN UINT16 Offset + ) +diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c +index 282fdca9d3..1cdc842966 100644 +--- a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c ++++ b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c +@@ -53,7 +53,7 @@ EFI_STATUS + EFIAPI + RngGetRNG ( + IN EFI_RNG_PROTOCOL *This, +- IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL ++ IN EFI_RNG_ALGORITHM *RNGAlgorithm OPTIONAL, + IN UINTN RNGValueLength, + OUT UINT8 *RNGValue + ) +diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c +index d0e6b7de06..834123b945 100644 +--- a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c ++++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c +@@ -49,7 +49,7 @@ EFI_STATUS + EFIAPI + RngGetRNG ( + IN EFI_RNG_PROTOCOL *This, +- IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL ++ IN EFI_RNG_ALGORITHM *RNGAlgorithm OPTIONAL, + IN UINTN RNGValueLength, + OUT UINT8 *RNGValue + ) +diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h +index 2660ed5875..25cccbe92c 100644 +--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h ++++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h +@@ -67,7 +67,7 @@ EFI_STATUS + EFIAPI + RngGetRNG ( + IN EFI_RNG_PROTOCOL *This, +- IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL ++ IN EFI_RNG_ALGORITHM *RNGAlgorithm OPTIONAL, + IN UINTN RNGValueLength, + OUT UINT8 *RNGValue + ); +diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c +index 68cd62307c..09cb4b0ee9 100644 +--- a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c ++++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigImpl.c +@@ -56,7 +56,7 @@ HII_VENDOR_DEVICE_PATH mTcgHiiVendorDevicePath = { + EFI_STATUS + GetTpmState ( + IN EFI_TCG_PROTOCOL *TcgProtocol, +- OUT BOOLEAN *TpmEnable, OPTIONAL ++ OUT BOOLEAN *TpmEnable OPTIONAL, + OUT BOOLEAN *TpmActivate OPTIONAL + ) + { +-- +2.41.0 + diff --git a/edk2-SecurityPkg-Change-use-of-EFI_D_-to-DEBUG_.patch b/edk2-SecurityPkg-Change-use-of-EFI_D_-to-DEBUG_.patch new file mode 100644 index 0000000..1d2659d --- /dev/null +++ b/edk2-SecurityPkg-Change-use-of-EFI_D_-to-DEBUG_.patch @@ -0,0 +1,2923 @@ +From a026f3bb9ee971b281638b5d4e6daf0bddf32103 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 7 Feb 2024 11:56:37 -0500 +Subject: [PATCH 01/17] SecurityPkg: Change use of EFI_D_* to DEBUG_* + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [1/13] 651bdf05edd106945ec4d5e18b4f08dc0e28055c (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21154 +CVE: CVE-2022-36763 +Upstream: Merged + +commit 292b44b682d88e6605645ec61ca7081c0a31b059 +Author: Michael D Kinney +Date: Tue Nov 16 19:21:36 2021 -0800 + + SecurityPkg: Change use of EFI_D_* to DEBUG_* + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3739 + + Update all use of EFI_D_* defines in DEBUG() macros to DEBUG_* defines. + + Cc: Andrew Fish + Cc: Leif Lindholm + Cc: Michael Kubacki + Signed-off-by: Michael D Kinney + Reviewed-by: Jian J Wang + +Signed-off-by: Jon Maloy +--- + SecurityPkg/Hash2DxeCrypto/Driver.c | 2 +- + .../Library/AuthVariableLib/AuthService.c | 2 +- + .../Library/AuthVariableLib/AuthVariableLib.c | 16 +- + .../DxeImageVerificationLib/Measurement.c | 8 +- + .../DxeTcg2PhysicalPresenceLib.c | 36 ++-- + .../DxeTcgPhysicalPresenceLib.c | 13 +- + .../DxeTpm2MeasureBootLib.c | 14 +- + .../DxeTpmMeasureBootLib.c | 4 +- + SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c | 12 +- + .../Library/Tpm12CommandLib/Tpm12Pcr.c | 2 +- + .../Tpm12CommandLib/Tpm12PhysicalPresence.c | 2 +- + .../Library/Tpm12DeviceLibDTpm/Tpm12Tis.c | 24 +-- + .../Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.c | 4 +- + .../Library/Tpm2CommandLib/Tpm2Context.c | 5 +- + .../Tpm2CommandLib/Tpm2DictionaryAttack.c | 8 +- + .../Tpm2EnhancedAuthorization.c | 16 +- + SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c | 2 +- + .../Library/Tpm2CommandLib/Tpm2Hierarchy.c | 40 ++-- + .../Library/Tpm2CommandLib/Tpm2Integrity.c | 42 ++-- + .../Tpm2CommandLib/Tpm2Miscellaneous.c | 4 +- + .../Library/Tpm2CommandLib/Tpm2NVStorage.c | 36 ++-- + .../Library/Tpm2CommandLib/Tpm2Sequences.c | 26 +-- + .../Library/Tpm2CommandLib/Tpm2Session.c | 6 +- + .../Library/Tpm2CommandLib/Tpm2Startup.c | 4 +- + .../Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c | 50 ++--- + .../Library/Tpm2DeviceLibDTpm/Tpm2Tis.c | 24 +-- + .../Tpm2DeviceLibRouterPei.c | 2 +- + .../Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.c | 4 +- + .../Tcg/MemoryOverwriteControl/TcgMor.c | 20 +- + .../TcgMorLockSmm.c | 3 +- + SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDriver.c | 4 +- + SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c | 2 +- + SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c | 6 +- + SecurityPkg/Tcg/Tcg2Config/TpmDetection.c | 6 +- + SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c | 188 +++++++++--------- + SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c | 22 +- + SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c | 9 +- + .../Tcg/TcgConfigDxe/TcgConfigDriver.c | 4 +- + SecurityPkg/Tcg/TcgDxe/TcgDxe.c | 28 +-- + SecurityPkg/Tcg/TcgPei/TcgPei.c | 8 +- + SecurityPkg/Tcg/TcgSmm/TcgSmm.c | 19 +- + .../SecureBootConfigImpl.c | 16 +- + 42 files changed, 368 insertions(+), 375 deletions(-) + +diff --git a/SecurityPkg/Hash2DxeCrypto/Driver.c b/SecurityPkg/Hash2DxeCrypto/Driver.c +index 4627061a28..0d123b2a2f 100644 +--- a/SecurityPkg/Hash2DxeCrypto/Driver.c ++++ b/SecurityPkg/Hash2DxeCrypto/Driver.c +@@ -142,7 +142,7 @@ Hash2ServiceBindingDestroyChild ( + } + } + if (Instance == NULL) { +- DEBUG ((EFI_D_ERROR, "Hash2ServiceBindingDestroyChild - Invalid handle\n")); ++ DEBUG ((DEBUG_ERROR, "Hash2ServiceBindingDestroyChild - Invalid handle\n")); + return EFI_UNSUPPORTED; + } + +diff --git a/SecurityPkg/Library/AuthVariableLib/AuthService.c b/SecurityPkg/Library/AuthVariableLib/AuthService.c +index 4fb609504d..aa9ebaf3be 100644 +--- a/SecurityPkg/Library/AuthVariableLib/AuthService.c ++++ b/SecurityPkg/Library/AuthVariableLib/AuthService.c +@@ -1752,7 +1752,7 @@ CleanCertsFromDb ( + AuthVariableInfo.Attributes | EFI_VARIABLE_NON_VOLATILE + ); + CertCleaned = TRUE; +- DEBUG((EFI_D_INFO, "Recovery!! Cert for Auth Variable %s Guid %g is removed for consistency\n", VariableName, &AuthVarGuid)); ++ DEBUG((DEBUG_INFO, "Recovery!! Cert for Auth Variable %s Guid %g is removed for consistency\n", VariableName, &AuthVarGuid)); + FreePool(VariableName); + break; + } +diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c +index 122b3b0bf4..7f31458edb 100644 +--- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c ++++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c +@@ -153,9 +153,9 @@ AuthVariableLibInitialize ( + + Status = AuthServiceInternalFindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME)); ++ DEBUG ((DEBUG_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME)); + } else { +- DEBUG ((EFI_D_INFO, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME)); ++ DEBUG ((DEBUG_INFO, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME)); + } + + // +@@ -238,9 +238,9 @@ AuthVariableLibInitialize ( + return Status; + } + +- DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SETUP_MODE_NAME, mPlatformMode)); +- DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME, SecureBootMode)); +- DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable)); ++ DEBUG ((DEBUG_INFO, "Variable %s is %x\n", EFI_SETUP_MODE_NAME, mPlatformMode)); ++ DEBUG ((DEBUG_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME, SecureBootMode)); ++ DEBUG ((DEBUG_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable)); + + // + // Initialize "CustomMode" in STANDARD_SECURE_BOOT_MODE state. +@@ -257,7 +257,7 @@ AuthVariableLibInitialize ( + return Status; + } + +- DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_CUSTOM_MODE_NAME, CustomMode)); ++ DEBUG ((DEBUG_INFO, "Variable %s is %x\n", EFI_CUSTOM_MODE_NAME, CustomMode)); + + // + // Check "certdb" variable's existence. +@@ -289,7 +289,7 @@ AuthVariableLibInitialize ( + // + Status = CleanCertsFromDb(); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Clean up CertDB fail! Status %x\n", Status)); ++ DEBUG ((DEBUG_ERROR, "Clean up CertDB fail! Status %x\n", Status)); + return Status; + } + } +@@ -347,7 +347,7 @@ AuthVariableLibInitialize ( + return Status; + } + +- DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_VENDOR_KEYS_VARIABLE_NAME, mVendorKeyState)); ++ DEBUG ((DEBUG_INFO, "Variable %s is %x\n", EFI_VENDOR_KEYS_VARIABLE_NAME, mVendorKeyState)); + + AuthVarLibContextOut->StructVersion = AUTH_VAR_LIB_CONTEXT_OUT_STRUCT_VERSION; + AuthVarLibContextOut->StructSize = sizeof (AUTH_VAR_LIB_CONTEXT_OUT); +diff --git a/SecurityPkg/Library/DxeImageVerificationLib/Measurement.c b/SecurityPkg/Library/DxeImageVerificationLib/Measurement.c +index 86d8eb4840..351107785d 100644 +--- a/SecurityPkg/Library/DxeImageVerificationLib/Measurement.c ++++ b/SecurityPkg/Library/DxeImageVerificationLib/Measurement.c +@@ -253,8 +253,8 @@ MeasureVariable ( + VarSize + ); + +- DEBUG ((EFI_D_INFO, "DxeImageVerification: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY)); +- DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid)); ++ DEBUG ((DEBUG_INFO, "DxeImageVerification: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY)); ++ DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid)); + + Status = TpmMeasureAndLogData ( + 7, +@@ -295,7 +295,7 @@ SecureBootHook ( + } + + if (IsDataMeasured (VariableName, VendorGuid, Data, DataSize)) { +- DEBUG ((EFI_D_ERROR, "MeasureSecureAuthorityVariable - IsDataMeasured\n")); ++ DEBUG ((DEBUG_ERROR, "MeasureSecureAuthorityVariable - IsDataMeasured\n")); + return ; + } + +@@ -305,7 +305,7 @@ SecureBootHook ( + Data, + DataSize + ); +- DEBUG ((EFI_D_INFO, "MeasureBootPolicyVariable - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "MeasureBootPolicyVariable - %r\n", Status)); + + if (!EFI_ERROR (Status)) { + AddDataMeasured (VariableName, VendorGuid, Data, DataSize); +diff --git a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c +index 1e00476509..fce5c0af50 100644 +--- a/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c ++++ b/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c +@@ -84,15 +84,15 @@ Tpm2CommandClear ( + CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size); + } + +- DEBUG ((EFI_D_INFO, "Tpm2ClearControl ... \n")); ++ DEBUG ((DEBUG_INFO, "Tpm2ClearControl ... \n")); + Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO); +- DEBUG ((EFI_D_INFO, "Tpm2ClearControl - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "Tpm2ClearControl - %r\n", Status)); + if (EFI_ERROR (Status)) { + goto Done; + } +- DEBUG ((EFI_D_INFO, "Tpm2Clear ... \n")); ++ DEBUG ((DEBUG_INFO, "Tpm2Clear ... \n")); + Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession); +- DEBUG ((EFI_D_INFO, "Tpm2Clear - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "Tpm2Clear - %r\n", Status)); + + Done: + ZeroMem (&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac)); +@@ -126,7 +126,7 @@ Tpm2CommandChangeEps ( + } + + Status = Tpm2ChangeEPS (TPM_RH_PLATFORM, AuthSession); +- DEBUG ((EFI_D_INFO, "Tpm2ChangeEPS - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "Tpm2ChangeEPS - %r\n", Status)); + + ZeroMem(&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac)); + return Status; +@@ -913,7 +913,7 @@ Tcg2PhysicalPresenceLibProcessRequest ( + &gEfiTcg2PhysicalPresenceGuid + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status)); + ASSERT_EFI_ERROR (Status); + } + } +@@ -922,7 +922,7 @@ Tcg2PhysicalPresenceLibProcessRequest ( + // Check S4 resume + // + if (GetBootModeHob () == BOOT_ON_S4_RESUME) { +- DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n")); ++ DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n")); + return ; + } + +@@ -947,7 +947,7 @@ Tcg2PhysicalPresenceLibProcessRequest ( + &PpiFlags + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status)); + return ; + } + DEBUG((DEBUG_INFO, "[TPM2] Initial physical presence flags value is 0x%x\n", PpiFlags.PPFlags)); +@@ -975,18 +975,18 @@ Tcg2PhysicalPresenceLibProcessRequest ( + &TcgPpData + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status)); + return ; + } + } + +- DEBUG ((EFI_D_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest)); ++ DEBUG ((DEBUG_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest)); + + // + // Execute pending TPM request. + // + Tcg2ExecutePendingTpmRequest (PlatformAuth, &TcgPpData, &PpiFlags); +- DEBUG ((EFI_D_INFO, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags.PPFlags)); ++ DEBUG ((DEBUG_INFO, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags.PPFlags)); + + } + +@@ -1016,7 +1016,7 @@ Tcg2PhysicalPresenceLibNeedUserConfirm( + // Check S4 resume + // + if (GetBootModeHob () == BOOT_ON_S4_RESUME) { +- DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n")); ++ DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n")); + return FALSE; + } + +@@ -1092,7 +1092,7 @@ Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction ( + UINTN DataSize; + EFI_TCG2_PHYSICAL_PRESENCE PpData; + +- DEBUG ((EFI_D_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n")); ++ DEBUG ((DEBUG_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n")); + + // + // Get the Physical Presence variable +@@ -1108,7 +1108,7 @@ Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction ( + if (EFI_ERROR (Status)) { + *MostRecentRequest = 0; + *Response = 0; +- DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status)); + return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE; + } + +@@ -1143,7 +1143,7 @@ Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction ( + EFI_TCG2_PHYSICAL_PRESENCE PpData; + EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags; + +- DEBUG ((EFI_D_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter)); ++ DEBUG ((DEBUG_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter)); + + // + // Get the Physical Presence variable +@@ -1157,7 +1157,7 @@ Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction ( + &PpData + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status)); + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE; + } + +@@ -1179,7 +1179,7 @@ Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction ( + &PpData + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status)); + return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE; + } + } +@@ -1217,7 +1217,7 @@ Tcg2PhysicalPresenceLibGetManagementFlags ( + EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags; + UINTN DataSize; + +- DEBUG ((EFI_D_INFO, "[TPM2] GetManagementFlags\n")); ++ DEBUG ((DEBUG_INFO, "[TPM2] GetManagementFlags\n")); + + DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS); + Status = gRT->GetVariable ( +diff --git a/SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.c b/SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.c +index ba1abe9e08..ab7f664c7a 100644 +--- a/SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.c ++++ b/SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.c +@@ -1203,11 +1203,11 @@ TcgPhysicalPresenceLibProcessRequest ( + &PpiFlags + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "[TPM] Set physical presence flag failed, Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM] Set physical presence flag failed, Status = %r\n", Status)); + return ; + } + } +- DEBUG ((EFI_D_INFO, "[TPM] PpiFlags = %x\n", PpiFlags.PPFlags)); ++ DEBUG ((DEBUG_INFO, "[TPM] PpiFlags = %x\n", PpiFlags.PPFlags)); + + // + // This flags variable controls whether physical presence is required for TPM command. +@@ -1221,7 +1221,7 @@ TcgPhysicalPresenceLibProcessRequest ( + &gEfiPhysicalPresenceGuid + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "[TPM] Error when lock variable %s, Status = %r\n", PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM] Error when lock variable %s, Status = %r\n", PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status)); + ASSERT_EFI_ERROR (Status); + } + } +@@ -1248,12 +1248,12 @@ TcgPhysicalPresenceLibProcessRequest ( + &TcgPpData + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "[TPM] Set physical presence variable failed, Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM] Set physical presence variable failed, Status = %r\n", Status)); + return; + } + } + +- DEBUG ((EFI_D_INFO, "[TPM] Flags=%x, PPRequest=%x\n", PpiFlags.PPFlags, TcgPpData.PPRequest)); ++ DEBUG ((DEBUG_INFO, "[TPM] Flags=%x, PPRequest=%x\n", PpiFlags.PPFlags, TcgPpData.PPRequest)); + + if (TcgPpData.PPRequest == PHYSICAL_PRESENCE_NO_ACTION) { + // +@@ -1292,7 +1292,7 @@ TcgPhysicalPresenceLibProcessRequest ( + // Execute pending TPM request. + // + ExecutePendingTpmRequest (TcgProtocol, &TcgPpData, PpiFlags); +- DEBUG ((EFI_D_INFO, "[TPM] PPResponse = %x\n", TcgPpData.PPResponse)); ++ DEBUG ((DEBUG_INFO, "[TPM] PPResponse = %x\n", TcgPpData.PPResponse)); + + // + // Lock physical presence. +@@ -1397,4 +1397,3 @@ TcgPhysicalPresenceLibNeedUserConfirm( + + return FALSE; + } +- +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +index 92eac71580..a531385f81 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +@@ -164,7 +164,7 @@ Tcg2MeasureGptTable ( + (UINT8 *)PrimaryHeader + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Failed to Read Partition Table Header!\n")); ++ DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n")); + FreePool (PrimaryHeader); + return EFI_DEVICE_ERROR; + } +@@ -334,7 +334,7 @@ Tcg2MeasurePeImage ( + break; + default: + DEBUG (( +- EFI_D_ERROR, ++ DEBUG_ERROR, + "Tcg2MeasurePeImage: Unknown subsystem type %d", + ImageType + )); +@@ -441,7 +441,7 @@ DxeTpm2MeasureBootHandler ( + // Tcg2 protocol is not installed. So, TPM2 is not present. + // Don't do any measurement, and directly return EFI_SUCCESS. + // +- DEBUG ((EFI_D_VERBOSE, "DxeTpm2MeasureBootHandler - Tcg2 - %r\n", Status)); ++ DEBUG ((DEBUG_VERBOSE, "DxeTpm2MeasureBootHandler - Tcg2 - %r\n", Status)); + return EFI_SUCCESS; + } + +@@ -454,7 +454,7 @@ DxeTpm2MeasureBootHandler ( + // + // TPM device doesn't work or activate. + // +- DEBUG ((EFI_D_ERROR, "DxeTpm2MeasureBootHandler (%r) - TPMPresentFlag - %x\n", Status, ProtocolCapability.TPMPresentFlag)); ++ DEBUG ((DEBUG_ERROR, "DxeTpm2MeasureBootHandler (%r) - TPMPresentFlag - %x\n", Status, ProtocolCapability.TPMPresentFlag)); + return EFI_SUCCESS; + } + +@@ -503,7 +503,7 @@ DxeTpm2MeasureBootHandler ( + // Measure GPT disk. + // + Status = Tcg2MeasureGptTable (Tcg2Protocol, Handle); +- DEBUG ((EFI_D_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasureGptTable - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasureGptTable - %r\n", Status)); + if (!EFI_ERROR (Status)) { + // + // GPT disk check done. +@@ -654,7 +654,7 @@ DxeTpm2MeasureBootHandler ( + ImageContext.ImageType, + DevicePathNode + ); +- DEBUG ((EFI_D_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasurePeImage - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasurePeImage - %r\n", Status)); + } + + // +@@ -665,7 +665,7 @@ Finish: + FreePool (OrigDevicePathNode); + } + +- DEBUG ((EFI_D_INFO, "DxeTpm2MeasureBootHandler - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - %r\n", Status)); + + return Status; + } +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +index d990eb2ad3..4e74cd9db6 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +@@ -164,7 +164,7 @@ TcgMeasureGptTable ( + (UINT8 *)PrimaryHeader + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Failed to Read Partition Table Header!\n")); ++ DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n")); + FreePool (PrimaryHeader); + return EFI_DEVICE_ERROR; + } +@@ -355,7 +355,7 @@ TcgMeasurePeImage ( + break; + default: + DEBUG (( +- EFI_D_ERROR, ++ DEBUG_ERROR, + "TcgMeasurePeImage: Unknown subsystem type %d", + ImageType + )); +diff --git a/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c b/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c +index bd24958505..876b15fad4 100644 +--- a/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c ++++ b/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c +@@ -237,7 +237,7 @@ HashAndExtend ( + TPM2B_EVENT EventData; + TPM2B_DIGEST Result; + +- DEBUG((EFI_D_VERBOSE, "\n HashAndExtend Entry \n")); ++ DEBUG((DEBUG_VERBOSE, "\n HashAndExtend Entry \n")); + + SequenceHandle = 0xFFFFFFFF; // Know bad value + +@@ -257,7 +257,7 @@ HashAndExtend ( + if (EFI_ERROR(Status)) { + return EFI_DEVICE_ERROR; + } +- DEBUG((EFI_D_VERBOSE, "\n Tpm2HashSequenceStart Success \n")); ++ DEBUG((DEBUG_VERBOSE, "\n Tpm2HashSequenceStart Success \n")); + + Buffer = (UINT8 *)(UINTN)DataToHash; + for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) { +@@ -271,7 +271,7 @@ HashAndExtend ( + return EFI_DEVICE_ERROR; + } + } +- DEBUG((EFI_D_VERBOSE, "\n Tpm2SequenceUpdate Success \n")); ++ DEBUG((DEBUG_VERBOSE, "\n Tpm2SequenceUpdate Success \n")); + + HashBuffer.size = (UINT16)HashLen; + CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen); +@@ -289,7 +289,7 @@ HashAndExtend ( + if (EFI_ERROR(Status)) { + return EFI_DEVICE_ERROR; + } +- DEBUG((EFI_D_VERBOSE, "\n Tpm2EventSequenceComplete Success \n")); ++ DEBUG((DEBUG_VERBOSE, "\n Tpm2EventSequenceComplete Success \n")); + } else { + Status = Tpm2SequenceComplete ( + SequenceHandle, +@@ -299,7 +299,7 @@ HashAndExtend ( + if (EFI_ERROR(Status)) { + return EFI_DEVICE_ERROR; + } +- DEBUG((EFI_D_VERBOSE, "\n Tpm2SequenceComplete Success \n")); ++ DEBUG((DEBUG_VERBOSE, "\n Tpm2SequenceComplete Success \n")); + + DigestList->count = 1; + DigestList->digests[0].hashAlg = AlgoId; +@@ -311,7 +311,7 @@ HashAndExtend ( + if (EFI_ERROR(Status)) { + return EFI_DEVICE_ERROR; + } +- DEBUG((EFI_D_VERBOSE, "\n Tpm2PcrExtend Success \n")); ++ DEBUG((DEBUG_VERBOSE, "\n Tpm2PcrExtend Success \n")); + } + + return EFI_SUCCESS; +diff --git a/SecurityPkg/Library/Tpm12CommandLib/Tpm12Pcr.c b/SecurityPkg/Library/Tpm12CommandLib/Tpm12Pcr.c +index 562cf582de..4fbcb3617c 100644 +--- a/SecurityPkg/Library/Tpm12CommandLib/Tpm12Pcr.c ++++ b/SecurityPkg/Library/Tpm12CommandLib/Tpm12Pcr.c +@@ -69,7 +69,7 @@ Tpm12Extend ( + } + + if (SwapBytes32(Response.Hdr.returnCode) != TPM_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm12Extend: Response Code error! 0x%08x\r\n", SwapBytes32(Response.Hdr.returnCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm12Extend: Response Code error! 0x%08x\r\n", SwapBytes32(Response.Hdr.returnCode))); + return EFI_DEVICE_ERROR; + } + +diff --git a/SecurityPkg/Library/Tpm12CommandLib/Tpm12PhysicalPresence.c b/SecurityPkg/Library/Tpm12CommandLib/Tpm12PhysicalPresence.c +index 208bff594d..6714d17d8e 100644 +--- a/SecurityPkg/Library/Tpm12CommandLib/Tpm12PhysicalPresence.c ++++ b/SecurityPkg/Library/Tpm12CommandLib/Tpm12PhysicalPresence.c +@@ -58,7 +58,7 @@ Tpm12PhysicalPresence ( + } + + if (SwapBytes32(Response.returnCode) != TPM_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm12PhysicalPresence: Response Code error! 0x%08x\r\n", SwapBytes32(Response.returnCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm12PhysicalPresence: Response Code error! 0x%08x\r\n", SwapBytes32(Response.returnCode))); + return EFI_DEVICE_ERROR; + } + +diff --git a/SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12Tis.c b/SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12Tis.c +index f858090479..b8218f122d 100644 +--- a/SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12Tis.c ++++ b/SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12Tis.c +@@ -266,22 +266,22 @@ Tpm12TisTpmCommand ( + DEBUG_CODE ( + UINTN DebugSize; + +- DEBUG ((EFI_D_VERBOSE, "Tpm12TisTpmCommand Send - ")); ++ DEBUG ((DEBUG_VERBOSE, "Tpm12TisTpmCommand Send - ")); + if (SizeIn > 0x100) { + DebugSize = 0x40; + } else { + DebugSize = SizeIn; + } + for (Index = 0; Index < DebugSize; Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferIn[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index])); + } + if (DebugSize != SizeIn) { +- DEBUG ((EFI_D_VERBOSE, "...... ")); ++ DEBUG ((DEBUG_VERBOSE, "...... ")); + for (Index = SizeIn - 0x20; Index < SizeIn; Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferIn[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index])); + } + } +- DEBUG ((EFI_D_VERBOSE, "\n")); ++ DEBUG ((DEBUG_VERBOSE, "\n")); + ); + TpmOutSize = 0; + +@@ -352,11 +352,11 @@ Tpm12TisTpmCommand ( + } + } + DEBUG_CODE ( +- DEBUG ((EFI_D_VERBOSE, "Tpm12TisTpmCommand ReceiveHeader - ")); ++ DEBUG ((DEBUG_VERBOSE, "Tpm12TisTpmCommand ReceiveHeader - ")); + for (Index = 0; Index < sizeof (TPM_RSP_COMMAND_HDR); Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferOut[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index])); + } +- DEBUG ((EFI_D_VERBOSE, "\n")); ++ DEBUG ((DEBUG_VERBOSE, "\n")); + ); + // + // Check the response data header (tag, parasize and returncode) +@@ -364,7 +364,7 @@ Tpm12TisTpmCommand ( + CopyMem (&Data16, BufferOut, sizeof (UINT16)); + RspTag = SwapBytes16 (Data16); + if (RspTag != TPM_TAG_RSP_COMMAND && RspTag != TPM_TAG_RSP_AUTH1_COMMAND && RspTag != TPM_TAG_RSP_AUTH2_COMMAND) { +- DEBUG ((EFI_D_ERROR, "TPM12: Response tag error - current tag value is %x\n", RspTag)); ++ DEBUG ((DEBUG_ERROR, "TPM12: Response tag error - current tag value is %x\n", RspTag)); + Status = EFI_UNSUPPORTED; + goto Exit; + } +@@ -396,11 +396,11 @@ Tpm12TisTpmCommand ( + } + Exit: + DEBUG_CODE ( +- DEBUG ((EFI_D_VERBOSE, "Tpm12TisTpmCommand Receive - ")); ++ DEBUG ((DEBUG_VERBOSE, "Tpm12TisTpmCommand Receive - ")); + for (Index = 0; Index < TpmOutSize; Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferOut[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index])); + } +- DEBUG ((EFI_D_VERBOSE, "\n")); ++ DEBUG ((DEBUG_VERBOSE, "\n")); + ); + MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY); + return Status; +diff --git a/SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.c b/SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.c +index f975b1bc8a..2869f9ec83 100644 +--- a/SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.c ++++ b/SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.c +@@ -47,7 +47,7 @@ Tpm12SubmitCommand ( + // + // TCG protocol is not installed. So, TPM12 is not present. + // +- DEBUG ((EFI_D_ERROR, "Tpm12SubmitCommand - TCG - %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "Tpm12SubmitCommand - TCG - %r\n", Status)); + return EFI_NOT_FOUND; + } + } +@@ -91,7 +91,7 @@ Tpm12RequestUseTpm ( + // + // TCG protocol is not installed. So, TPM12 is not present. + // +- DEBUG ((EFI_D_ERROR, "Tpm12RequestUseTpm - TCG - %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "Tpm12RequestUseTpm - TCG - %r\n", Status)); + return EFI_NOT_FOUND; + } + } +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Context.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Context.c +index 80b15a51f0..f284f8d21a 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Context.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Context.c +@@ -67,14 +67,13 @@ Tpm2FlushContext ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2FlushContext - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2FlushContext - RecvBufferSize Error - %x\n", RecvBufferSize)); + return EFI_DEVICE_ERROR; + } + if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2FlushContext - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2FlushContext - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; + } +- +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2DictionaryAttack.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2DictionaryAttack.c +index f502113873..2f830e0aea 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2DictionaryAttack.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2DictionaryAttack.c +@@ -102,12 +102,12 @@ Tpm2DictionaryAttackLockReset ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackLockReset - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2DictionaryAttackLockReset - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackLockReset - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2DictionaryAttackLockReset - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +@@ -193,12 +193,12 @@ Tpm2DictionaryAttackParameters ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackParameters - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2DictionaryAttackParameters - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2DictionaryAttackParameters - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2DictionaryAttackParameters - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c +index 61c6367262..0404c0f321 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2EnhancedAuthorization.c +@@ -159,12 +159,12 @@ Tpm2PolicySecret ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +@@ -263,11 +263,11 @@ Tpm2PolicyOR ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2PolicyOR - RecvBufferSize Error - %x\n", RecvBufferSize)); + return EFI_DEVICE_ERROR; + } + if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2PolicyOR - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + +@@ -318,11 +318,11 @@ Tpm2PolicyCommandCode ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2PolicyCommandCode - RecvBufferSize Error - %x\n", RecvBufferSize)); + return EFI_DEVICE_ERROR; + } + if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2PolicyCommandCode - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + +@@ -373,11 +373,11 @@ Tpm2PolicyGetDigest ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2PolicyGetDigest - RecvBufferSize Error - %x\n", RecvBufferSize)); + return EFI_DEVICE_ERROR; + } + if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2PolicyGetDigest - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c +index 36c240d122..13eeb6ec18 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c +@@ -266,7 +266,7 @@ CopyDigestListToBuffer ( + Buffer = (UINT8 *)Buffer + sizeof(DigestList->count); + for (Index = 0; Index < DigestList->count; Index++) { + if (!IsHashAlgSupportedInHashAlgorithmMask(DigestList->digests[Index].hashAlg, HashAlgorithmMask)) { +- DEBUG ((EFI_D_ERROR, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList->digests[Index].hashAlg)); ++ DEBUG ((DEBUG_ERROR, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList->digests[Index].hashAlg)); + continue; + } + CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof(DigestList->digests[Index].hashAlg)); +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c +index dc36963c0e..043d358a06 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c +@@ -184,12 +184,12 @@ Tpm2SetPrimaryPolicy ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2SetPrimaryPolicy - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2SetPrimaryPolicy - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2SetPrimaryPolicy - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2SetPrimaryPolicy - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +@@ -252,7 +252,7 @@ Tpm2Clear ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "Clear: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "Clear: Failed ExecuteCommand: Buffer Too Small\r\n")); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -262,7 +262,7 @@ Tpm2Clear ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "Clear: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "Clear: Response size too large! %d\r\n", RespSize)); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -271,7 +271,7 @@ Tpm2Clear ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Clear: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Clear: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +@@ -346,7 +346,7 @@ Tpm2ClearControl ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "ClearControl: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "ClearControl: Failed ExecuteCommand: Buffer Too Small\r\n")); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -356,7 +356,7 @@ Tpm2ClearControl ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "ClearControl: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "ClearControl: Response size too large! %d\r\n", RespSize)); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -365,7 +365,7 @@ Tpm2ClearControl ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "ClearControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "ClearControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +@@ -459,7 +459,7 @@ Tpm2HierarchyChangeAuth ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "HierarchyChangeAuth: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "HierarchyChangeAuth: Failed ExecuteCommand: Buffer Too Small\r\n")); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -469,7 +469,7 @@ Tpm2HierarchyChangeAuth ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "HierarchyChangeAuth: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "HierarchyChangeAuth: Response size too large! %d\r\n", RespSize)); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -478,7 +478,7 @@ Tpm2HierarchyChangeAuth ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG((EFI_D_ERROR,"HierarchyChangeAuth: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG((DEBUG_ERROR,"HierarchyChangeAuth: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +@@ -557,7 +557,7 @@ Tpm2ChangeEPS ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "ChangeEPS: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "ChangeEPS: Failed ExecuteCommand: Buffer Too Small\r\n")); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -567,7 +567,7 @@ Tpm2ChangeEPS ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "ChangeEPS: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "ChangeEPS: Response size too large! %d\r\n", RespSize)); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -576,7 +576,7 @@ Tpm2ChangeEPS ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG((EFI_D_ERROR,"ChangeEPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG((DEBUG_ERROR,"ChangeEPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +@@ -655,7 +655,7 @@ Tpm2ChangePPS ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "ChangePPS: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "ChangePPS: Failed ExecuteCommand: Buffer Too Small\r\n")); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -665,7 +665,7 @@ Tpm2ChangePPS ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "ChangePPS: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "ChangePPS: Response size too large! %d\r\n", RespSize)); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -674,7 +674,7 @@ Tpm2ChangePPS ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG((EFI_D_ERROR,"ChangePPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG((DEBUG_ERROR,"ChangePPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +@@ -763,7 +763,7 @@ Tpm2HierarchyControl ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "HierarchyControl: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "HierarchyControl: Failed ExecuteCommand: Buffer Too Small\r\n")); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -773,7 +773,7 @@ Tpm2HierarchyControl ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "HierarchyControl: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "HierarchyControl: Response size too large! %d\r\n", RespSize)); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -782,7 +782,7 @@ Tpm2HierarchyControl ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG((EFI_D_ERROR,"HierarchyControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG((DEBUG_ERROR,"HierarchyControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c +index ddb15178fb..8c87de0b0c 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c +@@ -130,7 +130,7 @@ Tpm2PcrExtend ( + Buffer += sizeof(UINT16); + DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg); + if (DigestSize == 0) { +- DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg)); ++ DEBUG ((DEBUG_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg)); + return EFI_DEVICE_ERROR; + } + CopyMem( +@@ -151,7 +151,7 @@ Tpm2PcrExtend ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer Too Small\r\n")); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -160,7 +160,7 @@ Tpm2PcrExtend ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n", RespSize)); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -168,7 +168,7 @@ Tpm2PcrExtend ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + +@@ -246,7 +246,7 @@ Tpm2PcrEvent ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Failed ExecuteCommand: Buffer Too Small\r\n")); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -255,7 +255,7 @@ Tpm2PcrEvent ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Response size too large! %d\r\n", RespSize)); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -263,7 +263,7 @@ Tpm2PcrEvent ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + +@@ -284,7 +284,7 @@ Tpm2PcrEvent ( + Buffer += sizeof(UINT16); + DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg); + if (DigestSize == 0) { +- DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg)); ++ DEBUG ((DEBUG_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg)); + return EFI_DEVICE_ERROR; + } + CopyMem( +@@ -353,11 +353,11 @@ Tpm2PcrRead ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); + return EFI_DEVICE_ERROR; + } + if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + return EFI_NOT_FOUND; + } + +@@ -369,7 +369,7 @@ Tpm2PcrRead ( + // PcrUpdateCounter + // + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); + return EFI_DEVICE_ERROR; + } + *PcrUpdateCounter = SwapBytes32(RecvBuffer.PcrUpdateCounter); +@@ -378,7 +378,7 @@ Tpm2PcrRead ( + // PcrSelectionOut + // + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); + return EFI_DEVICE_ERROR; + } + PcrSelectionOut->count = SwapBytes32(RecvBuffer.PcrSelectionOut.count); +@@ -388,7 +388,7 @@ Tpm2PcrRead ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count) + sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); + return EFI_DEVICE_ERROR; + } + for (Index = 0; Index < PcrSelectionOut->count; Index++) { +@@ -513,7 +513,7 @@ Tpm2PcrAllocate ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n")); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -523,7 +523,7 @@ Tpm2PcrAllocate ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize)); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } +@@ -532,7 +532,7 @@ Tpm2PcrAllocate ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG((EFI_D_ERROR,"Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG((DEBUG_ERROR,"Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +@@ -673,15 +673,15 @@ Tpm2PcrAllocateBanks ( + &SizeNeeded, + &SizeAvailable + ); +- DEBUG ((EFI_D_INFO, "Tpm2PcrAllocateBanks call Tpm2PcrAllocate - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "Tpm2PcrAllocateBanks call Tpm2PcrAllocate - %r\n", Status)); + if (EFI_ERROR (Status)) { + goto Done; + } + +- DEBUG ((EFI_D_INFO, "AllocationSuccess - %02x\n", AllocationSuccess)); +- DEBUG ((EFI_D_INFO, "MaxPCR - %08x\n", MaxPCR)); +- DEBUG ((EFI_D_INFO, "SizeNeeded - %08x\n", SizeNeeded)); +- DEBUG ((EFI_D_INFO, "SizeAvailable - %08x\n", SizeAvailable)); ++ DEBUG ((DEBUG_INFO, "AllocationSuccess - %02x\n", AllocationSuccess)); ++ DEBUG ((DEBUG_INFO, "MaxPCR - %08x\n", MaxPCR)); ++ DEBUG ((DEBUG_INFO, "SizeNeeded - %08x\n", SizeNeeded)); ++ DEBUG ((DEBUG_INFO, "SizeAvailable - %08x\n", SizeAvailable)); + + Done: + ZeroMem(&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac)); +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Miscellaneous.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Miscellaneous.c +index 32bff45844..1afc562998 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Miscellaneous.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Miscellaneous.c +@@ -96,12 +96,12 @@ Tpm2SetAlgorithmSet ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2SetAlgorithmSet - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2SetAlgorithmSet - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2SetAlgorithmSet - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2SetAlgorithmSet - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto Done; + } +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c +index 87572de201..fb46af0fed 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c +@@ -200,12 +200,12 @@ Tpm2NvReadPublic ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); + return EFI_DEVICE_ERROR; + } + ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); + if (ResponseCode != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + } + switch (ResponseCode) { + case TPM_RC_SUCCESS: +@@ -220,7 +220,7 @@ Tpm2NvReadPublic ( + } + + if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT16) + sizeof(UINT16)) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); + return EFI_NOT_FOUND; + } + +@@ -240,7 +240,7 @@ Tpm2NvReadPublic ( + } + + if (RecvBufferSize != sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16) + NvNameSize) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - NvPublicSize %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - NvPublicSize %x\n", RecvBufferSize)); + return EFI_NOT_FOUND; + } + +@@ -354,14 +354,14 @@ Tpm2NvDefineSpace ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvDefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + + ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); + if (ResponseCode != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvDefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + } + switch (ResponseCode) { + case TPM_RC_SUCCESS: +@@ -462,14 +462,14 @@ Tpm2NvUndefineSpace ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvUndefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + + ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); + if (ResponseCode != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvUndefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + } + switch (ResponseCode) { + case TPM_RC_SUCCESS: +@@ -577,13 +577,13 @@ Tpm2NvRead ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvRead - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvRead - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); + if (ResponseCode != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvRead - responseCode - %x\n", ResponseCode)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvRead - responseCode - %x\n", ResponseCode)); + } + switch (ResponseCode) { + case TPM_RC_SUCCESS: +@@ -723,13 +723,13 @@ Tpm2NvWrite ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvWrite - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvWrite - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); + if (ResponseCode != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvWrite - responseCode - %x\n", ResponseCode)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvWrite - responseCode - %x\n", ResponseCode)); + } + switch (ResponseCode) { + case TPM_RC_SUCCESS: +@@ -843,14 +843,14 @@ Tpm2NvReadLock ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvReadLock - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvReadLock - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + + ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); + if (ResponseCode != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvReadLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvReadLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + } + switch (ResponseCode) { + case TPM_RC_SUCCESS: +@@ -930,14 +930,14 @@ Tpm2NvWriteLock ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + + ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); + if (ResponseCode != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + } + switch (ResponseCode) { + case TPM_RC_SUCCESS: +@@ -1014,14 +1014,14 @@ Tpm2NvGlobalWriteLock ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvGlobalWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvGlobalWriteLock - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + + ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); + if (ResponseCode != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2NvGlobalWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2NvGlobalWriteLock - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + } + switch (ResponseCode) { + case TPM_RC_SUCCESS: +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c +index 201c2170fc..3d99f0615c 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c +@@ -134,7 +134,7 @@ Tpm2HashSequenceStart ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "HashSequenceStart: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "HashSequenceStart: Failed ExecuteCommand: Buffer Too Small\r\n")); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -143,7 +143,7 @@ Tpm2HashSequenceStart ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "HashSequenceStart: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "HashSequenceStart: Response size too large! %d\r\n", RespSize)); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -151,7 +151,7 @@ Tpm2HashSequenceStart ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "HashSequenceStart: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "HashSequenceStart: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + +@@ -231,7 +231,7 @@ Tpm2SequenceUpdate ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "SequenceUpdate: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "SequenceUpdate: Failed ExecuteCommand: Buffer Too Small\r\n")); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -240,7 +240,7 @@ Tpm2SequenceUpdate ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "SequenceUpdate: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "SequenceUpdate: Response size too large! %d\r\n", RespSize)); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -248,7 +248,7 @@ Tpm2SequenceUpdate ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "SequenceUpdate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "SequenceUpdate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + +@@ -340,7 +340,7 @@ Tpm2EventSequenceComplete ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "EventSequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n")); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -349,7 +349,7 @@ Tpm2EventSequenceComplete ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "EventSequenceComplete: Response size too large! %d\r\n", RespSize)); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -357,7 +357,7 @@ Tpm2EventSequenceComplete ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "EventSequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + +@@ -382,7 +382,7 @@ Tpm2EventSequenceComplete ( + + DigestSize = GetHashSizeFromAlgo (Results->digests[Index].hashAlg); + if (DigestSize == 0) { +- DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Unknown hash algorithm %d\r\n", Results->digests[Index].hashAlg)); ++ DEBUG ((DEBUG_ERROR, "EventSequenceComplete: Unknown hash algorithm %d\r\n", Results->digests[Index].hashAlg)); + return EFI_DEVICE_ERROR; + } + CopyMem( +@@ -466,7 +466,7 @@ Tpm2SequenceComplete ( + } + + if (ResultBufSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "SequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n")); ++ DEBUG ((DEBUG_ERROR, "SequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n")); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -475,7 +475,7 @@ Tpm2SequenceComplete ( + // + RespSize = SwapBytes32(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { +- DEBUG ((EFI_D_ERROR, "SequenceComplete: Response size too large! %d\r\n", RespSize)); ++ DEBUG ((DEBUG_ERROR, "SequenceComplete: Response size too large! %d\r\n", RespSize)); + return EFI_BUFFER_TOO_SMALL; + } + +@@ -483,7 +483,7 @@ Tpm2SequenceComplete ( + // Fail if command failed + // + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "SequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "SequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Session.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Session.c +index 57367432df..4ca616188c 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Session.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Session.c +@@ -124,7 +124,7 @@ Tpm2StartAuthSession ( + break; + default: + ASSERT (FALSE); +- DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - Symmetric->algorithm - %x\n", Symmetric->algorithm)); ++ DEBUG ((DEBUG_ERROR, "Tpm2StartAuthSession - Symmetric->algorithm - %x\n", Symmetric->algorithm)); + return EFI_UNSUPPORTED; + } + +@@ -144,11 +144,11 @@ Tpm2StartAuthSession ( + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { +- DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - RecvBufferSize Error - %x\n", RecvBufferSize)); ++ DEBUG ((DEBUG_ERROR, "Tpm2StartAuthSession - RecvBufferSize Error - %x\n", RecvBufferSize)); + return EFI_DEVICE_ERROR; + } + if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2StartAuthSession - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + +diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Startup.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Startup.c +index 41f2367ba2..645ac49b87 100644 +--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Startup.c ++++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Startup.c +@@ -77,7 +77,7 @@ Tpm2Startup ( + DEBUG ((DEBUG_INFO, "TPM2Startup: TPM_RC_INITIALIZE\n")); + return EFI_SUCCESS; + default: +- DEBUG ((EFI_D_ERROR, "Tpm2Startup: Response Code error! 0x%08x\r\n", ResponseCode)); ++ DEBUG ((DEBUG_ERROR, "Tpm2Startup: Response Code error! 0x%08x\r\n", ResponseCode)); + return EFI_DEVICE_ERROR; + } + } +@@ -113,7 +113,7 @@ Tpm2Shutdown ( + } + + if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { +- DEBUG ((EFI_D_ERROR, "Tpm2Shutdown: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); ++ DEBUG ((DEBUG_ERROR, "Tpm2Shutdown: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); + return EFI_DEVICE_ERROR; + } + +diff --git a/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c b/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c +index f1f8091683..edde7f8e15 100644 +--- a/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c ++++ b/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c +@@ -154,22 +154,22 @@ PtpCrbTpmCommand ( + DEBUG_CODE ( + UINTN DebugSize; + +- DEBUG ((EFI_D_VERBOSE, "PtpCrbTpmCommand Send - ")); ++ DEBUG ((DEBUG_VERBOSE, "PtpCrbTpmCommand Send - ")); + if (SizeIn > 0x100) { + DebugSize = 0x40; + } else { + DebugSize = SizeIn; + } + for (Index = 0; Index < DebugSize; Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferIn[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index])); + } + if (DebugSize != SizeIn) { +- DEBUG ((EFI_D_VERBOSE, "...... ")); ++ DEBUG ((DEBUG_VERBOSE, "...... ")); + for (Index = SizeIn - 0x20; Index < SizeIn; Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferIn[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index])); + } + } +- DEBUG ((EFI_D_VERBOSE, "\n")); ++ DEBUG ((DEBUG_VERBOSE, "\n")); + ); + TpmOutSize = 0; + +@@ -286,11 +286,11 @@ PtpCrbTpmCommand ( + BufferOut[Index] = MmioRead8 ((UINTN)&CrbReg->CrbDataBuffer[Index]); + } + DEBUG_CODE ( +- DEBUG ((EFI_D_VERBOSE, "PtpCrbTpmCommand ReceiveHeader - ")); ++ DEBUG ((DEBUG_VERBOSE, "PtpCrbTpmCommand ReceiveHeader - ")); + for (Index = 0; Index < sizeof (TPM2_RESPONSE_HEADER); Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferOut[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index])); + } +- DEBUG ((EFI_D_VERBOSE, "\n")); ++ DEBUG ((DEBUG_VERBOSE, "\n")); + ); + // + // Check the response data header (tag, parasize and returncode) +@@ -298,7 +298,7 @@ PtpCrbTpmCommand ( + CopyMem (&Data16, BufferOut, sizeof (UINT16)); + // TPM2 should not use this RSP_COMMAND + if (SwapBytes16 (Data16) == TPM_ST_RSP_COMMAND) { +- DEBUG ((EFI_D_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND)); ++ DEBUG ((DEBUG_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND)); + Status = EFI_UNSUPPORTED; + goto GoIdle_Exit; + } +@@ -321,11 +321,11 @@ PtpCrbTpmCommand ( + } + + DEBUG_CODE ( +- DEBUG ((EFI_D_VERBOSE, "PtpCrbTpmCommand Receive - ")); ++ DEBUG ((DEBUG_VERBOSE, "PtpCrbTpmCommand Receive - ")); + for (Index = 0; Index < TpmOutSize; Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferOut[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index])); + } +- DEBUG ((EFI_D_VERBOSE, "\n")); ++ DEBUG ((DEBUG_VERBOSE, "\n")); + ); + + GoReady_Exit: +@@ -494,36 +494,36 @@ DumpPtpInfo ( + // + // Dump InterfaceId Register for PTP + // +- DEBUG ((EFI_D_INFO, "InterfaceId - 0x%08x\n", InterfaceId.Uint32)); +- DEBUG ((EFI_D_INFO, " InterfaceType - 0x%02x\n", InterfaceId.Bits.InterfaceType)); ++ DEBUG ((DEBUG_INFO, "InterfaceId - 0x%08x\n", InterfaceId.Uint32)); ++ DEBUG ((DEBUG_INFO, " InterfaceType - 0x%02x\n", InterfaceId.Bits.InterfaceType)); + if (InterfaceId.Bits.InterfaceType != PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_TIS) { +- DEBUG ((EFI_D_INFO, " InterfaceVersion - 0x%02x\n", InterfaceId.Bits.InterfaceVersion)); +- DEBUG ((EFI_D_INFO, " CapFIFO - 0x%x\n", InterfaceId.Bits.CapFIFO)); +- DEBUG ((EFI_D_INFO, " CapCRB - 0x%x\n", InterfaceId.Bits.CapCRB)); ++ DEBUG ((DEBUG_INFO, " InterfaceVersion - 0x%02x\n", InterfaceId.Bits.InterfaceVersion)); ++ DEBUG ((DEBUG_INFO, " CapFIFO - 0x%x\n", InterfaceId.Bits.CapFIFO)); ++ DEBUG ((DEBUG_INFO, " CapCRB - 0x%x\n", InterfaceId.Bits.CapCRB)); + } + + // + // Dump Capability Register for TIS and FIFO + // +- DEBUG ((EFI_D_INFO, "InterfaceCapability - 0x%08x\n", InterfaceCapability.Uint32)); ++ DEBUG ((DEBUG_INFO, "InterfaceCapability - 0x%08x\n", InterfaceCapability.Uint32)); + if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_TIS) || + (InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO)) { +- DEBUG ((EFI_D_INFO, " InterfaceVersion - 0x%x\n", InterfaceCapability.Bits.InterfaceVersion)); ++ DEBUG ((DEBUG_INFO, " InterfaceVersion - 0x%x\n", InterfaceCapability.Bits.InterfaceVersion)); + } + + // + // Dump StatusEx Register for PTP FIFO + // +- DEBUG ((EFI_D_INFO, "StatusEx - 0x%02x\n", StatusEx)); ++ DEBUG ((DEBUG_INFO, "StatusEx - 0x%02x\n", StatusEx)); + if (InterfaceCapability.Bits.InterfaceVersion == INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP) { +- DEBUG ((EFI_D_INFO, " TpmFamily - 0x%x\n", (StatusEx & PTP_FIFO_STS_EX_TPM_FAMILY) >> PTP_FIFO_STS_EX_TPM_FAMILY_OFFSET)); ++ DEBUG ((DEBUG_INFO, " TpmFamily - 0x%x\n", (StatusEx & PTP_FIFO_STS_EX_TPM_FAMILY) >> PTP_FIFO_STS_EX_TPM_FAMILY_OFFSET)); + } + + Vid = 0xFFFF; + Did = 0xFFFF; + Rid = 0xFF; + PtpInterface = GetCachedPtpInterface (); +- DEBUG ((EFI_D_INFO, "PtpInterface - %x\n", PtpInterface)); ++ DEBUG ((DEBUG_INFO, "PtpInterface - %x\n", PtpInterface)); + switch (PtpInterface) { + case Tpm2PtpInterfaceCrb: + Vid = MmioRead16 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->Vid); +@@ -539,9 +539,9 @@ DumpPtpInfo ( + default: + break; + } +- DEBUG ((EFI_D_INFO, "VID - 0x%04x\n", Vid)); +- DEBUG ((EFI_D_INFO, "DID - 0x%04x\n", Did)); +- DEBUG ((EFI_D_INFO, "RID - 0x%02x\n", Rid)); ++ DEBUG ((DEBUG_INFO, "VID - 0x%04x\n", Vid)); ++ DEBUG ((DEBUG_INFO, "DID - 0x%04x\n", Did)); ++ DEBUG ((DEBUG_INFO, "RID - 0x%02x\n", Rid)); + } + + /** +diff --git a/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Tis.c b/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Tis.c +index 9a809612b3..e3bef8dfe4 100644 +--- a/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Tis.c ++++ b/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Tis.c +@@ -221,22 +221,22 @@ Tpm2TisTpmCommand ( + DEBUG_CODE ( + UINTN DebugSize; + +- DEBUG ((EFI_D_VERBOSE, "Tpm2TisTpmCommand Send - ")); ++ DEBUG ((DEBUG_VERBOSE, "Tpm2TisTpmCommand Send - ")); + if (SizeIn > 0x100) { + DebugSize = 0x40; + } else { + DebugSize = SizeIn; + } + for (Index = 0; Index < DebugSize; Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferIn[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index])); + } + if (DebugSize != SizeIn) { +- DEBUG ((EFI_D_VERBOSE, "...... ")); ++ DEBUG ((DEBUG_VERBOSE, "...... ")); + for (Index = SizeIn - 0x20; Index < SizeIn; Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferIn[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index])); + } + } +- DEBUG ((EFI_D_VERBOSE, "\n")); ++ DEBUG ((DEBUG_VERBOSE, "\n")); + ); + TpmOutSize = 0; + +@@ -333,11 +333,11 @@ Tpm2TisTpmCommand ( + } + } + DEBUG_CODE ( +- DEBUG ((EFI_D_VERBOSE, "Tpm2TisTpmCommand ReceiveHeader - ")); ++ DEBUG ((DEBUG_VERBOSE, "Tpm2TisTpmCommand ReceiveHeader - ")); + for (Index = 0; Index < sizeof (TPM2_RESPONSE_HEADER); Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferOut[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index])); + } +- DEBUG ((EFI_D_VERBOSE, "\n")); ++ DEBUG ((DEBUG_VERBOSE, "\n")); + ); + // + // Check the response data header (tag,parasize and returncode ) +@@ -345,7 +345,7 @@ Tpm2TisTpmCommand ( + CopyMem (&Data16, BufferOut, sizeof (UINT16)); + // TPM2 should not use this RSP_COMMAND + if (SwapBytes16 (Data16) == TPM_ST_RSP_COMMAND) { +- DEBUG ((EFI_D_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND)); ++ DEBUG ((DEBUG_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND)); + Status = EFI_UNSUPPORTED; + goto Exit; + } +@@ -377,11 +377,11 @@ Tpm2TisTpmCommand ( + } + Exit: + DEBUG_CODE ( +- DEBUG ((EFI_D_VERBOSE, "Tpm2TisTpmCommand Receive - ")); ++ DEBUG ((DEBUG_VERBOSE, "Tpm2TisTpmCommand Receive - ")); + for (Index = 0; Index < TpmOutSize; Index++) { +- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferOut[Index])); ++ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index])); + } +- DEBUG ((EFI_D_VERBOSE, "\n")); ++ DEBUG ((DEBUG_VERBOSE, "\n")); + ); + MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY); + return Status; +diff --git a/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.c b/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.c +index 2e77d35433..e24ef08515 100644 +--- a/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.c ++++ b/SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.c +@@ -123,7 +123,7 @@ Tpm2RegisterTpm2DeviceLib ( + // + // In PEI phase, there will be shadow driver dispatched again. + // +- DEBUG ((EFI_D_INFO, "Tpm2RegisterTpm2DeviceLib - Override\n")); ++ DEBUG ((DEBUG_INFO, "Tpm2RegisterTpm2DeviceLib - Override\n")); + CopyMem (Tpm2DeviceInterface, Tpm2Device, sizeof(*Tpm2Device)); + return EFI_SUCCESS; + } else { +diff --git a/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.c b/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.c +index c34c417093..9d12695a62 100644 +--- a/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.c ++++ b/SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.c +@@ -46,7 +46,7 @@ Tpm2SubmitCommand ( + // + // Tcg2 protocol is not installed. So, TPM2 is not present. + // +- DEBUG ((EFI_D_ERROR, "Tpm2SubmitCommand - Tcg2 - %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "Tpm2SubmitCommand - Tcg2 - %r\n", Status)); + return EFI_NOT_FOUND; + } + } +@@ -90,7 +90,7 @@ Tpm2RequestUseTpm ( + // + // Tcg2 protocol is not installed. So, TPM2 is not present. + // +- DEBUG ((EFI_D_ERROR, "Tpm2RequestUseTpm - Tcg2 - %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "Tpm2RequestUseTpm - Tcg2 - %r\n", Status)); + return EFI_NOT_FOUND; + } + } +diff --git a/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c b/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c +index 32b64a31d1..e5dd06ebcf 100644 +--- a/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c ++++ b/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c +@@ -40,7 +40,7 @@ OnReadyToBoot ( + // + // Clear MOR_CLEAR_MEMORY_BIT + // +- DEBUG ((EFI_D_INFO, "TcgMor: Clear MorClearMemory bit\n")); ++ DEBUG ((DEBUG_INFO, "TcgMor: Clear MorClearMemory bit\n")); + mMorControl &= 0xFE; + + DataSize = sizeof (mMorControl); +@@ -168,7 +168,7 @@ InitiateTPerReset ( + // Found a TCG device. + // + TcgFlag = TRUE; +- DEBUG ((EFI_D_INFO, "This device is a TCG protocol device\n")); ++ DEBUG ((DEBUG_INFO, "This device is a TCG protocol device\n")); + break; + } + +@@ -177,13 +177,13 @@ InitiateTPerReset ( + // Found a IEEE 1667 device. + // + IeeeFlag = TRUE; +- DEBUG ((EFI_D_INFO, "This device is a IEEE 1667 protocol device\n")); ++ DEBUG ((DEBUG_INFO, "This device is a IEEE 1667 protocol device\n")); + break; + } + } + + if (!TcgFlag && !IeeeFlag) { +- DEBUG ((EFI_D_INFO, "Neither a TCG nor IEEE 1667 protocol device is found\n")); ++ DEBUG ((DEBUG_INFO, "Neither a TCG nor IEEE 1667 protocol device is found\n")); + goto Exit; + } + +@@ -203,9 +203,9 @@ InitiateTPerReset ( + ); + + if (!EFI_ERROR (Status)) { +- DEBUG ((EFI_D_INFO, "Send TPer Reset Command Successfully !\n")); ++ DEBUG ((DEBUG_INFO, "Send TPer Reset Command Successfully !\n")); + } else { +- DEBUG ((EFI_D_INFO, "Send TPer Reset Command Fail !\n")); ++ DEBUG ((DEBUG_INFO, "Send TPer Reset Command Fail !\n")); + } + } + +@@ -213,7 +213,7 @@ InitiateTPerReset ( + // + // TBD : Perform a TPer Reset via IEEE 1667 Protocol + // +- DEBUG ((EFI_D_INFO, "IEEE 1667 Protocol didn't support yet!\n")); ++ DEBUG ((DEBUG_INFO, "IEEE 1667 Protocol didn't support yet!\n")); + } + + Exit: +@@ -336,7 +336,7 @@ MorDriverEntryPoint ( + DataSize, + &mMorControl + ); +- DEBUG ((EFI_D_INFO, "TcgMor: Create MOR variable! Status = %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "TcgMor: Create MOR variable! Status = %r\n", Status)); + } else { + // + // Create a Ready To Boot Event and Clear the MorControl bit in the call back function. +@@ -355,7 +355,7 @@ MorDriverEntryPoint ( + // + // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event. + // +- DEBUG ((EFI_D_INFO, "TcgMor: Create EndofDxe Event for Mor TPer Reset!\n")); ++ DEBUG ((DEBUG_INFO, "TcgMor: Create EndofDxe Event for Mor TPer Reset!\n")); + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, +@@ -371,5 +371,3 @@ MorDriverEntryPoint ( + + return Status; + } +- +- +diff --git a/SecurityPkg/Tcg/MemoryOverwriteRequestControlLock/TcgMorLockSmm.c b/SecurityPkg/Tcg/MemoryOverwriteRequestControlLock/TcgMorLockSmm.c +index 8c92317313..8e775cb96c 100644 +--- a/SecurityPkg/Tcg/MemoryOverwriteRequestControlLock/TcgMorLockSmm.c ++++ b/SecurityPkg/Tcg/MemoryOverwriteRequestControlLock/TcgMorLockSmm.c +@@ -123,7 +123,7 @@ MorLockDriverEntryPointSmm ( + // + // This driver link to Smm Variable driver + // +- DEBUG ((EFI_D_INFO, "MorLockDriverEntryPointSmm\n")); ++ DEBUG ((DEBUG_INFO, "MorLockDriverEntryPointSmm\n")); + + Status = gSmst->SmmLocateProtocol ( + &gEfiSmmVariableProtocolGuid, +@@ -149,4 +149,3 @@ MorLockDriverEntryPointSmm ( + + return Status; + } +- +diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDriver.c b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDriver.c +index 10d1c5cc78..fca5ae2645 100644 +--- a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDriver.c ++++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDriver.c +@@ -355,7 +355,7 @@ Tcg2ConfigDriverEntryPoint ( + &Tcg2DeviceDetection + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_DEVICE_DETECTION_NAME\n")); ++ DEBUG ((DEBUG_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_DEVICE_DETECTION_NAME\n")); + Status = gRT->SetVariable ( + TCG2_DEVICE_DETECTION_NAME, + &gTcg2ConfigFormSetGuid, +@@ -377,7 +377,7 @@ Tcg2ConfigDriverEntryPoint ( + &Tcg2Configuration + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_STORAGE_NAME\n")); ++ DEBUG ((DEBUG_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_STORAGE_NAME\n")); + } + + // +diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c +index 2946f95db0..a7446ef2f6 100644 +--- a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c ++++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c +@@ -960,7 +960,7 @@ InstallTcg2ConfigForm ( + &Tcg2ConfigInfo + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_STORAGE_INFO_NAME\n")); ++ DEBUG ((DEBUG_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_STORAGE_INFO_NAME\n")); + } + + return EFI_SUCCESS; +diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c +index 0f9bad724e..8abc33efd4 100644 +--- a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c ++++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c +@@ -104,11 +104,11 @@ Tcg2ConfigPeimEntryPoint ( + // + // Although we have SetupVariable info, we still need detect TPM device manually. + // +- DEBUG ((EFI_D_INFO, "Tcg2Configuration.TpmDevice from Setup: %x\n", Tcg2Configuration.TpmDevice)); ++ DEBUG ((DEBUG_INFO, "Tcg2Configuration.TpmDevice from Setup: %x\n", Tcg2Configuration.TpmDevice)); + + if (PcdGetBool (PcdTpmAutoDetection)) { + TpmDevice = DetectTpmDevice (Tcg2Configuration.TpmDevice); +- DEBUG ((EFI_D_INFO, "TpmDevice final: %x\n", TpmDevice)); ++ DEBUG ((DEBUG_INFO, "TpmDevice final: %x\n", TpmDevice)); + if (TpmDevice != TPM_DEVICE_NULL) { + Tcg2Configuration.TpmDevice = TpmDevice; + } +@@ -129,7 +129,7 @@ Tcg2ConfigPeimEntryPoint ( + Size = sizeof(mTpmInstanceId[Index].TpmInstanceGuid); + Status = PcdSetPtrS (PcdTpmInstanceGuid, &Size, &mTpmInstanceId[Index].TpmInstanceGuid); + ASSERT_EFI_ERROR (Status); +- DEBUG ((EFI_D_INFO, "TpmDevice PCD: %g\n", &mTpmInstanceId[Index].TpmInstanceGuid)); ++ DEBUG ((DEBUG_INFO, "TpmDevice PCD: %g\n", &mTpmInstanceId[Index].TpmInstanceGuid)); + break; + } + } +diff --git a/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c b/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c +index eeaadc5e2f..57d3638f0c 100644 +--- a/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c ++++ b/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c +@@ -47,7 +47,7 @@ DetectTpmDevice ( + // In S3, we rely on normal boot Detection, because we save to ReadOnly Variable in normal boot. + // + if (BootMode == BOOT_ON_S3_RESUME) { +- DEBUG ((EFI_D_INFO, "DetectTpmDevice: S3 mode\n")); ++ DEBUG ((DEBUG_INFO, "DetectTpmDevice: S3 mode\n")); + + Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariablePpi); + ASSERT_EFI_ERROR (Status); +@@ -65,12 +65,12 @@ DetectTpmDevice ( + if (!EFI_ERROR (Status) && + (Tcg2DeviceDetection.TpmDeviceDetected >= TPM_DEVICE_MIN) && + (Tcg2DeviceDetection.TpmDeviceDetected <= TPM_DEVICE_MAX)) { +- DEBUG ((EFI_D_ERROR, "TpmDevice from DeviceDetection: %x\n", Tcg2DeviceDetection.TpmDeviceDetected)); ++ DEBUG ((DEBUG_ERROR, "TpmDevice from DeviceDetection: %x\n", Tcg2DeviceDetection.TpmDeviceDetected)); + return Tcg2DeviceDetection.TpmDeviceDetected; + } + } + +- DEBUG ((EFI_D_INFO, "DetectTpmDevice:\n")); ++ DEBUG ((DEBUG_INFO, "DetectTpmDevice:\n")); + + // dTPM available and not disabled by setup + // We need check if it is TPM1.2 or TPM2.0 +diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c +index f1a97d4b2d..c26be18338 100644 +--- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c ++++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c +@@ -159,7 +159,7 @@ InternalDumpData ( + { + UINTN Index; + for (Index = 0; Index < Size; Index++) { +- DEBUG ((EFI_D_INFO, "%02x", (UINTN)Data[Index])); ++ DEBUG ((DEBUG_INFO, "%02x", (UINTN)Data[Index])); + } + } + +@@ -262,15 +262,15 @@ InternalDumpHex ( + Count = Size / COLUME_SIZE; + Left = Size % COLUME_SIZE; + for (Index = 0; Index < Count; Index++) { +- DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE)); ++ DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE)); + InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE); +- DEBUG ((EFI_D_INFO, "\n")); ++ DEBUG ((DEBUG_INFO, "\n")); + } + + if (Left != 0) { +- DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE)); ++ DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE)); + InternalDumpData (Data + Index * COLUME_SIZE, Left); +- DEBUG ((EFI_D_INFO, "\n")); ++ DEBUG ((DEBUG_INFO, "\n")); + } + } + +@@ -403,7 +403,7 @@ Tcg2GetCapability ( + ProtocolCapability->StructureVersion.Minor = 0; + ProtocolCapability->ProtocolVersion.Major = 1; + ProtocolCapability->ProtocolVersion.Minor = 0; +- DEBUG ((EFI_D_ERROR, "TreeGetCapability (Compatible) - %r\n", EFI_SUCCESS)); ++ DEBUG ((DEBUG_ERROR, "TreeGetCapability (Compatible) - %r\n", EFI_SUCCESS)); + return EFI_SUCCESS; + } + } +@@ -428,15 +428,15 @@ DumpEvent ( + { + UINTN Index; + +- DEBUG ((EFI_D_INFO, " Event:\n")); +- DEBUG ((EFI_D_INFO, " PCRIndex - %d\n", EventHdr->PCRIndex)); +- DEBUG ((EFI_D_INFO, " EventType - 0x%08x\n", EventHdr->EventType)); +- DEBUG ((EFI_D_INFO, " Digest - ")); ++ DEBUG ((DEBUG_INFO, " Event:\n")); ++ DEBUG ((DEBUG_INFO, " PCRIndex - %d\n", EventHdr->PCRIndex)); ++ DEBUG ((DEBUG_INFO, " EventType - 0x%08x\n", EventHdr->EventType)); ++ DEBUG ((DEBUG_INFO, " Digest - ")); + for (Index = 0; Index < sizeof(TCG_DIGEST); Index++) { +- DEBUG ((EFI_D_INFO, "%02x ", EventHdr->Digest.digest[Index])); ++ DEBUG ((DEBUG_INFO, "%02x ", EventHdr->Digest.digest[Index])); + } +- DEBUG ((EFI_D_INFO, "\n")); +- DEBUG ((EFI_D_INFO, " EventSize - 0x%08x\n", EventHdr->EventSize)); ++ DEBUG ((DEBUG_INFO, "\n")); ++ DEBUG ((DEBUG_INFO, " EventSize - 0x%08x\n", EventHdr->EventSize)); + InternalDumpHex ((UINT8 *)(EventHdr + 1), EventHdr->EventSize); + } + +@@ -456,33 +456,33 @@ DumpTcgEfiSpecIdEventStruct ( + UINT8 *VendorInfo; + UINT32 NumberOfAlgorithms; + +- DEBUG ((EFI_D_INFO, " TCG_EfiSpecIDEventStruct:\n")); +- DEBUG ((EFI_D_INFO, " signature - '")); ++ DEBUG ((DEBUG_INFO, " TCG_EfiSpecIDEventStruct:\n")); ++ DEBUG ((DEBUG_INFO, " signature - '")); + for (Index = 0; Index < sizeof(TcgEfiSpecIdEventStruct->signature); Index++) { +- DEBUG ((EFI_D_INFO, "%c", TcgEfiSpecIdEventStruct->signature[Index])); ++ DEBUG ((DEBUG_INFO, "%c", TcgEfiSpecIdEventStruct->signature[Index])); + } +- DEBUG ((EFI_D_INFO, "'\n")); +- DEBUG ((EFI_D_INFO, " platformClass - 0x%08x\n", TcgEfiSpecIdEventStruct->platformClass)); +- DEBUG ((EFI_D_INFO, " specVersion - %d.%d%d\n", TcgEfiSpecIdEventStruct->specVersionMajor, TcgEfiSpecIdEventStruct->specVersionMinor, TcgEfiSpecIdEventStruct->specErrata)); +- DEBUG ((EFI_D_INFO, " uintnSize - 0x%02x\n", TcgEfiSpecIdEventStruct->uintnSize)); ++ DEBUG ((DEBUG_INFO, "'\n")); ++ DEBUG ((DEBUG_INFO, " platformClass - 0x%08x\n", TcgEfiSpecIdEventStruct->platformClass)); ++ DEBUG ((DEBUG_INFO, " specVersion - %d.%d%d\n", TcgEfiSpecIdEventStruct->specVersionMajor, TcgEfiSpecIdEventStruct->specVersionMinor, TcgEfiSpecIdEventStruct->specErrata)); ++ DEBUG ((DEBUG_INFO, " uintnSize - 0x%02x\n", TcgEfiSpecIdEventStruct->uintnSize)); + + CopyMem (&NumberOfAlgorithms, TcgEfiSpecIdEventStruct + 1, sizeof(NumberOfAlgorithms)); +- DEBUG ((EFI_D_INFO, " NumberOfAlgorithms - 0x%08x\n", NumberOfAlgorithms)); ++ DEBUG ((DEBUG_INFO, " NumberOfAlgorithms - 0x%08x\n", NumberOfAlgorithms)); + + DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof(*TcgEfiSpecIdEventStruct) + sizeof(NumberOfAlgorithms)); + for (Index = 0; Index < NumberOfAlgorithms; Index++) { +- DEBUG ((EFI_D_INFO, " digest(%d)\n", Index)); +- DEBUG ((EFI_D_INFO, " algorithmId - 0x%04x\n", DigestSize[Index].algorithmId)); +- DEBUG ((EFI_D_INFO, " digestSize - 0x%04x\n", DigestSize[Index].digestSize)); ++ DEBUG ((DEBUG_INFO, " digest(%d)\n", Index)); ++ DEBUG ((DEBUG_INFO, " algorithmId - 0x%04x\n", DigestSize[Index].algorithmId)); ++ DEBUG ((DEBUG_INFO, " digestSize - 0x%04x\n", DigestSize[Index].digestSize)); + } + VendorInfoSize = (UINT8 *)&DigestSize[NumberOfAlgorithms]; +- DEBUG ((EFI_D_INFO, " VendorInfoSize - 0x%02x\n", *VendorInfoSize)); ++ DEBUG ((DEBUG_INFO, " VendorInfoSize - 0x%02x\n", *VendorInfoSize)); + VendorInfo = VendorInfoSize + 1; +- DEBUG ((EFI_D_INFO, " VendorInfo - ")); ++ DEBUG ((DEBUG_INFO, " VendorInfo - ")); + for (Index = 0; Index < *VendorInfoSize; Index++) { +- DEBUG ((EFI_D_INFO, "%02x ", VendorInfo[Index])); ++ DEBUG ((DEBUG_INFO, "%02x ", VendorInfo[Index])); + } +- DEBUG ((EFI_D_INFO, "\n")); ++ DEBUG ((DEBUG_INFO, "\n")); + } + + /** +@@ -525,34 +525,34 @@ DumpEvent2 ( + UINT32 EventSize; + UINT8 *EventBuffer; + +- DEBUG ((EFI_D_INFO, " Event:\n")); +- DEBUG ((EFI_D_INFO, " PCRIndex - %d\n", TcgPcrEvent2->PCRIndex)); +- DEBUG ((EFI_D_INFO, " EventType - 0x%08x\n", TcgPcrEvent2->EventType)); ++ DEBUG ((DEBUG_INFO, " Event:\n")); ++ DEBUG ((DEBUG_INFO, " PCRIndex - %d\n", TcgPcrEvent2->PCRIndex)); ++ DEBUG ((DEBUG_INFO, " EventType - 0x%08x\n", TcgPcrEvent2->EventType)); + +- DEBUG ((EFI_D_INFO, " DigestCount: 0x%08x\n", TcgPcrEvent2->Digest.count)); ++ DEBUG ((DEBUG_INFO, " DigestCount: 0x%08x\n", TcgPcrEvent2->Digest.count)); + + DigestCount = TcgPcrEvent2->Digest.count; + HashAlgo = TcgPcrEvent2->Digest.digests[0].hashAlg; + DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest.digests[0].digest; + for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) { +- DEBUG ((EFI_D_INFO, " HashAlgo : 0x%04x\n", HashAlgo)); +- DEBUG ((EFI_D_INFO, " Digest(%d): ", DigestIndex)); ++ DEBUG ((DEBUG_INFO, " HashAlgo : 0x%04x\n", HashAlgo)); ++ DEBUG ((DEBUG_INFO, " Digest(%d): ", DigestIndex)); + DigestSize = GetHashSizeFromAlgo (HashAlgo); + for (Index = 0; Index < DigestSize; Index++) { +- DEBUG ((EFI_D_INFO, "%02x ", DigestBuffer[Index])); ++ DEBUG ((DEBUG_INFO, "%02x ", DigestBuffer[Index])); + } +- DEBUG ((EFI_D_INFO, "\n")); ++ DEBUG ((DEBUG_INFO, "\n")); + // + // Prepare next + // + CopyMem (&HashAlgo, DigestBuffer + DigestSize, sizeof(TPMI_ALG_HASH)); + DigestBuffer = DigestBuffer + DigestSize + sizeof(TPMI_ALG_HASH); + } +- DEBUG ((EFI_D_INFO, "\n")); ++ DEBUG ((DEBUG_INFO, "\n")); + DigestBuffer = DigestBuffer - sizeof(TPMI_ALG_HASH); + + CopyMem (&EventSize, DigestBuffer, sizeof(TcgPcrEvent2->EventSize)); +- DEBUG ((EFI_D_INFO, " EventSize - 0x%08x\n", EventSize)); ++ DEBUG ((DEBUG_INFO, " EventSize - 0x%08x\n", EventSize)); + EventBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize); + InternalDumpHex (EventBuffer, EventSize); + } +@@ -618,7 +618,7 @@ DumpEventLog ( + TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct; + UINTN NumberOfEvents; + +- DEBUG ((EFI_D_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat)); ++ DEBUG ((DEBUG_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat)); + + switch (EventLogFormat) { + case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2: +@@ -628,11 +628,11 @@ DumpEventLog ( + EventHdr = (TCG_PCR_EVENT_HDR *)((UINTN)EventHdr + sizeof(TCG_PCR_EVENT_HDR) + EventHdr->EventSize); + } + if (FinalEventsTable == NULL) { +- DEBUG ((EFI_D_INFO, "FinalEventsTable: NOT FOUND\n")); ++ DEBUG ((DEBUG_INFO, "FinalEventsTable: NOT FOUND\n")); + } else { +- DEBUG ((EFI_D_INFO, "FinalEventsTable: (0x%x)\n", FinalEventsTable)); +- DEBUG ((EFI_D_INFO, " Version: (0x%x)\n", FinalEventsTable->Version)); +- DEBUG ((EFI_D_INFO, " NumberOfEvents: (0x%x)\n", FinalEventsTable->NumberOfEvents)); ++ DEBUG ((DEBUG_INFO, "FinalEventsTable: (0x%x)\n", FinalEventsTable)); ++ DEBUG ((DEBUG_INFO, " Version: (0x%x)\n", FinalEventsTable->Version)); ++ DEBUG ((DEBUG_INFO, " NumberOfEvents: (0x%x)\n", FinalEventsTable->NumberOfEvents)); + + EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)(FinalEventsTable + 1); + for (NumberOfEvents = 0; NumberOfEvents < FinalEventsTable->NumberOfEvents; NumberOfEvents++) { +@@ -658,11 +658,11 @@ DumpEventLog ( + } + + if (FinalEventsTable == NULL) { +- DEBUG ((EFI_D_INFO, "FinalEventsTable: NOT FOUND\n")); ++ DEBUG ((DEBUG_INFO, "FinalEventsTable: NOT FOUND\n")); + } else { +- DEBUG ((EFI_D_INFO, "FinalEventsTable: (0x%x)\n", FinalEventsTable)); +- DEBUG ((EFI_D_INFO, " Version: (0x%x)\n", FinalEventsTable->Version)); +- DEBUG ((EFI_D_INFO, " NumberOfEvents: (0x%x)\n", FinalEventsTable->NumberOfEvents)); ++ DEBUG ((DEBUG_INFO, "FinalEventsTable: (0x%x)\n", FinalEventsTable)); ++ DEBUG ((DEBUG_INFO, " Version: (0x%x)\n", FinalEventsTable->Version)); ++ DEBUG ((DEBUG_INFO, " NumberOfEvents: (0x%x)\n", FinalEventsTable->NumberOfEvents)); + + TcgPcrEvent2 = (TCG_PCR_EVENT2 *)(UINTN)(FinalEventsTable + 1); + for (NumberOfEvents = 0; NumberOfEvents < FinalEventsTable->NumberOfEvents; NumberOfEvents++) { +@@ -705,7 +705,7 @@ Tcg2GetEventLog ( + { + UINTN Index; + +- DEBUG ((EFI_D_INFO, "Tcg2GetEventLog ... (0x%x)\n", EventLogFormat)); ++ DEBUG ((DEBUG_INFO, "Tcg2GetEventLog ... (0x%x)\n", EventLogFormat)); + + if (This == NULL) { + return EFI_INVALID_PARAMETER; +@@ -740,7 +740,7 @@ Tcg2GetEventLog ( + + if (EventLogLocation != NULL) { + *EventLogLocation = mTcgDxeData.EventLogAreaStruct[Index].Lasa; +- DEBUG ((EFI_D_INFO, "Tcg2GetEventLog (EventLogLocation - %x)\n", *EventLogLocation)); ++ DEBUG ((DEBUG_INFO, "Tcg2GetEventLog (EventLogLocation - %x)\n", *EventLogLocation)); + } + + if (EventLogLastEntry != NULL) { +@@ -749,15 +749,15 @@ Tcg2GetEventLog ( + } else { + *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)mTcgDxeData.EventLogAreaStruct[Index].LastEvent; + } +- DEBUG ((EFI_D_INFO, "Tcg2GetEventLog (EventLogLastEntry - %x)\n", *EventLogLastEntry)); ++ DEBUG ((DEBUG_INFO, "Tcg2GetEventLog (EventLogLastEntry - %x)\n", *EventLogLastEntry)); + } + + if (EventLogTruncated != NULL) { + *EventLogTruncated = mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated; +- DEBUG ((EFI_D_INFO, "Tcg2GetEventLog (EventLogTruncated - %x)\n", *EventLogTruncated)); ++ DEBUG ((DEBUG_INFO, "Tcg2GetEventLog (EventLogTruncated - %x)\n", *EventLogTruncated)); + } + +- DEBUG ((EFI_D_INFO, "Tcg2GetEventLog - %r\n", EFI_SUCCESS)); ++ DEBUG ((DEBUG_INFO, "Tcg2GetEventLog - %r\n", EFI_SUCCESS)); + + // Dump Event Log for debug purpose + if ((EventLogLocation != NULL) && (EventLogLastEntry != NULL)) { +@@ -980,8 +980,8 @@ TcgDxeLogEvent ( + // Increase the NumberOfEvents in FinalEventsTable + // + (mTcgDxeData.FinalEventsTable[Index])->NumberOfEvents ++; +- DEBUG ((EFI_D_INFO, "FinalEventsTable->NumberOfEvents - 0x%x\n", (mTcgDxeData.FinalEventsTable[Index])->NumberOfEvents)); +- DEBUG ((EFI_D_INFO, " Size - 0x%x\n", (UINTN)EventLogAreaStruct->EventLogSize)); ++ DEBUG ((DEBUG_INFO, "FinalEventsTable->NumberOfEvents - 0x%x\n", (mTcgDxeData.FinalEventsTable[Index])->NumberOfEvents)); ++ DEBUG ((DEBUG_INFO, " Size - 0x%x\n", (UINTN)EventLogAreaStruct->EventLogSize)); + } + } + +@@ -1101,12 +1101,12 @@ TcgDxeLogHashEvent ( + UINT8 *DigestBuffer; + UINT32 *EventSizePtr; + +- DEBUG ((EFI_D_INFO, "SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs)); ++ DEBUG ((DEBUG_INFO, "SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs)); + + RetStatus = EFI_SUCCESS; + for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { + if ((mTcgDxeData.BsCap.SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) { +- DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat)); ++ DEBUG ((DEBUG_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat)); + switch (mTcg2EventInfo[Index].LogFormat) { + case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2: + Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest); +@@ -1224,7 +1224,7 @@ TcgDxeHashLogExtendEvent ( + } + + if (Status == EFI_DEVICE_ERROR) { +- DEBUG ((EFI_D_ERROR, "TcgDxeHashLogExtendEvent - %r. Disable TPM.\n", Status)); ++ DEBUG ((DEBUG_ERROR, "TcgDxeHashLogExtendEvent - %r. Disable TPM.\n", Status)); + mTcgDxeData.BsCap.TPMPresentFlag = FALSE; + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, +@@ -1308,7 +1308,7 @@ Tcg2HashLogExtendEvent ( + } + } + if (Status == EFI_DEVICE_ERROR) { +- DEBUG ((EFI_D_ERROR, "MeasurePeImageAndExtend - %r. Disable TPM.\n", Status)); ++ DEBUG ((DEBUG_ERROR, "MeasurePeImageAndExtend - %r. Disable TPM.\n", Status)); + mTcgDxeData.BsCap.TPMPresentFlag = FALSE; + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, +@@ -1354,7 +1354,7 @@ Tcg2SubmitCommand ( + { + EFI_STATUS Status; + +- DEBUG ((EFI_D_INFO, "Tcg2SubmitCommand ...\n")); ++ DEBUG ((DEBUG_INFO, "Tcg2SubmitCommand ...\n")); + + if ((This == NULL) || + (InputParameterBlockSize == 0) || (InputParameterBlock == NULL) || +@@ -1379,7 +1379,7 @@ Tcg2SubmitCommand ( + &OutputParameterBlockSize, + OutputParameterBlock + ); +- DEBUG ((EFI_D_INFO, "Tcg2SubmitCommand - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "Tcg2SubmitCommand - %r\n", Status)); + return Status; + } + +@@ -1425,7 +1425,7 @@ Tcg2SetActivePCRBanks ( + EFI_STATUS Status; + UINT32 ReturnCode; + +- DEBUG ((EFI_D_INFO, "Tcg2SetActivePCRBanks ... (0x%x)\n", ActivePcrBanks)); ++ DEBUG ((DEBUG_INFO, "Tcg2SetActivePCRBanks ... (0x%x)\n", ActivePcrBanks)); + + if (ActivePcrBanks == 0) { + return EFI_INVALID_PARAMETER; +@@ -1452,7 +1452,7 @@ Tcg2SetActivePCRBanks ( + Status = EFI_DEVICE_ERROR; + } + +- DEBUG ((EFI_D_INFO, "Tcg2SetActivePCRBanks - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "Tcg2SetActivePCRBanks - %r\n", Status)); + + return Status; + } +@@ -1533,7 +1533,7 @@ SetupEventLog ( + UINT32 NumberOfAlgorithms; + TCG_EfiStartupLocalityEvent StartupLocalityEvent; + +- DEBUG ((EFI_D_INFO, "SetupEventLog\n")); ++ DEBUG ((DEBUG_INFO, "SetupEventLog\n")); + + // + // 1. Create Log Area +@@ -1940,7 +1940,7 @@ MeasureSeparatorEvent ( + TCG_PCR_EVENT_HDR TcgEvent; + UINT32 EventData; + +- DEBUG ((EFI_D_INFO, "MeasureSeparatorEvent Pcr - %x\n", PCRIndex)); ++ DEBUG ((DEBUG_INFO, "MeasureSeparatorEvent Pcr - %x\n", PCRIndex)); + + EventData = 0; + TcgEvent.PCRIndex = PCRIndex; +@@ -1985,8 +1985,8 @@ MeasureVariable ( + UINTN VarNameLength; + UEFI_VARIABLE_DATA *VarLog; + +- DEBUG ((EFI_D_INFO, "Tcg2Dxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)PCRIndex, (UINTN)EventType)); +- DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid)); ++ DEBUG ((DEBUG_INFO, "Tcg2Dxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)PCRIndex, (UINTN)EventType)); ++ DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid)); + + VarNameLength = StrLen (VarName); + TcgEvent.PCRIndex = PCRIndex; +@@ -2336,11 +2336,11 @@ MeasureSecureBootPolicy ( + + if (PcdGetBool (PcdFirmwareDebuggerInitialized)) { + Status = MeasureLaunchOfFirmwareDebugger (); +- DEBUG ((EFI_D_INFO, "MeasureLaunchOfFirmwareDebugger - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "MeasureLaunchOfFirmwareDebugger - %r\n", Status)); + } + + Status = MeasureAllSecureVariables (); +- DEBUG ((EFI_D_INFO, "MeasureAllSecureVariables - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "MeasureAllSecureVariables - %r\n", Status)); + + // + // We need measure Separator(7) here, because this event must be between SecureBootPolicy (Configure) +@@ -2349,7 +2349,7 @@ MeasureSecureBootPolicy ( + // the Authority measurement happen before ReadToBoot event. + // + Status = MeasureSeparatorEvent (7); +- DEBUG ((EFI_D_INFO, "MeasureSeparatorEvent - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "MeasureSeparatorEvent - %r\n", Status)); + return ; + } + +@@ -2380,7 +2380,7 @@ OnReadyToBoot ( + // + Status = MeasureHandoffTables (); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "HOBs not Measured. Error!\n")); ++ DEBUG ((DEBUG_ERROR, "HOBs not Measured. Error!\n")); + } + + // +@@ -2388,7 +2388,7 @@ OnReadyToBoot ( + // + Status = MeasureAllBootVariables (); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Boot Variables not Measured. Error!\n")); ++ DEBUG ((DEBUG_ERROR, "Boot Variables not Measured. Error!\n")); + } + + // +@@ -2399,7 +2399,7 @@ OnReadyToBoot ( + EFI_CALLING_EFI_APPLICATION + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION)); ++ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION)); + } + + // +@@ -2433,7 +2433,7 @@ OnReadyToBoot ( + EFI_RETURNING_FROM_EFI_APPLICATION + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATION)); ++ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATION)); + } + + // +@@ -2445,11 +2445,11 @@ OnReadyToBoot ( + EFI_CALLING_EFI_APPLICATION + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION)); ++ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION)); + } + } + +- DEBUG ((EFI_D_INFO, "TPM2 Tcg2Dxe Measure Data when ReadyToBoot\n")); ++ DEBUG ((DEBUG_INFO, "TPM2 Tcg2Dxe Measure Data when ReadyToBoot\n")); + // + // Increase boot attempt counter. + // +@@ -2483,7 +2483,7 @@ OnExitBootServices ( + EFI_EXIT_BOOT_SERVICES_INVOCATION + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION)); ++ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION)); + } + + // +@@ -2494,7 +2494,7 @@ OnExitBootServices ( + EFI_EXIT_BOOT_SERVICES_SUCCEEDED + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED)); ++ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED)); + } + } + +@@ -2524,7 +2524,7 @@ OnExitBootServicesFailed ( + EFI_EXIT_BOOT_SERVICES_FAILED + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED)); ++ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED)); + } + + } +@@ -2663,13 +2663,13 @@ DriverEntry ( + } + + if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { +- DEBUG ((EFI_D_ERROR, "TPM2 error!\n")); ++ DEBUG ((DEBUG_ERROR, "TPM2 error!\n")); + return EFI_DEVICE_ERROR; + } + + Status = Tpm2RequestUseTpm (); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "TPM2 not detected!\n")); ++ DEBUG ((DEBUG_ERROR, "TPM2 not detected!\n")); + return Status; + } + +@@ -2684,14 +2684,14 @@ DriverEntry ( + mTcgDxeData.BsCap.StructureVersion.Major = 1; + mTcgDxeData.BsCap.StructureVersion.Minor = 1; + +- DEBUG ((EFI_D_INFO, "Tcg2.ProtocolVersion - %02x.%02x\n", mTcgDxeData.BsCap.ProtocolVersion.Major, mTcgDxeData.BsCap.ProtocolVersion.Minor)); +- DEBUG ((EFI_D_INFO, "Tcg2.StructureVersion - %02x.%02x\n", mTcgDxeData.BsCap.StructureVersion.Major, mTcgDxeData.BsCap.StructureVersion.Minor)); ++ DEBUG ((DEBUG_INFO, "Tcg2.ProtocolVersion - %02x.%02x\n", mTcgDxeData.BsCap.ProtocolVersion.Major, mTcgDxeData.BsCap.ProtocolVersion.Minor)); ++ DEBUG ((DEBUG_INFO, "Tcg2.StructureVersion - %02x.%02x\n", mTcgDxeData.BsCap.StructureVersion.Major, mTcgDxeData.BsCap.StructureVersion.Minor)); + + Status = Tpm2GetCapabilityManufactureID (&mTcgDxeData.BsCap.ManufacturerID); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityManufactureID fail!\n")); ++ DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityManufactureID fail!\n")); + } else { +- DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityManufactureID - %08x\n", mTcgDxeData.BsCap.ManufacturerID)); ++ DEBUG ((DEBUG_INFO, "Tpm2GetCapabilityManufactureID - %08x\n", mTcgDxeData.BsCap.ManufacturerID)); + } + + DEBUG_CODE ( +@@ -2700,19 +2700,19 @@ DriverEntry ( + + Status = Tpm2GetCapabilityFirmwareVersion (&FirmwareVersion1, &FirmwareVersion2); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityFirmwareVersion fail!\n")); ++ DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityFirmwareVersion fail!\n")); + } else { +- DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityFirmwareVersion - %08x %08x\n", FirmwareVersion1, FirmwareVersion2)); ++ DEBUG ((DEBUG_INFO, "Tpm2GetCapabilityFirmwareVersion - %08x %08x\n", FirmwareVersion1, FirmwareVersion2)); + } + ); + + Status = Tpm2GetCapabilityMaxCommandResponseSize (&MaxCommandSize, &MaxResponseSize); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityMaxCommandResponseSize fail!\n")); ++ DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityMaxCommandResponseSize fail!\n")); + } else { + mTcgDxeData.BsCap.MaxCommandSize = (UINT16)MaxCommandSize; + mTcgDxeData.BsCap.MaxResponseSize = (UINT16)MaxResponseSize; +- DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityMaxCommandResponseSize - %08x, %08x\n", MaxCommandSize, MaxResponseSize)); ++ DEBUG ((DEBUG_INFO, "Tpm2GetCapabilityMaxCommandResponseSize - %08x, %08x\n", MaxCommandSize, MaxResponseSize)); + } + + // +@@ -2739,7 +2739,7 @@ DriverEntry ( + } else { + mTcgDxeData.BsCap.NumberOfPCRBanks = PcdGet32 (PcdTcg2NumberOfPCRBanks); + if (PcdGet32 (PcdTcg2NumberOfPCRBanks) > NumberOfPCRBanks) { +- DEBUG ((EFI_D_ERROR, "ERROR: PcdTcg2NumberOfPCRBanks(0x%x) > NumberOfPCRBanks(0x%x)\n", PcdGet32 (PcdTcg2NumberOfPCRBanks), NumberOfPCRBanks)); ++ DEBUG ((DEBUG_ERROR, "ERROR: PcdTcg2NumberOfPCRBanks(0x%x) > NumberOfPCRBanks(0x%x)\n", PcdGet32 (PcdTcg2NumberOfPCRBanks), NumberOfPCRBanks)); + mTcgDxeData.BsCap.NumberOfPCRBanks = NumberOfPCRBanks; + } + } +@@ -2752,10 +2752,10 @@ DriverEntry ( + mTcgDxeData.BsCap.SupportedEventLogs &= ~EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; + } + +- DEBUG ((EFI_D_INFO, "Tcg2.SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs)); +- DEBUG ((EFI_D_INFO, "Tcg2.HashAlgorithmBitmap - 0x%08x\n", mTcgDxeData.BsCap.HashAlgorithmBitmap)); +- DEBUG ((EFI_D_INFO, "Tcg2.NumberOfPCRBanks - 0x%08x\n", mTcgDxeData.BsCap.NumberOfPCRBanks)); +- DEBUG ((EFI_D_INFO, "Tcg2.ActivePcrBanks - 0x%08x\n", mTcgDxeData.BsCap.ActivePcrBanks)); ++ DEBUG ((DEBUG_INFO, "Tcg2.SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs)); ++ DEBUG ((DEBUG_INFO, "Tcg2.HashAlgorithmBitmap - 0x%08x\n", mTcgDxeData.BsCap.HashAlgorithmBitmap)); ++ DEBUG ((DEBUG_INFO, "Tcg2.NumberOfPCRBanks - 0x%08x\n", mTcgDxeData.BsCap.NumberOfPCRBanks)); ++ DEBUG ((DEBUG_INFO, "Tcg2.ActivePcrBanks - 0x%08x\n", mTcgDxeData.BsCap.ActivePcrBanks)); + + if (mTcgDxeData.BsCap.TPMPresentFlag) { + // +@@ -2812,7 +2812,7 @@ DriverEntry ( + // Install Tcg2Protocol + // + Status = InstallTcg2 (); +- DEBUG ((EFI_D_INFO, "InstallTcg2 - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "InstallTcg2 - %r\n", Status)); + + return Status; + } +diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c +index 93a8803ff6..7eb02f08f9 100644 +--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c ++++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c +@@ -267,7 +267,7 @@ SyncPcrAllocationsAndPcrMask ( + UINT32 Tpm2PcrMask; + UINT32 NewTpm2PcrMask; + +- DEBUG ((EFI_D_ERROR, "SyncPcrAllocationsAndPcrMask!\n")); ++ DEBUG ((DEBUG_ERROR, "SyncPcrAllocationsAndPcrMask!\n")); + + // + // Determine the current TPM support and the Platform PCR mask. +@@ -297,9 +297,9 @@ SyncPcrAllocationsAndPcrMask ( + if ((TpmActivePcrBanks & Tpm2PcrMask) != TpmActivePcrBanks) { + NewTpmActivePcrBanks = TpmActivePcrBanks & Tpm2PcrMask; + +- DEBUG ((EFI_D_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks)); ++ DEBUG ((DEBUG_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n", __FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks)); + if (NewTpmActivePcrBanks == 0) { +- DEBUG ((EFI_D_ERROR, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__)); ++ DEBUG ((DEBUG_ERROR, "%a - No viable PCRs active! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__)); + ASSERT (FALSE); + } else { + Status = Tpm2PcrAllocateBanks (NULL, (UINT32)TpmHashAlgorithmBitmap, NewTpmActivePcrBanks); +@@ -307,7 +307,7 @@ SyncPcrAllocationsAndPcrMask ( + // + // We can't do much here, but we hope that this doesn't happen. + // +- DEBUG ((EFI_D_ERROR, "%a - Failed to reallocate PCRs!\n", __FUNCTION__)); ++ DEBUG ((DEBUG_ERROR, "%a - Failed to reallocate PCRs!\n", __FUNCTION__)); + ASSERT_EFI_ERROR (Status); + } + // +@@ -324,9 +324,9 @@ SyncPcrAllocationsAndPcrMask ( + if ((Tpm2PcrMask & TpmHashAlgorithmBitmap) != Tpm2PcrMask) { + NewTpm2PcrMask = Tpm2PcrMask & TpmHashAlgorithmBitmap; + +- DEBUG ((EFI_D_INFO, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__, Tpm2PcrMask, NewTpm2PcrMask)); ++ DEBUG ((DEBUG_INFO, "%a - Updating PcdTpm2HashMask from 0x%X to 0x%X.\n", __FUNCTION__, Tpm2PcrMask, NewTpm2PcrMask)); + if (NewTpm2PcrMask == 0) { +- DEBUG ((EFI_D_ERROR, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__)); ++ DEBUG ((DEBUG_ERROR, "%a - No viable PCRs supported! Please set a less restrictive value for PcdTpm2HashMask!\n", __FUNCTION__)); + ASSERT (FALSE); + } + +@@ -365,7 +365,7 @@ LogHashEvent ( + RetStatus = EFI_SUCCESS; + for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { + if ((SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) { +- DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat)); ++ DEBUG ((DEBUG_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat)); + switch (mTcg2EventInfo[Index].LogFormat) { + case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2: + Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest); +@@ -476,7 +476,7 @@ HashLogExtendEvent ( + } + + if (Status == EFI_DEVICE_ERROR) { +- DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status)); ++ DEBUG ((DEBUG_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status)); + BuildGuidHob (&gTpmErrorHobGuid,0); + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, +@@ -1011,7 +1011,7 @@ PeimEntryMA ( + } + + if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { +- DEBUG ((EFI_D_ERROR, "TPM2 error!\n")); ++ DEBUG ((DEBUG_ERROR, "TPM2 error!\n")); + return EFI_DEVICE_ERROR; + } + +@@ -1075,7 +1075,7 @@ PeimEntryMA ( + for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) { + Status = MeasureSeparatorEventWithError (PcrIndex); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Separator Event with Error not Measured. Error!\n")); ++ DEBUG ((DEBUG_ERROR, "Separator Event with Error not Measured. Error!\n")); + } + } + } +@@ -1106,7 +1106,7 @@ PeimEntryMA ( + + Done: + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "TPM2 error! Build Hob\n")); ++ DEBUG ((DEBUG_ERROR, "TPM2 error! Build Hob\n")); + BuildGuidHob (&gTpmErrorHobGuid,0); + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, +diff --git a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c +index f49eccb0bd..9f5111552b 100644 +--- a/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c ++++ b/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c +@@ -203,7 +203,7 @@ MemoryClearCallback ( + ); + if (EFI_ERROR (Status)) { + mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE; +- DEBUG ((EFI_D_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status)); + return EFI_SUCCESS; + } + +@@ -213,7 +213,7 @@ MemoryClearCallback ( + MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK; + } else { + mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE; +- DEBUG ((EFI_D_ERROR, "[TPM] MOR Parameter error! Parameter = %x\n", mTcgNvs->MemoryClear.Parameter)); ++ DEBUG ((DEBUG_ERROR, "[TPM] MOR Parameter error! Parameter = %x\n", mTcgNvs->MemoryClear.Parameter)); + return EFI_SUCCESS; + } + +@@ -227,7 +227,7 @@ MemoryClearCallback ( + ); + if (EFI_ERROR (Status)) { + mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE; +- DEBUG ((EFI_D_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status)); + } + + return EFI_SUCCESS; +@@ -285,7 +285,7 @@ InitializeTcgCommon ( + EFI_HANDLE NotifyHandle; + + if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){ +- DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n")); ++ DEBUG ((DEBUG_ERROR, "No TPM2 DTPM instance required!\n")); + return EFI_UNSUPPORTED; + } + +@@ -372,4 +372,3 @@ Cleanup: + + return Status; + } +- +diff --git a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDriver.c b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDriver.c +index 8210548077..4bc6086454 100644 +--- a/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDriver.c ++++ b/SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDriver.c +@@ -33,13 +33,13 @@ TcgConfigDriverEntryPoint ( + EFI_TCG_PROTOCOL *TcgProtocol; + + if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){ +- DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n")); ++ DEBUG ((DEBUG_ERROR, "No TPM12 instance required!\n")); + return EFI_UNSUPPORTED; + } + + Status = Tpm12RequestUseTpm (); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "TPM not detected!\n")); ++ DEBUG ((DEBUG_ERROR, "TPM not detected!\n")); + return Status; + } + +diff --git a/SecurityPkg/Tcg/TcgDxe/TcgDxe.c b/SecurityPkg/Tcg/TcgDxe/TcgDxe.c +index 3990d1e937..7019c666b1 100644 +--- a/SecurityPkg/Tcg/TcgDxe/TcgDxe.c ++++ b/SecurityPkg/Tcg/TcgDxe/TcgDxe.c +@@ -588,7 +588,7 @@ TcgDxeHashLogExtendEventI ( + + Done: + if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) { +- DEBUG ((EFI_D_ERROR, "TcgDxeHashLogExtendEventI - %r. Disable TPM.\n", Status)); ++ DEBUG ((DEBUG_ERROR, "TcgDxeHashLogExtendEventI - %r. Disable TPM.\n", Status)); + TcgData->BsCap.TPMPresentFlag = FALSE; + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, +@@ -1127,7 +1127,7 @@ OnReadyToBoot ( + // + Status = MeasureHandoffTables (); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "HOBs not Measured. Error!\n")); ++ DEBUG ((DEBUG_ERROR, "HOBs not Measured. Error!\n")); + } + + // +@@ -1135,7 +1135,7 @@ OnReadyToBoot ( + // + Status = MeasureAllBootVariables (); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Boot Variables not Measured. Error!\n")); ++ DEBUG ((DEBUG_ERROR, "Boot Variables not Measured. Error!\n")); + } + + // +@@ -1145,7 +1145,7 @@ OnReadyToBoot ( + EFI_CALLING_EFI_APPLICATION + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION)); ++ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION)); + } + + // +@@ -1177,11 +1177,11 @@ OnReadyToBoot ( + EFI_RETURNING_FROM_EFI_APPLICATION + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATION)); ++ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATION)); + } + } + +- DEBUG ((EFI_D_INFO, "TPM TcgDxe Measure Data when ReadyToBoot\n")); ++ DEBUG ((DEBUG_INFO, "TPM TcgDxe Measure Data when ReadyToBoot\n")); + // + // Increase boot attempt counter. + // +@@ -1260,7 +1260,7 @@ InstallAcpiTable ( + } + + if (EFI_ERROR (Status)) { +- DEBUG((EFI_D_ERROR, "Tcg Acpi Table installation failure")); ++ DEBUG((DEBUG_ERROR, "Tcg Acpi Table installation failure")); + } + } + +@@ -1289,7 +1289,7 @@ OnExitBootServices ( + EFI_EXIT_BOOT_SERVICES_INVOCATION + ); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION)); ++ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION)); + } + + // +@@ -1299,7 +1299,7 @@ OnExitBootServices ( + EFI_EXIT_BOOT_SERVICES_SUCCEEDED + ); + if (EFI_ERROR (Status)){ +- DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED)); ++ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED)); + } + } + +@@ -1328,7 +1328,7 @@ OnExitBootServicesFailed ( + EFI_EXIT_BOOT_SERVICES_FAILED + ); + if (EFI_ERROR (Status)){ +- DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED)); ++ DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED)); + } + } + +@@ -1381,25 +1381,25 @@ DriverEntry ( + VOID *Registration; + + if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){ +- DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n")); ++ DEBUG ((DEBUG_ERROR, "No TPM12 instance required!\n")); + return EFI_UNSUPPORTED; + } + + if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { +- DEBUG ((EFI_D_ERROR, "TPM error!\n")); ++ DEBUG ((DEBUG_ERROR, "TPM error!\n")); + return EFI_DEVICE_ERROR; + } + + Status = Tpm12RequestUseTpm (); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "TPM not detected!\n")); ++ DEBUG ((DEBUG_ERROR, "TPM not detected!\n")); + return Status; + } + + Status = GetTpmStatus (&mTcgDxeData.BsCap.TPMDeactivatedFlag); + if (EFI_ERROR (Status)) { + DEBUG (( +- EFI_D_ERROR, ++ DEBUG_ERROR, + "DriverEntry: TPM not working properly\n" + )); + return Status; +diff --git a/SecurityPkg/Tcg/TcgPei/TcgPei.c b/SecurityPkg/Tcg/TcgPei/TcgPei.c +index db33daed37..536bd5a408 100644 +--- a/SecurityPkg/Tcg/TcgPei/TcgPei.c ++++ b/SecurityPkg/Tcg/TcgPei/TcgPei.c +@@ -351,7 +351,7 @@ HashLogExtendEvent ( + + Done: + if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) { +- DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status)); ++ DEBUG ((DEBUG_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status)); + BuildGuidHob (&gTpmErrorHobGuid,0); + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, +@@ -844,12 +844,12 @@ PeimEntryMA ( + EFI_BOOT_MODE BootMode; + + if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){ +- DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n")); ++ DEBUG ((DEBUG_ERROR, "No TPM12 instance required!\n")); + return EFI_UNSUPPORTED; + } + + if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { +- DEBUG ((EFI_D_ERROR, "TPM error!\n")); ++ DEBUG ((DEBUG_ERROR, "TPM error!\n")); + return EFI_DEVICE_ERROR; + } + +@@ -913,7 +913,7 @@ PeimEntryMA ( + + Done: + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "TPM error! Build Hob\n")); ++ DEBUG ((DEBUG_ERROR, "TPM error! Build Hob\n")); + BuildGuidHob (&gTpmErrorHobGuid,0); + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, +diff --git a/SecurityPkg/Tcg/TcgSmm/TcgSmm.c b/SecurityPkg/Tcg/TcgSmm/TcgSmm.c +index a60efc7d69..25f443c04f 100644 +--- a/SecurityPkg/Tcg/TcgSmm/TcgSmm.c ++++ b/SecurityPkg/Tcg/TcgSmm/TcgSmm.c +@@ -62,13 +62,13 @@ PhysicalPresenceCallback ( + &PpData + ); + +- DEBUG ((EFI_D_INFO, "[TPM] PP callback, Parameter = %x\n", mTcgNvs->PhysicalPresence.Parameter)); ++ DEBUG ((DEBUG_INFO, "[TPM] PP callback, Parameter = %x\n", mTcgNvs->PhysicalPresence.Parameter)); + if (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) { + if (EFI_ERROR (Status)) { + mTcgNvs->PhysicalPresence.ReturnCode = PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE; + mTcgNvs->PhysicalPresence.LastRequest = 0; + mTcgNvs->PhysicalPresence.Response = 0; +- DEBUG ((EFI_D_ERROR, "[TPM] Get PP variable failure! Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM] Get PP variable failure! Status = %r\n", Status)); + return EFI_SUCCESS; + } + mTcgNvs->PhysicalPresence.ReturnCode = PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS; +@@ -78,7 +78,7 @@ PhysicalPresenceCallback ( + || (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2)) { + if (EFI_ERROR (Status)) { + mTcgNvs->PhysicalPresence.ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE; +- DEBUG ((EFI_D_ERROR, "[TPM] Get PP variable failure! Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM] Get PP variable failure! Status = %r\n", Status)); + return EFI_SUCCESS; + } + if (mTcgNvs->PhysicalPresence.Request == PHYSICAL_PRESENCE_SET_OPERATOR_AUTH) { +@@ -124,7 +124,7 @@ PhysicalPresenceCallback ( + } else if (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) { + if (EFI_ERROR (Status)) { + mTcgNvs->PhysicalPresence.ReturnCode = TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION; +- DEBUG ((EFI_D_ERROR, "[TPM] Get PP variable failure! Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM] Get PP variable failure! Status = %r\n", Status)); + return EFI_SUCCESS; + } + // +@@ -140,7 +140,7 @@ PhysicalPresenceCallback ( + ); + if (EFI_ERROR (Status)) { + mTcgNvs->PhysicalPresence.ReturnCode = TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION; +- DEBUG ((EFI_D_ERROR, "[TPM] Get PP flags failure! Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM] Get PP flags failure! Status = %r\n", Status)); + return EFI_SUCCESS; + } + +@@ -257,7 +257,7 @@ MemoryClearCallback ( + ); + if (EFI_ERROR (Status)) { + mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE; +- DEBUG ((EFI_D_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status)); + return EFI_SUCCESS; + } + +@@ -267,7 +267,7 @@ MemoryClearCallback ( + MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK; + } else { + mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE; +- DEBUG ((EFI_D_ERROR, "[TPM] MOR Parameter error! Parameter = %x\n", mTcgNvs->MemoryClear.Parameter)); ++ DEBUG ((DEBUG_ERROR, "[TPM] MOR Parameter error! Parameter = %x\n", mTcgNvs->MemoryClear.Parameter)); + return EFI_SUCCESS; + } + +@@ -281,7 +281,7 @@ MemoryClearCallback ( + ); + if (EFI_ERROR (Status)) { + mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE; +- DEBUG ((EFI_D_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status)); ++ DEBUG ((DEBUG_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status)); + } + + return EFI_SUCCESS; +@@ -424,7 +424,7 @@ InitializeTcgSmm ( + EFI_HANDLE SwHandle; + + if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){ +- DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n")); ++ DEBUG ((DEBUG_ERROR, "No TPM12 instance required!\n")); + return EFI_UNSUPPORTED; + } + +@@ -460,4 +460,3 @@ InitializeTcgSmm ( + + return EFI_SUCCESS; + } +- +diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +index 65a8188d6d..c19f9e7b90 100644 +--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c ++++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +@@ -458,7 +458,7 @@ EnrollPlatformKey ( + DataSize = PkCert->SignatureListSize; + Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); ++ DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status)); + goto ON_EXIT; + } + +@@ -471,7 +471,7 @@ EnrollPlatformKey ( + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_OUT_OF_RESOURCES) { +- DEBUG ((EFI_D_ERROR, "Enroll PK failed with out of resource.\n")); ++ DEBUG ((DEBUG_ERROR, "Enroll PK failed with out of resource.\n")); + } + goto ON_EXIT; + } +@@ -600,7 +600,7 @@ EnrollRsa2048ToKek ( + | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); ++ DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status)); + goto ON_EXIT; + } + +@@ -724,7 +724,7 @@ EnrollX509ToKek ( + | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); ++ DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status)); + goto ON_EXIT; + } + +@@ -897,7 +897,7 @@ EnrollX509toSigDB ( + | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); ++ DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status)); + goto ON_EXIT; + } + +@@ -2243,7 +2243,7 @@ EnrollImageSignatureToSigDB ( + | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); ++ DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status)); + goto ON_EXIT; + } + +@@ -2700,7 +2700,7 @@ DeleteKeyExchangeKey ( + if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { + Status = CreateTimeBasedPayload (&DataSize, &OldData); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); ++ DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status)); + goto ON_EXIT; + } + } +@@ -2901,7 +2901,7 @@ DeleteSignature ( + if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { + Status = CreateTimeBasedPayload (&DataSize, &OldData); + if (EFI_ERROR (Status)) { +- DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); ++ DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status)); + goto ON_EXIT; + } + } +-- +2.41.0 + diff --git a/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SEC-PATCH-4118-2.patch b/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SEC-PATCH-4118-2.patch new file mode 100644 index 0000000..464b257 --- /dev/null +++ b/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SEC-PATCH-4118-2.patch @@ -0,0 +1,272 @@ +From 7b5040e857f1a16bed935f7944bda8bc6f6999ac Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 13 Feb 2024 16:30:10 -0500 +Subject: [PATCH 11/17] SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH + 4117/4118 symbol rename + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [11/13] 45fc2658aaa726b57219789bb1af64f5c4e2cfdc (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21156 +CVE: CVE-2022-36764 +Upstream: Merged + +commit 40adbb7f628dee79156c679fb0857968b61b7620 +Author: Doug Flick +Date: Wed Jan 17 14:47:20 2024 -0800 + + SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117/4118 symbol rename + + Updates the sanitation function names to be lib unique names + + Cc: Jiewen Yao + Cc: Rahul Kumar + + Signed-off-by: Doug Flick [MSFT] + Message-Id: <7b18434c8a8b561654efd40ced3becb8b378c8f1.1705529990.git.doug.edk2@gmail.com> + Reviewed-by: Jiewen Yao + +Signed-off-by: Jon Maloy +--- + .../DxeTpm2MeasureBootLib.c | 8 +++--- + .../DxeTpm2MeasureBootLibSanitization.c | 8 +++--- + .../DxeTpm2MeasureBootLibSanitization.h | 8 +++--- + .../DxeTpm2MeasureBootLibSanitizationTest.c | 26 +++++++++---------- + 4 files changed, 25 insertions(+), 25 deletions(-) + +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +index f06926e631..8f8bef1d0b 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +@@ -197,7 +197,7 @@ Tcg2MeasureGptTable ( + BlockIo->Media->BlockSize, + (UINT8 *)PrimaryHeader + ); +- if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { ++ if (EFI_ERROR (Status) || EFI_ERROR (Tpm2SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { + DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n")); + FreePool (PrimaryHeader); + return EFI_DEVICE_ERROR; +@@ -206,7 +206,7 @@ Tcg2MeasureGptTable ( + // + // Read the partition entry. + // +- Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); ++ Status = Tpm2SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); + if (EFI_ERROR (Status)) { + FreePool (PrimaryHeader); + return EFI_BAD_BUFFER_SIZE; +@@ -245,7 +245,7 @@ Tcg2MeasureGptTable ( + // + // Prepare Data for Measurement (CcProtocol and Tcg2Protocol) + // +- Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &TcgEventSize); ++ Status = Tpm2SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &TcgEventSize); + if (EFI_ERROR (Status)) { + FreePool (PrimaryHeader); + FreePool (EntryPtr); +@@ -414,7 +414,7 @@ Tcg2MeasurePeImage ( + } + + FilePathSize = (UINT32)GetDevicePathSize (FilePath); +- Status = SanitizePeImageEventSize (FilePathSize, &EventSize); ++ Status = Tpm2SanitizePeImageEventSize (FilePathSize, &EventSize); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c +index 2a4d52c6d5..809a3bfd89 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c +@@ -63,7 +63,7 @@ + **/ + EFI_STATUS + EFIAPI +-SanitizeEfiPartitionTableHeader ( ++Tpm2SanitizeEfiPartitionTableHeader ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo + ) +@@ -169,7 +169,7 @@ SanitizeEfiPartitionTableHeader ( + **/ + EFI_STATUS + EFIAPI +-SanitizePrimaryHeaderAllocationSize ( ++Tpm2SanitizePrimaryHeaderAllocationSize ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + OUT UINT32 *AllocationSize + ) +@@ -221,7 +221,7 @@ SanitizePrimaryHeaderAllocationSize ( + One of the passed parameters was invalid. + **/ + EFI_STATUS +-SanitizePrimaryHeaderGptEventSize ( ++Tpm2SanitizePrimaryHeaderGptEventSize ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + IN UINTN NumberOfPartition, + OUT UINT32 *EventSize +@@ -292,7 +292,7 @@ SanitizePrimaryHeaderGptEventSize ( + One of the passed parameters was invalid. + **/ + EFI_STATUS +-SanitizePeImageEventSize ( ++Tpm2SanitizePeImageEventSize ( + IN UINT32 FilePathSize, + OUT UINT32 *EventSize + ) +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h +index 8f72ba4240..8526bc7537 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h +@@ -54,7 +54,7 @@ + **/ + EFI_STATUS + EFIAPI +-SanitizeEfiPartitionTableHeader ( ++Tpm2SanitizeEfiPartitionTableHeader ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo + ); +@@ -78,7 +78,7 @@ SanitizeEfiPartitionTableHeader ( + **/ + EFI_STATUS + EFIAPI +-SanitizePrimaryHeaderAllocationSize ( ++Tpm2SanitizePrimaryHeaderAllocationSize ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + OUT UINT32 *AllocationSize + ); +@@ -107,7 +107,7 @@ SanitizePrimaryHeaderAllocationSize ( + One of the passed parameters was invalid. + **/ + EFI_STATUS +-SanitizePrimaryHeaderGptEventSize ( ++Tpm2SanitizePrimaryHeaderGptEventSize ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + IN UINTN NumberOfPartition, + OUT UINT32 *EventSize +@@ -131,7 +131,7 @@ SanitizePrimaryHeaderGptEventSize ( + One of the passed parameters was invalid. + **/ + EFI_STATUS +-SanitizePeImageEventSize ( ++Tpm2SanitizePeImageEventSize ( + IN UINT32 FilePathSize, + OUT UINT32 *EventSize + ); +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c +index 820e99aeb9..50a68e1076 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c +@@ -84,27 +84,27 @@ TestSanitizeEfiPartitionTableHeader ( + PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize); + + // Test that a normal PrimaryHeader passes validation +- Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ Status = Tpm2SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR + // Should print "Invalid Partition Table Header NumberOfPartitionEntries!"" + PrimaryHeader.NumberOfPartitionEntries = 0; +- Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ Status = Tpm2SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); + PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; + + // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR + // Should print "Invalid Partition Table Header Size!" + PrimaryHeader.Header.HeaderSize = 0; +- Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ Status = Tpm2SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); + PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); + + // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR + // should print: "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!" + PrimaryHeader.SizeOfPartitionEntry = 1; +- Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ Status = Tpm2SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); + + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); +@@ -137,7 +137,7 @@ TestSanitizePrimaryHeaderAllocationSize ( + PrimaryHeader.NumberOfPartitionEntries = 5; + PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; + +- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // Test that the allocation size is correct compared to the existing logic +@@ -146,19 +146,19 @@ TestSanitizePrimaryHeaderAllocationSize ( + // Test that an overflow is detected + PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; + PrimaryHeader.SizeOfPartitionEntry = 5; +- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); + + // Test the inverse + PrimaryHeader.NumberOfPartitionEntries = 5; + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; +- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); + + // Test the worst case scenario + PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; +- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ Status = Tpm2SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); + + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); +@@ -196,7 +196,7 @@ TestSanitizePrimaryHeaderGptEventSize ( + NumberOfPartition = 13; + + // that the primary event size is correct +- Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); ++ Status = Tpm2SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // Calculate the existing logic event size +@@ -207,12 +207,12 @@ TestSanitizePrimaryHeaderGptEventSize ( + UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize); + + // Tests that the primary event size may not overflow +- Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize); ++ Status = Tpm2SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize); + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); + + // Test that the size of partition entries may not overflow + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; +- Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); ++ Status = Tpm2SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); + + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); +@@ -245,7 +245,7 @@ TestSanitizePeImageEventSize ( + FilePathSize = 255; + + // Test that a normal PE image passes validation +- Status = SanitizePeImageEventSize (FilePathSize, &EventSize); ++ Status = Tpm2SanitizePeImageEventSize (FilePathSize, &EventSize); + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); + + // Test that the event size is correct compared to the existing logic +@@ -258,7 +258,7 @@ TestSanitizePeImageEventSize ( + } + + // Test that the event size may not overflow +- Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize); ++ Status = Tpm2SanitizePeImageEventSize (MAX_UINT32, &EventSize); + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); + + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); +-- +2.41.0 + diff --git a/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch b/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch new file mode 100644 index 0000000..372ad1f --- /dev/null +++ b/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch @@ -0,0 +1,1066 @@ +From dd30c6c8f2a47b46d514eb413c8c96aedc951297 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 17 Jan 2024 12:20:52 -0500 +Subject: [PATCH 06/17] SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117 + - CVE 2022-36763 + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [6/13] d8e42e23d4215506de05ed540644545a4dd65f44 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21154 +CVE: CVE-2022-36763 +Upstream: Merged +Conflicts: Only cosmetic conflicts. + +commit 224446543206450ddb5830e6abd026d61d3c7f4b +Author: Douglas Flick [MSFT] +Date: Fri Jan 12 02:16:01 2024 +0800 + + SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117 - CVE 2022-36763 + + This commit contains the patch files and tests for DxeTpm2MeasureBootLib + CVE 2022-36763. + + Cc: Jiewen Yao + + Signed-off-by: Doug Flick [MSFT] + +Signed-off-by: Jon Maloy +--- + .../DxeTpm2MeasureBootLib.c | 81 ++--- + .../DxeTpm2MeasureBootLib.inf | 4 +- + .../DxeTpm2MeasureBootLibSanitization.c | 275 ++++++++++++++++ + .../DxeTpm2MeasureBootLibSanitization.h | 113 +++++++ + .../DxeTpm2MeasureBootLibSanitizationTest.c | 303 ++++++++++++++++++ + ...Tpm2MeasureBootLibSanitizationTestHost.inf | 28 ++ + SecurityPkg/SecurityPkg.ci.yaml | 2 + + SecurityPkg/Test/SecurityPkgHostTest.dsc | 47 +++ + 8 files changed, 815 insertions(+), 38 deletions(-) + create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c + create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h + create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c + create mode 100644 SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf + create mode 100644 SecurityPkg/Test/SecurityPkgHostTest.dsc + +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +index 7abacdbc0a..476c8d543f 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +@@ -20,6 +20,8 @@ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP
+ SPDX-License-Identifier: BSD-2-Clause-Patent + ++Copyright (c) Microsoft Corporation.
++SPDX-License-Identifier: BSD-2-Clause-Patent + **/ + + #include +@@ -44,6 +46,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + #include + #include + ++#include "DxeTpm2MeasureBootLibSanitization.h" ++ + typedef struct { + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; +@@ -144,10 +148,11 @@ Tcg2MeasureGptTable ( + EFI_TCG2_EVENT *Tcg2Event; + EFI_CC_EVENT *CcEvent; + EFI_GPT_DATA *GptData; +- UINT32 EventSize; ++ UINT32 TcgEventSize; + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; + EFI_CC_MR_INDEX MrIndex; ++ UINT32 AllocSize; + + if (mTcg2MeasureGptCount > 0) { + return EFI_SUCCESS; +@@ -192,25 +197,22 @@ Tcg2MeasureGptTable ( + BlockIo->Media->BlockSize, + (UINT8 *)PrimaryHeader + ); +- if (EFI_ERROR (Status)) { +- DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n")); ++ if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { ++ DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n")); + FreePool (PrimaryHeader); + return EFI_DEVICE_ERROR; + } + + // +- // PrimaryHeader->SizeOfPartitionEntry should not be zero ++ // Read the partition entry. + // +- if (PrimaryHeader->SizeOfPartitionEntry == 0) { +- DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry should not be zero!\n")); ++ Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); ++ if (EFI_ERROR (Status)) { + FreePool (PrimaryHeader); + return EFI_BAD_BUFFER_SIZE; + } + +- // +- // Read the partition entry. +- // +- EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry); ++ EntryPtr = (UINT8 *)AllocatePool (AllocSize); + if (EntryPtr == NULL) { + FreePool (PrimaryHeader); + return EFI_OUT_OF_RESOURCES; +@@ -218,8 +220,8 @@ Tcg2MeasureGptTable ( + Status = DiskIo->ReadDisk ( + DiskIo, + BlockIo->Media->MediaId, +- MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), +- PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry, ++ MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), ++ AllocSize, + EntryPtr + ); + if (EFI_ERROR (Status)) { +@@ -243,23 +245,22 @@ Tcg2MeasureGptTable ( + // + // Prepare Data for Measurement (CcProtocol and Tcg2Protocol) + // +- EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) +- + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry); +- EventPtr = (UINT8 *)AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)); ++ Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &TcgEventSize); ++ if (EFI_ERROR (Status)) { ++ FreePool (PrimaryHeader); ++ FreePool (EntryPtr); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ EventPtr = (UINT8 *)AllocateZeroPool (TcgEventSize); + if (EventPtr == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + Tcg2Event = (EFI_TCG2_EVENT *)EventPtr; +- if (Tcg2Event == NULL) { +- FreePool (PrimaryHeader); +- FreePool (EntryPtr); +- return EFI_OUT_OF_RESOURCES; +- } +- +- Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event); +- Tcg2Event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER); ++ Tcg2Event->Size = TcgEventSize; ++ Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER); + Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION; + Tcg2Event->Header.PCRIndex = 5; + Tcg2Event->Header.EventType = EV_EFI_GPT_EVENT; +@@ -310,7 +311,7 @@ Tcg2MeasureGptTable ( + CcProtocol, + 0, + (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData, +- (UINT64)EventSize, ++ (UINT64)TcgEventSize - OFFSET_OF (EFI_TCG2_EVENT, Event), + CcEvent + ); + if (!EFI_ERROR (Status)) { +@@ -326,7 +327,7 @@ Tcg2MeasureGptTable ( + Tcg2Protocol, + 0, + (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData, +- (UINT64)EventSize, ++ (UINT64)TcgEventSize - OFFSET_OF (EFI_TCG2_EVENT, Event), + Tcg2Event + ); + if (!EFI_ERROR (Status)) { +@@ -442,11 +443,13 @@ Tcg2MeasurePeImage ( + Tcg2Event->Header.PCRIndex = 2; + break; + default: +- DEBUG (( +- DEBUG_ERROR, +- "Tcg2MeasurePeImage: Unknown subsystem type %d", +- ImageType +- )); ++ DEBUG ( ++ ( ++ DEBUG_ERROR, ++ "Tcg2MeasurePeImage: Unknown subsystem type %d", ++ ImageType ++ ) ++ ); + goto Finish; + } + +@@ -514,7 +517,7 @@ Finish: + + @param MeasureBootProtocols Pointer to the located measure boot protocol instances. + +- @retval EFI_SUCCESS Sucessfully locate the measure boot protocol instances (at least one instance). ++ @retval EFI_SUCCESS Successfully locate the measure boot protocol instances (at least one instance). + @retval EFI_UNSUPPORTED Measure boot is not supported. + **/ + EFI_STATUS +@@ -644,12 +647,16 @@ DxeTpm2MeasureBootHandler ( + DEBUG ((DEBUG_INFO, "None of Tcg2Protocol/CcMeasurementProtocol is installed.\n")); + return EFI_SUCCESS; + } +- DEBUG (( +- DEBUG_INFO, +- "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n", +- MeasureBootProtocols.Tcg2Protocol, +- MeasureBootProtocols.CcProtocol +- )); ++ ++ DEBUG ( ++ ( ++ DEBUG_INFO, ++ "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n", ++ MeasureBootProtocols.Tcg2Protocol, ++ MeasureBootProtocols.CcProtocol ++ ) ++ ); ++ + // + // Copy File Device Path + // +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf +index 6dca79a20c..28995f438d 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf +@@ -37,6 +37,8 @@ + + [Sources] + DxeTpm2MeasureBootLib.c ++ DxeTpm2MeasureBootLibSanitization.c ++ DxeTpm2MeasureBootLibSanitization.h + + [Packages] + MdePkg/MdePkg.dec +@@ -46,6 +48,7 @@ + + [LibraryClasses] + BaseMemoryLib ++ SafeIntLib + DebugLib + MemoryAllocationLib + DevicePathLib +@@ -65,4 +68,3 @@ + gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES +- +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c +new file mode 100644 +index 0000000000..e2309655d3 +--- /dev/null ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c +@@ -0,0 +1,275 @@ ++/** @file ++ The library instance provides security service of TPM2 measure boot and ++ Confidential Computing (CC) measure boot. ++ ++ Caution: This file requires additional review when modified. ++ This library will have external input - PE/COFF image and GPT partition. ++ This external input must be validated carefully to avoid security issue like ++ buffer overflow, integer overflow. ++ ++ This file will pull out the validation logic from the following functions, in an ++ attempt to validate the untrusted input in the form of unit tests ++ ++ These are those functions: ++ ++ DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content ++ read is within the image buffer. ++ ++ Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse ++ partition data carefully. ++ ++ Copyright (c) Microsoft Corporation.
++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "DxeTpm2MeasureBootLibSanitization.h" ++ ++#define GPT_HEADER_REVISION_V1 0x00010000 ++ ++/** ++ This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse ++ However this function will not attempt to verify the validity of the GPT partition ++ It will check the following: ++ - Signature ++ - Revision ++ - AlternateLBA ++ - FirstUsableLBA ++ - LastUsableLBA ++ - PartitionEntryLBA ++ - NumberOfPartitionEntries ++ - SizeOfPartitionEntry ++ - BlockIo ++ ++ @param[in] PrimaryHeader ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ ++ @param[in] BlockIo ++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure. ++ ++ @retval EFI_SUCCESS ++ The EFI_PARTITION_TABLE_HEADER structure is valid. ++ ++ @retval EFI_INVALID_PARAMETER ++ The EFI_PARTITION_TABLE_HEADER structure is invalid. ++**/ ++EFI_STATUS ++EFIAPI ++SanitizeEfiPartitionTableHeader ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo ++ ) ++{ ++ // ++ // Verify that the input parameters are safe to use ++ // ++ if (PrimaryHeader == NULL) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((BlockIo == NULL) || (BlockIo->Media == NULL)) { ++ DEBUG ((DEBUG_ERROR, "Invalid BlockIo!\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // The signature must be EFI_PTAB_HEADER_ID ("EFI PART" in ASCII) ++ // ++ if (PrimaryHeader->Header.Signature != EFI_PTAB_HEADER_ID) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // The version must be GPT_HEADER_REVISION_V1 (0x00010000) ++ // ++ if (PrimaryHeader->Header.Revision != GPT_HEADER_REVISION_V1) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header Revision!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // The HeaderSize must be greater than or equal to 92 and must be less than or equal to the logical block size ++ // ++ if ((PrimaryHeader->Header.HeaderSize < sizeof (EFI_PARTITION_TABLE_HEADER)) || (PrimaryHeader->Header.HeaderSize > BlockIo->Media->BlockSize)) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header HeaderSize!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // The partition entries should all be before the first usable block ++ // ++ if (PrimaryHeader->FirstUsableLBA <= PrimaryHeader->PartitionEntryLBA) { ++ DEBUG ((DEBUG_ERROR, "GPT PartitionEntryLBA is not less than FirstUsableLBA!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // Check that the PartitionEntryLBA greater than the Max LBA ++ // This will be used later for multiplication ++ // ++ if (PrimaryHeader->PartitionEntryLBA > DivU64x32 (MAX_UINT64, BlockIo->Media->BlockSize)) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header PartitionEntryLBA!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // Check that the number of partition entries is greater than zero ++ // ++ if (PrimaryHeader->NumberOfPartitionEntries == 0) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // SizeOfPartitionEntry must be 128, 256, 512... improper size may lead to accessing uninitialized memory ++ // ++ if ((PrimaryHeader->SizeOfPartitionEntry < 128) || ((PrimaryHeader->SizeOfPartitionEntry & (PrimaryHeader->SizeOfPartitionEntry - 1)) != 0)) { ++ DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // This check is to prevent overflow when calculating the allocation size for the partition entries ++ // This check will be used later for multiplication ++ // ++ if (PrimaryHeader->NumberOfPartitionEntries > DivU64x32 (MAX_UINT64, PrimaryHeader->SizeOfPartitionEntry)) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ This function will validate that the allocation size from the primary header is sane ++ It will check the following: ++ - AllocationSize does not overflow ++ ++ @param[in] PrimaryHeader ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ ++ @param[out] AllocationSize ++ Pointer to the allocation size. ++ ++ @retval EFI_SUCCESS ++ The allocation size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ The allocation size is invalid. ++**/ ++EFI_STATUS ++EFIAPI ++SanitizePrimaryHeaderAllocationSize ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ OUT UINT32 *AllocationSize ++ ) ++{ ++ EFI_STATUS Status; ++ ++ if (PrimaryHeader == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (AllocationSize == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Replacing logic: ++ // PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry; ++ // ++ Status = SafeUint32Mult (PrimaryHeader->NumberOfPartitionEntries, PrimaryHeader->SizeOfPartitionEntry, AllocationSize); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "Allocation Size would have overflowed!\n")); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ This function will validate that the Gpt Event Size calculated from the primary header is sane ++ It will check the following: ++ - EventSize does not overflow ++ ++ Important: This function includes the entire length of the allocated space, including ++ (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) . When hashing the buffer allocated with this ++ size, the caller must subtract the size of the (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) ++ from the size of the buffer before hashing. ++ ++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ @param[in] NumberOfPartition - Number of partitions. ++ @param[out] EventSize - Pointer to the event size. ++ ++ @retval EFI_SUCCESS ++ The event size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ Overflow would have occurred. ++ ++ @retval EFI_INVALID_PARAMETER ++ One of the passed parameters was invalid. ++**/ ++EFI_STATUS ++SanitizePrimaryHeaderGptEventSize ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ IN UINTN NumberOfPartition, ++ OUT UINT32 *EventSize ++ ) ++{ ++ EFI_STATUS Status; ++ UINT32 SafeNumberOfPartitions; ++ ++ if (PrimaryHeader == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (EventSize == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // We shouldn't even attempt to perform the multiplication if the number of partitions is greater than the maximum value of UINT32 ++ // ++ Status = SafeUintnToUint32 (NumberOfPartition, &SafeNumberOfPartitions); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "NumberOfPartition would have overflowed!\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Replacing logic: ++ // (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry); ++ // ++ Status = SafeUint32Mult (SafeNumberOfPartitions, PrimaryHeader->SizeOfPartitionEntry, EventSize); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed!\n")); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // ++ // Replacing logic: ++ // *EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event); ++ // ++ Status = SafeUint32Add ( ++ OFFSET_OF (EFI_TCG2_EVENT, Event) + OFFSET_OF (EFI_GPT_DATA, Partitions), ++ *EventSize, ++ EventSize ++ ); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed because of GPTData!\n")); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ return EFI_SUCCESS; ++} +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h +new file mode 100644 +index 0000000000..048b738987 +--- /dev/null ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h +@@ -0,0 +1,113 @@ ++/** @file ++ This file includes the function prototypes for the sanitization functions. ++ ++ These are those functions: ++ ++ DxeTpm2MeasureBootLibImageRead() function will make sure the PE/COFF image content ++ read is within the image buffer. ++ ++ Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse ++ partition data carefully. ++ ++ Copyright (c) Microsoft Corporation.
++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#ifndef DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_ ++#define DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse ++ However this function will not attempt to verify the validity of the GPT partition ++ It will check the following: ++ - Signature ++ - Revision ++ - AlternateLBA ++ - FirstUsableLBA ++ - LastUsableLBA ++ - PartitionEntryLBA ++ - NumberOfPartitionEntries ++ - SizeOfPartitionEntry ++ - BlockIo ++ ++ @param[in] PrimaryHeader ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ ++ @param[in] BlockIo ++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure. ++ ++ @retval EFI_SUCCESS ++ The EFI_PARTITION_TABLE_HEADER structure is valid. ++ ++ @retval EFI_INVALID_PARAMETER ++ The EFI_PARTITION_TABLE_HEADER structure is invalid. ++**/ ++EFI_STATUS ++EFIAPI ++SanitizeEfiPartitionTableHeader ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo ++ ); ++ ++/** ++ This function will validate that the allocation size from the primary header is sane ++ It will check the following: ++ - AllocationSize does not overflow ++ ++ @param[in] PrimaryHeader ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ ++ @param[out] AllocationSize ++ Pointer to the allocation size. ++ ++ @retval EFI_SUCCESS ++ The allocation size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ The allocation size is invalid. ++**/ ++EFI_STATUS ++EFIAPI ++SanitizePrimaryHeaderAllocationSize ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ OUT UINT32 *AllocationSize ++ ); ++ ++/** ++ This function will validate that the Gpt Event Size calculated from the primary header is sane ++ It will check the following: ++ - EventSize does not overflow ++ ++ Important: This function includes the entire length of the allocated space, including ++ (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) . When hashing the buffer allocated with this ++ size, the caller must subtract the size of the (sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)) ++ from the size of the buffer before hashing. ++ ++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ @param[in] NumberOfPartition - Number of partitions. ++ @param[out] EventSize - Pointer to the event size. ++ ++ @retval EFI_SUCCESS ++ The event size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ Overflow would have occurred. ++ ++ @retval EFI_INVALID_PARAMETER ++ One of the passed parameters was invalid. ++**/ ++EFI_STATUS ++SanitizePrimaryHeaderGptEventSize ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ IN UINTN NumberOfPartition, ++ OUT UINT32 *EventSize ++ ); ++ ++#endif // DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_ +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c +new file mode 100644 +index 0000000000..3eb9763e3c +--- /dev/null ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c +@@ -0,0 +1,303 @@ ++/** @file ++ This file includes the unit test cases for the DxeTpm2MeasureBootLibSanitizationTest.c. ++ ++ Copyright (c) Microsoft Corporation.
++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../DxeTpm2MeasureBootLibSanitization.h" ++ ++#define UNIT_TEST_NAME "DxeTpm2MeasureBootLibSanitizationTest" ++#define UNIT_TEST_VERSION "1.0" ++ ++#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION 0x00010000 ++#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES 1 ++#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY 128 ++ ++/** ++ This function tests the SanitizeEfiPartitionTableHeader function. ++ It's intent is to test that a malicious EFI_PARTITION_TABLE_HEADER ++ structure will not cause undefined or unexpected behavior. ++ ++ In general the TPM should still be able to measure the data, but ++ be the header should be sanitized to prevent any unexpected behavior. ++ ++ @param[in] Context The unit test context. ++ ++ @retval UNIT_TEST_PASSED The test passed. ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. ++**/ ++UNIT_TEST_STATUS ++EFIAPI ++TestSanitizeEfiPartitionTableHeader ( ++ IN UNIT_TEST_CONTEXT Context ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; ++ EFI_BLOCK_IO_PROTOCOL BlockIo; ++ EFI_BLOCK_IO_MEDIA BlockMedia; ++ ++ // Generate EFI_BLOCK_IO_MEDIA test data ++ BlockMedia.MediaId = 1; ++ BlockMedia.RemovableMedia = FALSE; ++ BlockMedia.MediaPresent = TRUE; ++ BlockMedia.LogicalPartition = FALSE; ++ BlockMedia.ReadOnly = FALSE; ++ BlockMedia.WriteCaching = FALSE; ++ BlockMedia.BlockSize = 512; ++ BlockMedia.IoAlign = 1; ++ BlockMedia.LastBlock = 0; ++ ++ // Generate EFI_BLOCK_IO_PROTOCOL test data ++ BlockIo.Revision = 1; ++ BlockIo.Media = &BlockMedia; ++ BlockIo.Reset = NULL; ++ BlockIo.ReadBlocks = NULL; ++ BlockIo.WriteBlocks = NULL; ++ BlockIo.FlushBlocks = NULL; ++ ++ // Geneate EFI_PARTITION_TABLE_HEADER test data ++ PrimaryHeader.Header.Signature = EFI_PTAB_HEADER_ID; ++ PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION; ++ PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); ++ PrimaryHeader.MyLBA = 1; ++ PrimaryHeader.AlternateLBA = 2; ++ PrimaryHeader.FirstUsableLBA = 3; ++ PrimaryHeader.LastUsableLBA = 4; ++ PrimaryHeader.PartitionEntryLBA = 5; ++ PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES; ++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; ++ PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid ++ ++ // Calculate the CRC32 of the PrimaryHeader ++ PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize); ++ ++ // Test that a normal PrimaryHeader passes validation ++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ UT_ASSERT_NOT_EFI_ERROR (Status); ++ ++ // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR ++ // Should print "Invalid Partition Table Header NumberOfPartitionEntries!"" ++ PrimaryHeader.NumberOfPartitionEntries = 0; ++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); ++ PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; ++ ++ // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR ++ // Should print "Invalid Partition Table Header Size!" ++ PrimaryHeader.Header.HeaderSize = 0; ++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); ++ PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); ++ ++ // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR ++ // should print: "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!" ++ PrimaryHeader.SizeOfPartitionEntry = 1; ++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); ++ ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); ++ ++ return UNIT_TEST_PASSED; ++} ++ ++/** ++ This function tests the SanitizePrimaryHeaderAllocationSize function. ++ It's intent is to test that the untrusted input from a EFI_PARTITION_TABLE_HEADER ++ structure will not cause an overflow when calculating the allocation size. ++ ++ @param[in] Context The unit test context. ++ ++ @retval UNIT_TEST_PASSED The test passed. ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. ++**/ ++UNIT_TEST_STATUS ++EFIAPI ++TestSanitizePrimaryHeaderAllocationSize ( ++ IN UNIT_TEST_CONTEXT Context ++ ) ++{ ++ UINT32 AllocationSize; ++ ++ EFI_STATUS Status; ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; ++ ++ // Test that a normal PrimaryHeader passes validation ++ PrimaryHeader.NumberOfPartitionEntries = 5; ++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; ++ ++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ UT_ASSERT_NOT_EFI_ERROR (Status); ++ ++ // Test that the allocation size is correct compared to the existing logic ++ UT_ASSERT_EQUAL (AllocationSize, PrimaryHeader.NumberOfPartitionEntries * PrimaryHeader.SizeOfPartitionEntry); ++ ++ // Test that an overflow is detected ++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; ++ PrimaryHeader.SizeOfPartitionEntry = 5; ++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); ++ ++ // Test the inverse ++ PrimaryHeader.NumberOfPartitionEntries = 5; ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; ++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); ++ ++ // Test the worst case scenario ++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; ++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); ++ ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); ++ ++ return UNIT_TEST_PASSED; ++} ++ ++/** ++ This function tests the SanitizePrimaryHeaderGptEventSize function. ++ It's intent is to test that the untrusted input from a EFI_GPT_DATA structure ++ will not cause an overflow when calculating the event size. ++ ++ @param[in] Context The unit test context. ++ ++ @retval UNIT_TEST_PASSED The test passed. ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. ++**/ ++UNIT_TEST_STATUS ++EFIAPI ++TestSanitizePrimaryHeaderGptEventSize ( ++ IN UNIT_TEST_CONTEXT Context ++ ) ++{ ++ UINT32 EventSize; ++ UINT32 ExistingLogicEventSize; ++ EFI_STATUS Status; ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; ++ UINTN NumberOfPartition; ++ EFI_GPT_DATA *GptData; ++ EFI_TCG2_EVENT *Tcg2Event; ++ ++ Tcg2Event = NULL; ++ GptData = NULL; ++ ++ // Test that a normal PrimaryHeader passes validation ++ PrimaryHeader.NumberOfPartitionEntries = 5; ++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; ++ ++ // set the number of partitions ++ NumberOfPartition = 13; ++ ++ // that the primary event size is correct ++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); ++ UT_ASSERT_NOT_EFI_ERROR (Status); ++ ++ // Calculate the existing logic event size ++ ExistingLogicEventSize = (UINT32)(OFFSET_OF (EFI_TCG2_EVENT, Event) + OFFSET_OF (EFI_GPT_DATA, Partitions) ++ + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry); ++ ++ // Check that the event size is correct ++ UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize); ++ ++ // Tests that the primary event size may not overflow ++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize); ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); ++ ++ // Test that the size of partition entries may not overflow ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; ++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); ++ ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); ++ ++ return UNIT_TEST_PASSED; ++} ++ ++// *--------------------------------------------------------------------* ++// * Unit Test Code Main Function ++// *--------------------------------------------------------------------* ++ ++/** ++ This function acts as the entry point for the unit tests. ++ ++ @retval UNIT_TEST_PASSED The test passed. ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. ++ @retval others The test failed. ++**/ ++EFI_STATUS ++EFIAPI ++UefiTestMain ( ++ VOID ++ ) ++{ ++ EFI_STATUS Status; ++ UNIT_TEST_FRAMEWORK_HANDLE Framework; ++ UNIT_TEST_SUITE_HANDLE Tcg2MeasureBootLibValidationTestSuite; ++ ++ Framework = NULL; ++ ++ DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME)); ++ ++ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = %r\n", UNIT_TEST_NAME, Status)); ++ goto EXIT; ++ } ++ ++ Status = CreateUnitTestSuite (&Tcg2MeasureBootLibValidationTestSuite, Framework, "Tcg2MeasureBootLibValidationTestSuite", "Common.Tcg2MeasureBootLibValidation", NULL, NULL); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for Tcg2MeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME)); ++ Status = EFI_OUT_OF_RESOURCES; ++ goto EXIT; ++ } ++ ++ // -----------Suite---------------------------------Description----------------------------Class----------------------------------Test Function------------------------Pre---Clean-Context ++ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.Tcg2MeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL); ++ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL); ++ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL); ++ ++ Status = RunAllTestSuites (Framework); ++ ++EXIT: ++ if (Framework != NULL) { ++ FreeUnitTestFramework (Framework); ++ } ++ ++ DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME)); ++ return Status; ++} ++ ++/// ++/// Avoid ECC error for function name that starts with lower case letter ++/// ++#define DxeTpm2MeasureBootLibUnitTestMain main ++ ++/** ++ Standard POSIX C entry point for host based unit test execution. ++ ++ @param[in] Argc Number of arguments ++ @param[in] Argv Array of pointers to arguments ++ ++ @retval 0 Success ++ @retval other Error ++**/ ++INT32 ++DxeTpm2MeasureBootLibUnitTestMain ( ++ IN INT32 Argc, ++ IN CHAR8 *Argv[] ++ ) ++{ ++ return (INT32)UefiTestMain (); ++} +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf +new file mode 100644 +index 0000000000..2999aa2a44 +--- /dev/null ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf +@@ -0,0 +1,28 @@ ++## @file ++# This file builds the unit tests for DxeTpm2MeasureBootLib ++# ++# Copyright (C) Microsoft Corporation.
++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++ ++[Defines] ++ INF_VERSION = 0x00010006 ++ BASE_NAME = DxeTpm2MeasuredBootLibTest ++ FILE_GUID = 144d757f-d423-484e-9309-a23695fad5bd ++ MODULE_TYPE = HOST_APPLICATION ++ VERSION_STRING = 1.0 ++ ENTRY_POINT = main ++ ++[Sources] ++ DxeTpm2MeasureBootLibSanitizationTest.c ++ ../DxeTpm2MeasureBootLibSanitization.c ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ ++[LibraryClasses] ++ BaseLib ++ DebugLib ++ UnitTestLib ++ PrintLib ++ SafeIntLib +diff --git a/SecurityPkg/SecurityPkg.ci.yaml b/SecurityPkg/SecurityPkg.ci.yaml +index d7b9e1f4e2..aa8496d6d9 100644 +--- a/SecurityPkg/SecurityPkg.ci.yaml ++++ b/SecurityPkg/SecurityPkg.ci.yaml +@@ -15,6 +15,8 @@ + ## "", "" + ## ] + "ExceptionList": [ ++ "8005", "gRT", ++ "8001", "DxeTpm2MeasureBootLibUnitTestMain", + ], + ## Both file path and directory path are accepted. + "IgnoreFiles": [ +diff --git a/SecurityPkg/Test/SecurityPkgHostTest.dsc b/SecurityPkg/Test/SecurityPkgHostTest.dsc +new file mode 100644 +index 0000000000..788c1ab6fe +--- /dev/null ++++ b/SecurityPkg/Test/SecurityPkgHostTest.dsc +@@ -0,0 +1,47 @@ ++## @file ++# SecurityPkg DSC file used to build host-based unit tests. ++# ++# Copyright (C) Microsoft Corporation. ++# SPDX-License-Identifier: BSD-2-Clause-Patent ++# ++## ++ ++[Defines] ++ PLATFORM_NAME = SecurityPkgHostTest ++ PLATFORM_GUID = 9D78A9B4-00CD-477E-A5BF-90CC793EEFB0 ++ PLATFORM_VERSION = 0.1 ++ DSC_SPECIFICATION = 0x00010005 ++ OUTPUT_DIRECTORY = Build/SecurityPkg/HostTest ++ SUPPORTED_ARCHITECTURES = IA32|X64 ++ BUILD_TARGETS = NOOPT ++ SKUID_IDENTIFIER = DEFAULT ++ ++!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc ++ ++[LibraryClasses] ++ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf ++ ++[Components] ++ SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiRuntimeServicesTableLib.inf ++ SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockPlatformPKProtectionLib.inf ++ SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiLib.inf ++ SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf ++ SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf ++ ++ # ++ # Build SecurityPkg HOST_APPLICATION Tests ++ # ++ SecurityPkg/Library/SecureBootVariableLib/UnitTest/SecureBootVariableLibUnitTest.inf { ++ ++ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf ++ UefiRuntimeServicesTableLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiRuntimeServicesTableLib.inf ++ PlatformPKProtectionLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockPlatformPKProtectionLib.inf ++ UefiLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiLib.inf ++ } ++ SecurityPkg/Library/SecureBootVariableLib/GoogleTest/SecureBootVariableLibGoogleTest.inf { ++ ++ SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf ++ UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf ++ PlatformPKProtectionLib|SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf ++ UefiLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.inf ++ } +-- +2.41.0 + diff --git a/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-418.patch b/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-418.patch new file mode 100644 index 0000000..f01c9a1 --- /dev/null +++ b/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-418.patch @@ -0,0 +1,286 @@ +From 7c3fefb0c857acb9e7e14b150c4c3131e78fbb63 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 7 Feb 2024 15:43:10 -0500 +Subject: [PATCH 09/17] SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4118 + - CVE 2022-36764 + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [9/13] c7890fc5c5d7fef2fc1daa931ea2d48f3a76b9e3 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21156 +CVE: CVE-2022-36764 +Upstream: Merged + +commit c7b27944218130cca3bbb20314ba5b88b5de4aa4 +Author: Douglas Flick [MSFT] +Date: Fri Jan 12 02:16:04 2024 +0800 + + SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764 + + This commit contains the patch files and tests for DxeTpm2MeasureBootLib + CVE 2022-36764. + + Cc: Jiewen Yao + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Jiewen Yao + +Signed-off-by: Jon Maloy +--- + .../DxeTpm2MeasureBootLib.c | 15 +++-- + .../DxeTpm2MeasureBootLibSanitization.c | 46 +++++++++++++- + .../DxeTpm2MeasureBootLibSanitization.h | 28 ++++++++- + .../DxeTpm2MeasureBootLibSanitizationTest.c | 60 ++++++++++++++++--- + 4 files changed, 133 insertions(+), 16 deletions(-) + +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +index 476c8d543f..f06926e631 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +@@ -372,7 +372,6 @@ Exit: + @retval EFI_OUT_OF_RESOURCES No enough resource to measure image. + @retval EFI_UNSUPPORTED ImageType is unsupported or PE image is mal-format. + @retval other error value +- + **/ + EFI_STATUS + EFIAPI +@@ -399,6 +398,7 @@ Tcg2MeasurePeImage ( + Status = EFI_UNSUPPORTED; + ImageLoad = NULL; + EventPtr = NULL; ++ Tcg2Event = NULL; + + Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol; + CcProtocol = MeasureBootProtocols->CcProtocol; +@@ -413,19 +413,24 @@ Tcg2MeasurePeImage ( + return EFI_UNSUPPORTED; + } + +- FilePathSize = (UINT32) GetDevicePathSize (FilePath); ++ FilePathSize = (UINT32)GetDevicePathSize (FilePath); ++ Status = SanitizePeImageEventSize (FilePathSize, &EventSize); ++ if (EFI_ERROR (Status)) { ++ return EFI_UNSUPPORTED; ++ } + + // + // Determine destination PCR by BootPolicy + // +- EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize; +- EventPtr = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)); ++ // from a malicious GPT disk partition ++ EventPtr = AllocateZeroPool (EventSize); + if (EventPtr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Tcg2Event = (EFI_TCG2_EVENT *)EventPtr; +- Tcg2Event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER); ++ Tcg2Event->Size = EventSize; ++ Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER); + Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION; + ImageLoad = (EFI_IMAGE_LOAD_EVENT *) Tcg2Event->Event; + +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c +index e2309655d3..2a4d52c6d5 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c +@@ -151,7 +151,7 @@ SanitizeEfiPartitionTableHeader ( + } + + /** +- This function will validate that the allocation size from the primary header is sane ++ This function will validate that the allocation size from the primary header is sane + It will check the following: + - AllocationSize does not overflow + +@@ -273,3 +273,47 @@ SanitizePrimaryHeaderGptEventSize ( + + return EFI_SUCCESS; + } ++ ++/** ++ This function will validate that the PeImage Event Size from the loaded image is sane ++ It will check the following: ++ - EventSize does not overflow ++ ++ @param[in] FilePathSize - Size of the file path. ++ @param[out] EventSize - Pointer to the event size. ++ ++ @retval EFI_SUCCESS ++ The event size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ Overflow would have occurred. ++ ++ @retval EFI_INVALID_PARAMETER ++ One of the passed parameters was invalid. ++**/ ++EFI_STATUS ++SanitizePeImageEventSize ( ++ IN UINT32 FilePathSize, ++ OUT UINT32 *EventSize ++ ) ++{ ++ EFI_STATUS Status; ++ ++ // Replacing logic: ++ // sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize; ++ Status = SafeUint32Add (OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath), FilePathSize, EventSize); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n")); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // Replacing logic: ++ // EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event) ++ Status = SafeUint32Add (*EventSize, OFFSET_OF (EFI_TCG2_EVENT, Event), EventSize); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n")); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ return EFI_SUCCESS; ++} +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h +index 048b738987..8f72ba4240 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h +@@ -9,6 +9,9 @@ + Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse + partition data carefully. + ++ Tcg2MeasurePeImage() function will accept untrusted PE/COFF image and validate its ++ data structure within this image buffer before use. ++ + Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +@@ -110,4 +113,27 @@ SanitizePrimaryHeaderGptEventSize ( + OUT UINT32 *EventSize + ); + +-#endif // DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_ ++/** ++ This function will validate that the PeImage Event Size from the loaded image is sane ++ It will check the following: ++ - EventSize does not overflow ++ ++ @param[in] FilePathSize - Size of the file path. ++ @param[out] EventSize - Pointer to the event size. ++ ++ @retval EFI_SUCCESS ++ The event size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ Overflow would have occurred. ++ ++ @retval EFI_INVALID_PARAMETER ++ One of the passed parameters was invalid. ++**/ ++EFI_STATUS ++SanitizePeImageEventSize ( ++ IN UINT32 FilePathSize, ++ OUT UINT32 *EventSize ++ ); ++ ++#endif // DXE_TPM2_MEASURE_BOOT_LIB_VALIDATION_ +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c +index 3eb9763e3c..820e99aeb9 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c +@@ -72,10 +72,10 @@ TestSanitizeEfiPartitionTableHeader ( + PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION; + PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); + PrimaryHeader.MyLBA = 1; +- PrimaryHeader.AlternateLBA = 2; +- PrimaryHeader.FirstUsableLBA = 3; +- PrimaryHeader.LastUsableLBA = 4; +- PrimaryHeader.PartitionEntryLBA = 5; ++ PrimaryHeader.PartitionEntryLBA = 2; ++ PrimaryHeader.AlternateLBA = 3; ++ PrimaryHeader.FirstUsableLBA = 4; ++ PrimaryHeader.LastUsableLBA = 5; + PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES; + PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; + PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid +@@ -187,11 +187,6 @@ TestSanitizePrimaryHeaderGptEventSize ( + EFI_STATUS Status; + EFI_PARTITION_TABLE_HEADER PrimaryHeader; + UINTN NumberOfPartition; +- EFI_GPT_DATA *GptData; +- EFI_TCG2_EVENT *Tcg2Event; +- +- Tcg2Event = NULL; +- GptData = NULL; + + // Test that a normal PrimaryHeader passes validation + PrimaryHeader.NumberOfPartitionEntries = 5; +@@ -225,6 +220,52 @@ TestSanitizePrimaryHeaderGptEventSize ( + return UNIT_TEST_PASSED; + } + ++/** ++ This function tests the SanitizePeImageEventSize function. ++ It's intent is to test that the untrusted input from a file path when generating a ++ EFI_IMAGE_LOAD_EVENT structure will not cause an overflow when calculating ++ the event size when allocating space ++ ++ @param[in] Context The unit test context. ++ ++ @retval UNIT_TEST_PASSED The test passed. ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. ++**/ ++UNIT_TEST_STATUS ++EFIAPI ++TestSanitizePeImageEventSize ( ++ IN UNIT_TEST_CONTEXT Context ++ ) ++{ ++ UINT32 EventSize; ++ UINTN ExistingLogicEventSize; ++ UINT32 FilePathSize; ++ EFI_STATUS Status; ++ ++ FilePathSize = 255; ++ ++ // Test that a normal PE image passes validation ++ Status = SanitizePeImageEventSize (FilePathSize, &EventSize); ++ UT_ASSERT_EQUAL (Status, EFI_SUCCESS); ++ ++ // Test that the event size is correct compared to the existing logic ++ ExistingLogicEventSize = OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath) + FilePathSize; ++ ExistingLogicEventSize += OFFSET_OF (EFI_TCG2_EVENT, Event); ++ ++ if (EventSize != ExistingLogicEventSize) { ++ UT_LOG_ERROR ("SanitizePeImageEventSize returned an incorrect event size. Expected %u, got %u\n", ExistingLogicEventSize, EventSize); ++ return UNIT_TEST_ERROR_TEST_FAILED; ++ } ++ ++ // Test that the event size may not overflow ++ Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize); ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); ++ ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); ++ ++ return UNIT_TEST_PASSED; ++} ++ + // *--------------------------------------------------------------------* + // * Unit Test Code Main Function + // *--------------------------------------------------------------------* +@@ -267,6 +308,7 @@ UefiTestMain ( + AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.Tcg2MeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL); + AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL); + AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL); ++ AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests PE Image and FileSize checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePeImageEventSize, NULL, NULL, NULL); + + Status = RunAllTestSuites (Framework); + +-- +2.41.0 + diff --git a/edk2-SecurityPkg-DxeTpmMeasureBootLib-SEC-PATCH-4117-2.patch b/edk2-SecurityPkg-DxeTpmMeasureBootLib-SEC-PATCH-4117-2.patch new file mode 100644 index 0000000..b9629c0 --- /dev/null +++ b/edk2-SecurityPkg-DxeTpmMeasureBootLib-SEC-PATCH-4117-2.patch @@ -0,0 +1,279 @@ +From ac25c501c8d97c7520a7c75ae708fb4c43bae035 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 13 Feb 2024 16:30:10 -0500 +Subject: [PATCH 12/17] SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH + 4117/4118 symbol rename + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [12/13] 6ef41050fb68f984a5ae6104ccc102afb5290f9f (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21156 +CVE: CVE-2022-36764 +Upstream: Merged + +commit 326db0c9072004dea89427ea3a44393a84966f2b +Author: Doug Flick +Date: Wed Jan 17 14:47:21 2024 -0800 + + SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117/4118 symbol rename + + Updates the sanitation function names to be lib unique names + + Cc: Jiewen Yao + Cc: Rahul Kumar + + Signed-off-by: Doug Flick [MSFT] + Message-Id: <355aa846a99ca6ac0f7574cf5982661da0d9fea6.1705529990.git.doug.edk2@gmail.com> + Reviewed-by: Jiewen Yao + +Signed-off-by: Jon Maloy +--- + .../DxeTpmMeasureBootLib.c | 8 +++--- + .../DxeTpmMeasureBootLibSanitization.c | 10 +++---- + .../DxeTpmMeasureBootLibSanitization.h | 8 +++--- + .../DxeTpmMeasureBootLibSanitizationTest.c | 26 +++++++++---------- + 4 files changed, 26 insertions(+), 26 deletions(-) + +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +index 1598015176..c39018d7e4 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +@@ -171,7 +171,7 @@ TcgMeasureGptTable ( + BlockIo->Media->BlockSize, + (UINT8 *)PrimaryHeader + ); +- if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { ++ if (EFI_ERROR (Status) || EFI_ERROR (TpmSanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { + DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n")); + FreePool (PrimaryHeader); + return EFI_DEVICE_ERROR; +@@ -179,7 +179,7 @@ TcgMeasureGptTable ( + // + // Read the partition entry. + // +- Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); ++ Status = TpmSanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); + if (EFI_ERROR (Status)) { + FreePool (PrimaryHeader); + return EFI_DEVICE_ERROR; +@@ -218,7 +218,7 @@ TcgMeasureGptTable ( + // + // Prepare Data for Measurement + // +- Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &EventSize); ++ Status = TpmSanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &EventSize); + TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize); + if (TcgEvent == NULL) { + FreePool (PrimaryHeader); +@@ -344,7 +344,7 @@ TcgMeasurePeImage ( + + // Determine destination PCR by BootPolicy + // +- Status = SanitizePeImageEventSize (FilePathSize, &EventSize); ++ Status = TpmSanitizePeImageEventSize (FilePathSize, &EventSize); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c +index bcf8c6de6f..7f17af56cd 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c +@@ -1,5 +1,5 @@ + /** @file +- The library instance provides security service of TPM2 measure boot and ++ The library instance provides security service of TPM measure boot and + Confidential Computing (CC) measure boot. + + Caution: This file requires additional review when modified. +@@ -63,7 +63,7 @@ + **/ + EFI_STATUS + EFIAPI +-SanitizeEfiPartitionTableHeader ( ++TpmSanitizeEfiPartitionTableHeader ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo + ) +@@ -145,7 +145,7 @@ SanitizeEfiPartitionTableHeader ( + **/ + EFI_STATUS + EFIAPI +-SanitizePrimaryHeaderAllocationSize ( ++TpmSanitizePrimaryHeaderAllocationSize ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + OUT UINT32 *AllocationSize + ) +@@ -194,7 +194,7 @@ SanitizePrimaryHeaderAllocationSize ( + One of the passed parameters was invalid. + **/ + EFI_STATUS +-SanitizePrimaryHeaderGptEventSize ( ++TpmSanitizePrimaryHeaderGptEventSize ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + IN UINTN NumberOfPartition, + OUT UINT32 *EventSize +@@ -258,7 +258,7 @@ SanitizePrimaryHeaderGptEventSize ( + One of the passed parameters was invalid. + **/ + EFI_STATUS +-SanitizePeImageEventSize ( ++TpmSanitizePeImageEventSize ( + IN UINT32 FilePathSize, + OUT UINT32 *EventSize + ) +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h +index 2248495813..db6e9c3752 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h +@@ -53,7 +53,7 @@ + **/ + EFI_STATUS + EFIAPI +-SanitizeEfiPartitionTableHeader ( ++TpmSanitizeEfiPartitionTableHeader ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo + ); +@@ -77,7 +77,7 @@ SanitizeEfiPartitionTableHeader ( + **/ + EFI_STATUS + EFIAPI +-SanitizePrimaryHeaderAllocationSize ( ++TpmSanitizePrimaryHeaderAllocationSize ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + OUT UINT32 *AllocationSize + ); +@@ -105,7 +105,7 @@ SanitizePrimaryHeaderAllocationSize ( + One of the passed parameters was invalid. + **/ + EFI_STATUS +-SanitizePrimaryHeaderGptEventSize ( ++TpmSanitizePrimaryHeaderGptEventSize ( + IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, + IN UINTN NumberOfPartition, + OUT UINT32 *EventSize +@@ -129,7 +129,7 @@ SanitizePrimaryHeaderGptEventSize ( + One of the passed parameters was invalid. + **/ + EFI_STATUS +-SanitizePeImageEventSize ( ++TpmSanitizePeImageEventSize ( + IN UINT32 FilePathSize, + OUT UINT32 *EventSize + ); +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c +index c41498be45..de1740af41 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c +@@ -83,27 +83,27 @@ TestSanitizeEfiPartitionTableHeader ( + PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize); + + // Test that a normal PrimaryHeader passes validation +- Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ Status = TpmSanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR + // Should print "Invalid Partition Table Header NumberOfPartitionEntries!"" + PrimaryHeader.NumberOfPartitionEntries = 0; +- Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ Status = TpmSanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); + PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; + + // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR + // Should print "Invalid Partition Table Header Size!" + PrimaryHeader.Header.HeaderSize = 0; +- Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ Status = TpmSanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); + PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); + + // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR + // should print: "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!" + PrimaryHeader.SizeOfPartitionEntry = 1; +- Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ Status = TpmSanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); + UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); + + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); +@@ -136,7 +136,7 @@ TestSanitizePrimaryHeaderAllocationSize ( + PrimaryHeader.NumberOfPartitionEntries = 5; + PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; + +- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // Test that the allocation size is correct compared to the existing logic +@@ -145,19 +145,19 @@ TestSanitizePrimaryHeaderAllocationSize ( + // Test that an overflow is detected + PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; + PrimaryHeader.SizeOfPartitionEntry = 5; +- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); + + // Test the inverse + PrimaryHeader.NumberOfPartitionEntries = 5; + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; +- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); + + // Test the worst case scenario + PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; +- Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ Status = TpmSanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); + + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); +@@ -195,7 +195,7 @@ TestSanitizePrimaryHeaderGptEventSize ( + NumberOfPartition = 13; + + // that the primary event size is correct +- Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); ++ Status = TpmSanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // Calculate the existing logic event size +@@ -206,12 +206,12 @@ TestSanitizePrimaryHeaderGptEventSize ( + UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize); + + // Tests that the primary event size may not overflow +- Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize); ++ Status = TpmSanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize); + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); + + // Test that the size of partition entries may not overflow + PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; +- Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); ++ Status = TpmSanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); + UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); + + DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); +@@ -269,7 +269,7 @@ TestSanitizePeImageEventSize ( + FilePathSize = 255; + + // Test that a normal PE image passes validation +- Status = SanitizePeImageEventSize (FilePathSize, &EventSize); ++ Status = TpmSanitizePeImageEventSize (FilePathSize, &EventSize); + if (EFI_ERROR (Status)) { + UT_LOG_ERROR ("SanitizePeImageEventSize failed with %r\n", Status); + goto Exit; +@@ -285,7 +285,7 @@ TestSanitizePeImageEventSize ( + } + + // Test that the event size may not overflow +- Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize); ++ Status = TpmSanitizePeImageEventSize (MAX_UINT32, &EventSize); + if (Status != EFI_BAD_BUFFER_SIZE) { + UT_LOG_ERROR ("SanitizePeImageEventSize succeded when it was supposed to fail with %r\n", Status); + goto Exit; +-- +2.41.0 + diff --git a/edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4117.patch b/edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4117.patch new file mode 100644 index 0000000..499abda --- /dev/null +++ b/edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4117.patch @@ -0,0 +1,960 @@ +From cb36d95002013ae8d4e5120383cd756a2a6c4124 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 17 Jan 2024 12:20:52 -0500 +Subject: [PATCH 07/17] SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117 + - CVE 2022-36763 + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [7/13] f5a5d2b0a33dc1efdb83e501eda2716df0e904a0 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21154 +CVE: CVE-2022-36763 +Upstream: Merged +Conflicts: We get function definiton clash for the following three functions: + - SanitizeEfiPartitionTableHeader() + - SanitizePrimaryHeaderAllocationSize() + - SanitizePrimaryHeaderGptEventSize() + Those are are defined both in + - SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitazion.c + and + - SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitazion.c + Closer investigation reveals that they are identical in functionality (although + not in comment style). + I chose to leave them as is now, meaning that this package will be + unbuildable until I add a commit renaming these symbols later in + this series. + +commit 4776a1b39ee08fc45c70c1eab5a0195f325000d3 +Author: Douglas Flick [MSFT] +Date: Fri Jan 12 02:16:02 2024 +0800 + + SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117 - CVE 2022-36763 + + This commit contains the patch files and tests for DxeTpmMeasureBootLib + CVE 2022-36763. + + Cc: Jiewen Yao + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Jiewen Yao + +Signed-off-by: Jon Maloy +--- + .../DxeTpmMeasureBootLib.c | 74 +++-- + .../DxeTpmMeasureBootLib.inf | 4 +- + .../DxeTpmMeasureBootLibSanitization.c | 242 ++++++++++++++ + .../DxeTpmMeasureBootLibSanitization.h | 114 +++++++ + .../DxeTpmMeasureBootLibSanitizationTest.c | 301 ++++++++++++++++++ + ...eTpmMeasureBootLibSanitizationTestHost.inf | 28 ++ + SecurityPkg/SecurityPkg.ci.yaml | 1 + + SecurityPkg/Test/SecurityPkgHostTest.dsc | 1 + + 8 files changed, 734 insertions(+), 31 deletions(-) + create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c + create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h + create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c + create mode 100644 SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf + +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +index 27c0ea48ca..d44422dee8 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +@@ -18,6 +18,8 @@ + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + ++Copyright (c) Microsoft Corporation.
++SPDX-License-Identifier: BSD-2-Clause-Patent + **/ + + #include +@@ -40,6 +42,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + #include + #include + ++#include "DxeTpmMeasureBootLibSanitization.h" ++ + // + // Flag to check GPT partition. It only need be measured once. + // +@@ -123,19 +127,22 @@ TcgMeasureGptTable ( + IN EFI_HANDLE GptHandle + ) + { +- EFI_STATUS Status; +- EFI_BLOCK_IO_PROTOCOL *BlockIo; +- EFI_DISK_IO_PROTOCOL *DiskIo; +- EFI_PARTITION_TABLE_HEADER *PrimaryHeader; +- EFI_PARTITION_ENTRY *PartitionEntry; +- UINT8 *EntryPtr; +- UINTN NumberOfPartition; +- UINT32 Index; +- TCG_PCR_EVENT *TcgEvent; +- EFI_GPT_DATA *GptData; +- UINT32 EventSize; +- UINT32 EventNumber; +- EFI_PHYSICAL_ADDRESS EventLogLastEntry; ++ EFI_STATUS Status; ++ EFI_BLOCK_IO_PROTOCOL *BlockIo; ++ EFI_DISK_IO_PROTOCOL *DiskIo; ++ EFI_PARTITION_TABLE_HEADER *PrimaryHeader; ++ EFI_PARTITION_ENTRY *PartitionEntry; ++ UINT8 *EntryPtr; ++ UINTN NumberOfPartition; ++ UINT32 Index; ++ TCG_PCR_EVENT *TcgEvent; ++ EFI_GPT_DATA *GptData; ++ UINT32 EventSize; ++ UINT32 EventNumber; ++ EFI_PHYSICAL_ADDRESS EventLogLastEntry; ++ UINT32 AllocSize; ++ ++ GptData = NULL; + + if (mMeasureGptCount > 0) { + return EFI_SUCCESS; +@@ -163,15 +170,21 @@ TcgMeasureGptTable ( + BlockIo->Media->BlockSize, + (UINT8 *)PrimaryHeader + ); +- if (EFI_ERROR (Status)) { +- DEBUG ((DEBUG_ERROR, "Failed to Read Partition Table Header!\n")); ++ if (EFI_ERROR (Status) || EFI_ERROR (SanitizeEfiPartitionTableHeader (PrimaryHeader, BlockIo))) { ++ DEBUG ((DEBUG_ERROR, "Failed to read Partition Table Header or invalid Partition Table Header!\n")); + FreePool (PrimaryHeader); + return EFI_DEVICE_ERROR; + } + // + // Read the partition entry. + // +- EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry); ++ Status = SanitizePrimaryHeaderAllocationSize (PrimaryHeader, &AllocSize); ++ if (EFI_ERROR (Status)) { ++ FreePool (PrimaryHeader); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ EntryPtr = (UINT8 *)AllocatePool (AllocSize); + if (EntryPtr == NULL) { + FreePool (PrimaryHeader); + return EFI_OUT_OF_RESOURCES; +@@ -179,8 +192,8 @@ TcgMeasureGptTable ( + Status = DiskIo->ReadDisk ( + DiskIo, + BlockIo->Media->MediaId, +- MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), +- PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry, ++ MultU64x32 (PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), ++ AllocSize, + EntryPtr + ); + if (EFI_ERROR (Status)) { +@@ -204,19 +217,18 @@ TcgMeasureGptTable ( + // + // Prepare Data for Measurement + // +- EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) +- + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry); +- TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR)); ++ Status = SanitizePrimaryHeaderGptEventSize (PrimaryHeader, NumberOfPartition, &EventSize); ++ TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (EventSize); + if (TcgEvent == NULL) { + FreePool (PrimaryHeader); + FreePool (EntryPtr); + return EFI_OUT_OF_RESOURCES; + } + +- TcgEvent->PCRIndex = 5; +- TcgEvent->EventType = EV_EFI_GPT_EVENT; +- TcgEvent->EventSize = EventSize; +- GptData = (EFI_GPT_DATA *) TcgEvent->Event; ++ TcgEvent->PCRIndex = 5; ++ TcgEvent->EventType = EV_EFI_GPT_EVENT; ++ TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR); ++ GptData = (EFI_GPT_DATA *)TcgEvent->Event; + + // + // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition +@@ -354,11 +366,13 @@ TcgMeasurePeImage ( + TcgEvent->PCRIndex = 2; + break; + default: +- DEBUG (( +- DEBUG_ERROR, +- "TcgMeasurePeImage: Unknown subsystem type %d", +- ImageType +- )); ++ DEBUG ( ++ ( ++ DEBUG_ERROR, ++ "TcgMeasurePeImage: Unknown subsystem type %d", ++ ImageType ++ ) ++ ); + goto Finish; + } + +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf +index ebab6f7c1e..414c654d15 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf +@@ -32,6 +32,8 @@ + + [Sources] + DxeTpmMeasureBootLib.c ++ DxeTpmMeasureBootLibSanitization.c ++ DxeTpmMeasureBootLibSanitization.h + + [Packages] + MdePkg/MdePkg.dec +@@ -41,6 +43,7 @@ + + [LibraryClasses] + BaseMemoryLib ++ SafeIntLib + DebugLib + MemoryAllocationLib + DevicePathLib +@@ -59,4 +62,3 @@ + gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES +- +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c +new file mode 100644 +index 0000000000..37cd3ed0ea +--- /dev/null ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c +@@ -0,0 +1,242 @@ ++/** @file ++ The library instance provides security service of TPM2 measure boot and ++ Confidential Computing (CC) measure boot. ++ ++ Caution: This file requires additional review when modified. ++ This library will have external input - PE/COFF image and GPT partition. ++ This external input must be validated carefully to avoid security issue like ++ buffer overflow, integer overflow. ++ ++ This file will pull out the validation logic from the following functions, in an ++ attempt to validate the untrusted input in the form of unit tests ++ ++ These are those functions: ++ ++ DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content ++ read is within the image buffer. ++ ++ Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse ++ partition data carefully. ++ ++ Copyright (c) Microsoft Corporation.
++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "DxeTpmMeasureBootLibSanitization.h" ++ ++#define GPT_HEADER_REVISION_V1 0x00010000 ++ ++/** ++ This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse ++ However this function will not attempt to verify the validity of the GPT partition ++ It will check the following: ++ - Signature ++ - Revision ++ - AlternateLBA ++ - FirstUsableLBA ++ - LastUsableLBA ++ - PartitionEntryLBA ++ - NumberOfPartitionEntries ++ - SizeOfPartitionEntry ++ - BlockIo ++ ++ @param[in] PrimaryHeader ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ ++ @param[in] BlockIo ++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure. ++ ++ @retval EFI_SUCCESS ++ The EFI_PARTITION_TABLE_HEADER structure is valid. ++ ++ @retval EFI_INVALID_PARAMETER ++ The EFI_PARTITION_TABLE_HEADER structure is invalid. ++**/ ++EFI_STATUS ++EFIAPI ++SanitizeEfiPartitionTableHeader ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo ++ ) ++{ ++ // Verify that the input parameters are safe to use ++ if (PrimaryHeader == NULL) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((BlockIo == NULL) || (BlockIo->Media == NULL)) { ++ DEBUG ((DEBUG_ERROR, "Invalid BlockIo!\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // The signature must be EFI_PTAB_HEADER_ID ("EFI PART" in ASCII) ++ if (PrimaryHeader->Header.Signature != EFI_PTAB_HEADER_ID) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // The version must be GPT_HEADER_REVISION_V1 (0x00010000) ++ if (PrimaryHeader->Header.Revision != GPT_HEADER_REVISION_V1) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header Revision!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // The HeaderSize must be greater than or equal to 92 and must be less than or equal to the logical block size ++ if ((PrimaryHeader->Header.HeaderSize < sizeof (EFI_PARTITION_TABLE_HEADER)) || (PrimaryHeader->Header.HeaderSize > BlockIo->Media->BlockSize)) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header HeaderSize!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // check that the PartitionEntryLBA greater than the Max LBA ++ // This will be used later for multiplication ++ if (PrimaryHeader->PartitionEntryLBA > DivU64x32 (MAX_UINT64, BlockIo->Media->BlockSize)) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header PartitionEntryLBA!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // Check that the number of partition entries is greater than zero ++ if (PrimaryHeader->NumberOfPartitionEntries == 0) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // SizeOfPartitionEntry must be 128, 256, 512... improper size may lead to accessing uninitialized memory ++ if ((PrimaryHeader->SizeOfPartitionEntry < 128) || ((PrimaryHeader->SizeOfPartitionEntry & (PrimaryHeader->SizeOfPartitionEntry - 1)) != 0)) { ++ DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // This check is to prevent overflow when calculating the allocation size for the partition entries ++ // This check will be used later for multiplication ++ if (PrimaryHeader->NumberOfPartitionEntries > DivU64x32 (MAX_UINT64, PrimaryHeader->SizeOfPartitionEntry)) { ++ DEBUG ((DEBUG_ERROR, "Invalid Partition Table Header NumberOfPartitionEntries!\n")); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ This function will validate that the allocation size from the primary header is sane ++ It will check the following: ++ - AllocationSize does not overflow ++ ++ @param[in] PrimaryHeader ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ ++ @param[out] AllocationSize ++ Pointer to the allocation size. ++ ++ @retval EFI_SUCCESS ++ The allocation size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ The allocation size is invalid. ++**/ ++EFI_STATUS ++EFIAPI ++SanitizePrimaryHeaderAllocationSize ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ OUT UINT32 *AllocationSize ++ ) ++{ ++ EFI_STATUS Status; ++ ++ if (PrimaryHeader == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (AllocationSize == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // Replacing logic: ++ // PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry; ++ Status = SafeUint32Mult (PrimaryHeader->NumberOfPartitionEntries, PrimaryHeader->SizeOfPartitionEntry, AllocationSize); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "Allocation Size would have overflowed!\n")); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ This function will validate that the Gpt Event Size calculated from the primary header is sane ++ It will check the following: ++ - EventSize does not overflow ++ ++ Important: This function includes the entire length of the allocated space, including the ++ TCG_PCR_EVENT_HDR. When hashing the buffer allocated with this size, the caller must subtract ++ the size of the TCG_PCR_EVENT_HDR from the size of the buffer before hashing. ++ ++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ @param[in] NumberOfPartition - Number of partitions. ++ @param[out] EventSize - Pointer to the event size. ++ ++ @retval EFI_SUCCESS ++ The event size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ Overflow would have occurred. ++ ++ @retval EFI_INVALID_PARAMETER ++ One of the passed parameters was invalid. ++**/ ++EFI_STATUS ++SanitizePrimaryHeaderGptEventSize ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ IN UINTN NumberOfPartition, ++ OUT UINT32 *EventSize ++ ) ++{ ++ EFI_STATUS Status; ++ UINT32 SafeNumberOfPartitions; ++ ++ if (PrimaryHeader == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (EventSize == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // We shouldn't even attempt to perform the multiplication if the number of partitions is greater than the maximum value of UINT32 ++ Status = SafeUintnToUint32 (NumberOfPartition, &SafeNumberOfPartitions); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "NumberOfPartition would have overflowed!\n")); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // Replacing logic: ++ // (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry + sizeof (TCG_PCR_EVENT_HDR)); ++ Status = SafeUint32Mult (SafeNumberOfPartitions, PrimaryHeader->SizeOfPartitionEntry, EventSize); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed!\n")); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ Status = SafeUint32Add ( ++ sizeof (TCG_PCR_EVENT_HDR) + ++ OFFSET_OF (EFI_GPT_DATA, Partitions), ++ *EventSize, ++ EventSize ++ ); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "Event Size would have overflowed because of GPTData!\n")); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ return EFI_SUCCESS; ++} ++ +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h +new file mode 100644 +index 0000000000..0d9d00c281 +--- /dev/null ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h +@@ -0,0 +1,114 @@ ++/** @file ++ This file includes the function prototypes for the sanitization functions. ++ ++ These are those functions: ++ ++ DxeTpmMeasureBootLibImageRead() function will make sure the PE/COFF image content ++ read is within the image buffer. ++ ++ TcgMeasurePeImage() function will accept untrusted PE/COFF image and validate its ++ data structure within this image buffer before use. ++ ++ TcgMeasureGptTable() function will receive untrusted GPT partition table, and parse ++ partition data carefully. ++ ++ Copyright (c) Microsoft Corporation.
++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#ifndef DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_ ++#define DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_ ++ ++#include ++#include ++#include ++#include ++ ++/** ++ This function will validate the EFI_PARTITION_TABLE_HEADER structure is safe to parse ++ However this function will not attempt to verify the validity of the GPT partition ++ It will check the following: ++ - Signature ++ - Revision ++ - AlternateLBA ++ - FirstUsableLBA ++ - LastUsableLBA ++ - PartitionEntryLBA ++ - NumberOfPartitionEntries ++ - SizeOfPartitionEntry ++ - BlockIo ++ ++ @param[in] PrimaryHeader ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ ++ @param[in] BlockIo ++ Pointer to the EFI_BLOCK_IO_PROTOCOL structure. ++ ++ @retval EFI_SUCCESS ++ The EFI_PARTITION_TABLE_HEADER structure is valid. ++ ++ @retval EFI_INVALID_PARAMETER ++ The EFI_PARTITION_TABLE_HEADER structure is invalid. ++**/ ++EFI_STATUS ++EFIAPI ++SanitizeEfiPartitionTableHeader ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ IN CONST EFI_BLOCK_IO_PROTOCOL *BlockIo ++ ); ++ ++/** ++ This function will validate that the allocation size from the primary header is sane ++ It will check the following: ++ - AllocationSize does not overflow ++ ++ @param[in] PrimaryHeader ++ Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ ++ @param[out] AllocationSize ++ Pointer to the allocation size. ++ ++ @retval EFI_SUCCESS ++ The allocation size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ The allocation size is invalid. ++**/ ++EFI_STATUS ++EFIAPI ++SanitizePrimaryHeaderAllocationSize ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ OUT UINT32 *AllocationSize ++ ); ++ ++/** ++ This function will validate that the Gpt Event Size calculated from the primary header is sane ++ It will check the following: ++ - EventSize does not overflow ++ ++ Important: This function includes the entire length of the allocated space, including the ++ TCG_PCR_EVENT_HDR. When hashing the buffer allocated with this size, the caller must subtract ++ the size of the TCG_PCR_EVENT_HDR from the size of the buffer before hashing. ++ ++ @param[in] PrimaryHeader - Pointer to the EFI_PARTITION_TABLE_HEADER structure. ++ @param[in] NumberOfPartition - Number of partitions. ++ @param[out] EventSize - Pointer to the event size. ++ ++ @retval EFI_SUCCESS ++ The event size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ Overflow would have occurred. ++ ++ @retval EFI_INVALID_PARAMETER ++ One of the passed parameters was invalid. ++**/ ++EFI_STATUS ++SanitizePrimaryHeaderGptEventSize ( ++ IN CONST EFI_PARTITION_TABLE_HEADER *PrimaryHeader, ++ IN UINTN NumberOfPartition, ++ OUT UINT32 *EventSize ++ ); ++ ++#endif // DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_ +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c +new file mode 100644 +index 0000000000..eeb928cdb0 +--- /dev/null ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c +@@ -0,0 +1,301 @@ ++/** @file ++This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c. ++ ++Copyright (c) Microsoft Corporation.
++SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../DxeTpmMeasureBootLibSanitization.h" ++ ++#define UNIT_TEST_NAME "DxeTpmMeasureBootLibSanitizationTest" ++#define UNIT_TEST_VERSION "1.0" ++ ++#define DEFAULT_PRIMARY_TABLE_HEADER_REVISION 0x00010000 ++#define DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES 1 ++#define DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY 128 ++ ++/** ++ This function tests the SanitizeEfiPartitionTableHeader function. ++ It's intent is to test that a malicious EFI_PARTITION_TABLE_HEADER ++ structure will not cause undefined or unexpected behavior. ++ ++ In general the TPM should still be able to measure the data, but ++ be the header should be sanitized to prevent any unexpected behavior. ++ ++ @param[in] Context The unit test context. ++ ++ @retval UNIT_TEST_PASSED The test passed. ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. ++**/ ++UNIT_TEST_STATUS ++EFIAPI ++TestSanitizeEfiPartitionTableHeader ( ++ IN UNIT_TEST_CONTEXT Context ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; ++ EFI_BLOCK_IO_PROTOCOL BlockIo; ++ EFI_BLOCK_IO_MEDIA BlockMedia; ++ ++ // Generate EFI_BLOCK_IO_MEDIA test data ++ BlockMedia.MediaId = 1; ++ BlockMedia.RemovableMedia = FALSE; ++ BlockMedia.MediaPresent = TRUE; ++ BlockMedia.LogicalPartition = FALSE; ++ BlockMedia.ReadOnly = FALSE; ++ BlockMedia.WriteCaching = FALSE; ++ BlockMedia.BlockSize = 512; ++ BlockMedia.IoAlign = 1; ++ BlockMedia.LastBlock = 0; ++ ++ // Generate EFI_BLOCK_IO_PROTOCOL test data ++ BlockIo.Revision = 1; ++ BlockIo.Media = &BlockMedia; ++ BlockIo.Reset = NULL; ++ BlockIo.ReadBlocks = NULL; ++ BlockIo.WriteBlocks = NULL; ++ BlockIo.FlushBlocks = NULL; ++ ++ // Geneate EFI_PARTITION_TABLE_HEADER test data ++ PrimaryHeader.Header.Signature = EFI_PTAB_HEADER_ID; ++ PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION; ++ PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); ++ PrimaryHeader.MyLBA = 1; ++ PrimaryHeader.AlternateLBA = 2; ++ PrimaryHeader.FirstUsableLBA = 3; ++ PrimaryHeader.LastUsableLBA = 4; ++ PrimaryHeader.PartitionEntryLBA = 5; ++ PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES; ++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; ++ PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid ++ ++ // Calculate the CRC32 of the PrimaryHeader ++ PrimaryHeader.Header.CRC32 = CalculateCrc32 ((UINT8 *)&PrimaryHeader, PrimaryHeader.Header.HeaderSize); ++ ++ // Test that a normal PrimaryHeader passes validation ++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ UT_ASSERT_NOT_EFI_ERROR (Status); ++ ++ // Test that when number of partition entries is 0, the function returns EFI_DEVICE_ERROR ++ // Should print "Invalid Partition Table Header NumberOfPartitionEntries!"" ++ PrimaryHeader.NumberOfPartitionEntries = 0; ++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); ++ PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; ++ ++ // Test that when the header size is too small, the function returns EFI_DEVICE_ERROR ++ // Should print "Invalid Partition Table Header Size!" ++ PrimaryHeader.Header.HeaderSize = 0; ++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); ++ PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER); ++ ++ // Test that when the SizeOfPartitionEntry is too small, the function returns EFI_DEVICE_ERROR ++ // should print: "SizeOfPartitionEntry shall be set to a value of 128 x 2^n where n is an integer greater than or equal to zero (e.g., 128, 256, 512, etc.)!" ++ PrimaryHeader.SizeOfPartitionEntry = 1; ++ Status = SanitizeEfiPartitionTableHeader (&PrimaryHeader, &BlockIo); ++ UT_ASSERT_EQUAL (Status, EFI_DEVICE_ERROR); ++ ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); ++ ++ return UNIT_TEST_PASSED; ++} ++ ++/** ++ This function tests the SanitizePrimaryHeaderAllocationSize function. ++ It's intent is to test that the untrusted input from a EFI_PARTITION_TABLE_HEADER ++ structure will not cause an overflow when calculating the allocation size. ++ ++ @param[in] Context The unit test context. ++ ++ @retval UNIT_TEST_PASSED The test passed. ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. ++**/ ++UNIT_TEST_STATUS ++EFIAPI ++TestSanitizePrimaryHeaderAllocationSize ( ++ IN UNIT_TEST_CONTEXT Context ++ ) ++{ ++ UINT32 AllocationSize; ++ ++ EFI_STATUS Status; ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; ++ ++ // Test that a normal PrimaryHeader passes validation ++ PrimaryHeader.NumberOfPartitionEntries = 5; ++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; ++ ++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ UT_ASSERT_NOT_EFI_ERROR (Status); ++ ++ // Test that the allocation size is correct compared to the existing logic ++ UT_ASSERT_EQUAL (AllocationSize, PrimaryHeader.NumberOfPartitionEntries * PrimaryHeader.SizeOfPartitionEntry); ++ ++ // Test that an overflow is detected ++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; ++ PrimaryHeader.SizeOfPartitionEntry = 5; ++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); ++ ++ // Test the inverse ++ PrimaryHeader.NumberOfPartitionEntries = 5; ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; ++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); ++ ++ // Test the worst case scenario ++ PrimaryHeader.NumberOfPartitionEntries = MAX_UINT32; ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; ++ Status = SanitizePrimaryHeaderAllocationSize (&PrimaryHeader, &AllocationSize); ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); ++ ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); ++ ++ return UNIT_TEST_PASSED; ++} ++ ++/** ++ This function tests the SanitizePrimaryHeaderGptEventSize function. ++ It's intent is to test that the untrusted input from a EFI_GPT_DATA structure ++ will not cause an overflow when calculating the event size. ++ ++ @param[in] Context The unit test context. ++ ++ @retval UNIT_TEST_PASSED The test passed. ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. ++**/ ++UNIT_TEST_STATUS ++EFIAPI ++TestSanitizePrimaryHeaderGptEventSize ( ++ IN UNIT_TEST_CONTEXT Context ++ ) ++{ ++ UINT32 EventSize; ++ UINT32 ExistingLogicEventSize; ++ EFI_STATUS Status; ++ EFI_PARTITION_TABLE_HEADER PrimaryHeader; ++ UINTN NumberOfPartition; ++ EFI_GPT_DATA *GptData; ++ ++ GptData = NULL; ++ ++ // Test that a normal PrimaryHeader passes validation ++ PrimaryHeader.NumberOfPartitionEntries = 5; ++ PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY; ++ ++ // set the number of partitions ++ NumberOfPartition = 13; ++ ++ // that the primary event size is correct ++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); ++ UT_ASSERT_NOT_EFI_ERROR (Status); ++ ++ // Calculate the existing logic event size ++ ExistingLogicEventSize = (UINT32)(sizeof (TCG_PCR_EVENT_HDR) + OFFSET_OF (EFI_GPT_DATA, Partitions) ++ + NumberOfPartition * PrimaryHeader.SizeOfPartitionEntry); ++ ++ // Check that the event size is correct ++ UT_ASSERT_EQUAL (EventSize, ExistingLogicEventSize); ++ ++ // Tests that the primary event size may not overflow ++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, MAX_UINT32, &EventSize); ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); ++ ++ // Test that the size of partition entries may not overflow ++ PrimaryHeader.SizeOfPartitionEntry = MAX_UINT32; ++ Status = SanitizePrimaryHeaderGptEventSize (&PrimaryHeader, NumberOfPartition, &EventSize); ++ UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE); ++ ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); ++ ++ return UNIT_TEST_PASSED; ++} ++ ++// *--------------------------------------------------------------------* ++// * Unit Test Code Main Function ++// *--------------------------------------------------------------------* ++ ++/** ++ This function acts as the entry point for the unit tests. ++ ++ @param argc - The number of command line arguments ++ @param argv - The command line arguments ++ ++ @return int - The status of the test ++**/ ++EFI_STATUS ++EFIAPI ++UefiTestMain ( ++ VOID ++ ) ++{ ++ EFI_STATUS Status; ++ UNIT_TEST_FRAMEWORK_HANDLE Framework; ++ UNIT_TEST_SUITE_HANDLE TcgMeasureBootLibValidationTestSuite; ++ ++ Framework = NULL; ++ ++ DEBUG ((DEBUG_INFO, "%a: TestMain() - Start\n", UNIT_TEST_NAME)); ++ ++ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a: Failed in InitUnitTestFramework. Status = %r\n", UNIT_TEST_NAME, Status)); ++ goto EXIT; ++ } ++ ++ Status = CreateUnitTestSuite (&TcgMeasureBootLibValidationTestSuite, Framework, "TcgMeasureBootLibValidationTestSuite", "Common.TcgMeasureBootLibValidation", NULL, NULL); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%s: Failed in CreateUnitTestSuite for TcgMeasureBootLibValidationTestSuite\n", UNIT_TEST_NAME)); ++ Status = EFI_OUT_OF_RESOURCES; ++ goto EXIT; ++ } ++ ++ // -----------Suite---------------------------------Description----------------------------Class----------------------------------Test Function------------------------Pre---Clean-Context ++ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.TcgMeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL); ++ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL); ++ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL); ++ ++ Status = RunAllTestSuites (Framework); ++ ++EXIT: ++ if (Framework != NULL) { ++ FreeUnitTestFramework (Framework); ++ } ++ ++ DEBUG ((DEBUG_INFO, "%a: TestMain() - End\n", UNIT_TEST_NAME)); ++ return Status; ++} ++ ++/// ++/// Avoid ECC error for function name that starts with lower case letter ++/// ++#define DxeTpmMeasureBootLibUnitTestMain main ++ ++/** ++ Standard POSIX C entry point for host based unit test execution. ++ ++ @param[in] Argc Number of arguments ++ @param[in] Argv Array of pointers to arguments ++ ++ @retval 0 Success ++ @retval other Error ++**/ ++INT32 ++DxeTpmMeasureBootLibUnitTestMain ( ++ IN INT32 Argc, ++ IN CHAR8 *Argv[] ++ ) ++{ ++ return (INT32)UefiTestMain (); ++} +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf +new file mode 100644 +index 0000000000..47b0811b00 +--- /dev/null ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf +@@ -0,0 +1,28 @@ ++## @file ++# This file builds the unit tests for DxeTpmMeasureBootLib ++# ++# Copyright (C) Microsoft Corporation.
++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++ ++[Defines] ++ INF_VERSION = 0x00010006 ++ BASE_NAME = DxeTpmMeasuredBootLibTest ++ FILE_GUID = eb01bc38-309c-4d3e-967e-9f078c90772f ++ MODULE_TYPE = HOST_APPLICATION ++ VERSION_STRING = 1.0 ++ ENTRY_POINT = main ++ ++[Sources] ++ DxeTpmMeasureBootLibSanitizationTest.c ++ ../DxeTpmMeasureBootLibSanitization.c ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ ++[LibraryClasses] ++ BaseLib ++ DebugLib ++ UnitTestLib ++ PrintLib ++ SafeIntLib +diff --git a/SecurityPkg/SecurityPkg.ci.yaml b/SecurityPkg/SecurityPkg.ci.yaml +index aa8496d6d9..26865cb15a 100644 +--- a/SecurityPkg/SecurityPkg.ci.yaml ++++ b/SecurityPkg/SecurityPkg.ci.yaml +@@ -17,6 +17,7 @@ + "ExceptionList": [ + "8005", "gRT", + "8001", "DxeTpm2MeasureBootLibUnitTestMain", ++ "8001", "DxeTpmMeasureBootLibUnitTestMain" + ], + ## Both file path and directory path are accepted. + "IgnoreFiles": [ +diff --git a/SecurityPkg/Test/SecurityPkgHostTest.dsc b/SecurityPkg/Test/SecurityPkgHostTest.dsc +index 788c1ab6fe..1655e573ea 100644 +--- a/SecurityPkg/Test/SecurityPkgHostTest.dsc ++++ b/SecurityPkg/Test/SecurityPkgHostTest.dsc +@@ -27,6 +27,7 @@ + SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiLib.inf + SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf + SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTestHost.inf ++ SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTestHost.inf + + # + # Build SecurityPkg HOST_APPLICATION Tests +-- +2.41.0 + diff --git a/edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4118.patch b/edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4118.patch new file mode 100644 index 0000000..8586c39 --- /dev/null +++ b/edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4118.patch @@ -0,0 +1,307 @@ +From f6f72373630d901f331df719a0fb55e8f1143c4f Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 7 Feb 2024 15:43:10 -0500 +Subject: [PATCH 10/17] SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4118 + - CVE 2022-36764 + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [10/13] 5ed702e16f390c79d1abb0ec0b04d886e0094c0b (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21156 +CVE: CVE-2022-36764 +Upstream: Merged +Conflicts: We get function definiton clash for the following three functions: + - SanitizePeImageEventSize() + This is defined both in + - SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitazion.c + and + - SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitazion.c + Closer investigation reveals that they are identical in functionality (although + not in comment style). + I chose to leave them as is now, meaning that this package will be + unbuildable until I add a commit renaming these symbols later in + this series. + +commit 0d341c01eeabe0ab5e76693b36e728b8f538a40e +Author: Douglas Flick [MSFT] +Date: Fri Jan 12 02:16:05 2024 +0800 + + SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764 + + This commit contains the patch files and tests for DxeTpmMeasureBootLib + CVE 2022-36764. + + Cc: Jiewen Yao + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Jiewen Yao + +Signed-off-by: Jon Maloy +--- + .../DxeTpmMeasureBootLib.c | 17 ++-- + .../DxeTpmMeasureBootLibSanitization.c | 44 +++++++++ + .../DxeTpmMeasureBootLibSanitization.h | 23 +++++ + .../DxeTpmMeasureBootLibSanitizationTest.c | 98 +++++++++++++++++-- + 4 files changed, 170 insertions(+), 12 deletions(-) + +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +index d44422dee8..1598015176 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c +@@ -17,6 +17,7 @@ + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent ++Copyright (c) Microsoft Corporation.
+ + Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +@@ -338,19 +339,23 @@ TcgMeasurePeImage ( + ImageLoad = NULL; + SectionHeader = NULL; + Sha1Ctx = NULL; +- FilePathSize = (UINT32) GetDevicePathSize (FilePath); ++ TcgEvent = NULL; ++ FilePathSize = (UINT32)GetDevicePathSize (FilePath); + +- // + // Determine destination PCR by BootPolicy + // +- EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize; +- TcgEvent = AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT)); ++ Status = SanitizePeImageEventSize (FilePathSize, &EventSize); ++ if (EFI_ERROR (Status)) { ++ return EFI_UNSUPPORTED; ++ } ++ ++ TcgEvent = AllocateZeroPool (EventSize); + if (TcgEvent == NULL) { + return EFI_OUT_OF_RESOURCES; + } + +- TcgEvent->EventSize = EventSize; +- ImageLoad = (EFI_IMAGE_LOAD_EVENT *) TcgEvent->Event; ++ TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR); ++ ImageLoad = (EFI_IMAGE_LOAD_EVENT *)TcgEvent->Event; + + switch (ImageType) { + case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION: +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c +index 37cd3ed0ea..bcf8c6de6f 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c +@@ -240,3 +240,47 @@ SanitizePrimaryHeaderGptEventSize ( + return EFI_SUCCESS; + } + ++/** ++ This function will validate that the PeImage Event Size from the loaded image is sane ++ It will check the following: ++ - EventSize does not overflow ++ ++ @param[in] FilePathSize - Size of the file path. ++ @param[out] EventSize - Pointer to the event size. ++ ++ @retval EFI_SUCCESS ++ The event size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ Overflow would have occurred. ++ ++ @retval EFI_INVALID_PARAMETER ++ One of the passed parameters was invalid. ++**/ ++EFI_STATUS ++SanitizePeImageEventSize ( ++ IN UINT32 FilePathSize, ++ OUT UINT32 *EventSize ++ ) ++{ ++ EFI_STATUS Status; ++ ++ // Replacing logic: ++ // sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize; ++ Status = SafeUint32Add (OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath), FilePathSize, EventSize); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n")); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ // Replacing logic: ++ // EventSize + sizeof (TCG_PCR_EVENT_HDR) ++ Status = SafeUint32Add (*EventSize, sizeof (TCG_PCR_EVENT_HDR), EventSize); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n")); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ ++ return EFI_SUCCESS; ++} ++ +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h +index 0d9d00c281..2248495813 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h +@@ -111,4 +111,27 @@ SanitizePrimaryHeaderGptEventSize ( + OUT UINT32 *EventSize + ); + ++/** ++ This function will validate that the PeImage Event Size from the loaded image is sane ++ It will check the following: ++ - EventSize does not overflow ++ ++ @param[in] FilePathSize - Size of the file path. ++ @param[out] EventSize - Pointer to the event size. ++ ++ @retval EFI_SUCCESS ++ The event size is valid. ++ ++ @retval EFI_OUT_OF_RESOURCES ++ Overflow would have occurred. ++ ++ @retval EFI_INVALID_PARAMETER ++ One of the passed parameters was invalid. ++**/ ++EFI_STATUS ++SanitizePeImageEventSize ( ++ IN UINT32 FilePathSize, ++ OUT UINT32 *EventSize ++ ); ++ + #endif // DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_ +diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c +index eeb928cdb0..c41498be45 100644 +--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c ++++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c +@@ -1,8 +1,8 @@ + /** @file +-This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c. ++ This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c. + +-Copyright (c) Microsoft Corporation.
+-SPDX-License-Identifier: BSD-2-Clause-Patent ++ Copyright (c) Microsoft Corporation.
++ SPDX-License-Identifier: BSD-2-Clause-Patent + **/ + + #include +@@ -186,9 +186,6 @@ TestSanitizePrimaryHeaderGptEventSize ( + EFI_STATUS Status; + EFI_PARTITION_TABLE_HEADER PrimaryHeader; + UINTN NumberOfPartition; +- EFI_GPT_DATA *GptData; +- +- GptData = NULL; + + // Test that a normal PrimaryHeader passes validation + PrimaryHeader.NumberOfPartitionEntries = 5; +@@ -222,6 +219,94 @@ TestSanitizePrimaryHeaderGptEventSize ( + return UNIT_TEST_PASSED; + } + ++/** ++ This function tests the SanitizePeImageEventSize function. ++ It's intent is to test that the untrusted input from a file path for an ++ EFI_IMAGE_LOAD_EVENT structure will not cause an overflow when calculating ++ the event size when allocating space. ++ ++ @param[in] Context The unit test context. ++ ++ @retval UNIT_TEST_PASSED The test passed. ++ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed. ++**/ ++UNIT_TEST_STATUS ++EFIAPI ++TestSanitizePeImageEventSize ( ++ IN UNIT_TEST_CONTEXT Context ++ ) ++{ ++ UINT32 EventSize; ++ UINTN ExistingLogicEventSize; ++ UINT32 FilePathSize; ++ EFI_STATUS Status; ++ EFI_DEVICE_PATH_PROTOCOL DevicePath; ++ EFI_IMAGE_LOAD_EVENT *ImageLoadEvent; ++ UNIT_TEST_STATUS TestStatus; ++ ++ TestStatus = UNIT_TEST_ERROR_TEST_FAILED; ++ ++ // Generate EFI_DEVICE_PATH_PROTOCOL test data ++ DevicePath.Type = 0; ++ DevicePath.SubType = 0; ++ DevicePath.Length[0] = 0; ++ DevicePath.Length[1] = 0; ++ ++ // Generate EFI_IMAGE_LOAD_EVENT test data ++ ImageLoadEvent = AllocateZeroPool (sizeof (EFI_IMAGE_LOAD_EVENT) + sizeof (EFI_DEVICE_PATH_PROTOCOL)); ++ if (ImageLoadEvent == NULL) { ++ DEBUG ((DEBUG_ERROR, "%a: AllocateZeroPool failed\n", __func__)); ++ goto Exit; ++ } ++ ++ // Populate EFI_IMAGE_LOAD_EVENT54 test data ++ ImageLoadEvent->ImageLocationInMemory = (EFI_PHYSICAL_ADDRESS)0x12345678; ++ ImageLoadEvent->ImageLengthInMemory = 0x1000; ++ ImageLoadEvent->ImageLinkTimeAddress = (UINTN)ImageLoadEvent; ++ ImageLoadEvent->LengthOfDevicePath = sizeof (EFI_DEVICE_PATH_PROTOCOL); ++ CopyMem (ImageLoadEvent->DevicePath, &DevicePath, sizeof (EFI_DEVICE_PATH_PROTOCOL)); ++ ++ FilePathSize = 255; ++ ++ // Test that a normal PE image passes validation ++ Status = SanitizePeImageEventSize (FilePathSize, &EventSize); ++ if (EFI_ERROR (Status)) { ++ UT_LOG_ERROR ("SanitizePeImageEventSize failed with %r\n", Status); ++ goto Exit; ++ } ++ ++ // Test that the event size is correct compared to the existing logic ++ ExistingLogicEventSize = OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath) + FilePathSize; ++ ExistingLogicEventSize += sizeof (TCG_PCR_EVENT_HDR); ++ ++ if (EventSize != ExistingLogicEventSize) { ++ UT_LOG_ERROR ("SanitizePeImageEventSize returned an incorrect event size. Expected %u, got %u\n", ExistingLogicEventSize, EventSize); ++ goto Exit; ++ } ++ ++ // Test that the event size may not overflow ++ Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize); ++ if (Status != EFI_BAD_BUFFER_SIZE) { ++ UT_LOG_ERROR ("SanitizePeImageEventSize succeded when it was supposed to fail with %r\n", Status); ++ goto Exit; ++ } ++ ++ TestStatus = UNIT_TEST_PASSED; ++Exit: ++ ++ if (ImageLoadEvent != NULL) { ++ FreePool (ImageLoadEvent); ++ } ++ ++ if (TestStatus == UNIT_TEST_ERROR_TEST_FAILED) { ++ DEBUG ((DEBUG_ERROR, "%a: Test failed\n", __func__)); ++ } else { ++ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__)); ++ } ++ ++ return TestStatus; ++} ++ + // *--------------------------------------------------------------------* + // * Unit Test Code Main Function + // *--------------------------------------------------------------------* +@@ -265,6 +350,7 @@ UefiTestMain ( + AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.TcgMeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL); + AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL); + AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL); ++ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests PE Image and FileSize checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePeImageEventSize, NULL, NULL, NULL); + + Status = RunAllTestSuites (Framework); + +-- +2.41.0 + diff --git a/edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpm2.patch b/edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpm2.patch new file mode 100644 index 0000000..2ee9f81 --- /dev/null +++ b/edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpm2.patch @@ -0,0 +1,584 @@ +From e138f66708415704ad1133938c0dce5243795656 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 13 Feb 2024 16:30:10 -0500 +Subject: [PATCH 04/17] SecurityPkg: Support CcMeasurementProtocol in + DxeTpm2MeasureBootLib + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [4/13] 8038fb605dbdaccfd40cb9d9d56db559ee9df639 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21154 +CVE: CVE-2022-36763 +Upstream: Merged +Conflicts: Only cosmetic, due to the uncrustify changes made + in the newer version. + +commit a124cd4ef92a349a6c823ea6701fcfd3a17db255 +Author: Min Xu +Date: Sat Dec 11 21:08:41 2021 +0800 + + SecurityPkg: Support CcMeasurementProtocol in DxeTpm2MeasureBootLib + + BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3625 + + DxeTpm2MeasureBootLib supports TPM2 based measure boot. After + CcMeasurementProtocol is introduced, CC based measure boot needs to + be supported in DxeTpm2MeasureBootLib as well. + + There are 2 major changes in this commit. + + 1. A platform should have only one RTS/RTR. Only one of (virtual)TPM1.2, + (virtual)TPM2.0 and CC MR exists. Then only one TCG_SERVICE_PROTOCOL, + TCG2_PROTOCOL, CC_MEASUREMENT_PROTOCOL is exposed. In this library when + do measure boot only one of TCG2_PROTOCOL / CC_MEASUREMENT_PROTOCOL + will be called. MEASURE_BOOT_PROTOCOLS is defined to store the instances + of TCG2 protocol and CC Measurement protocol. + + 2. CcEvent is similar to Tcg2Event except the MrIndex and PcrIndex. + So in the code Tcg2Event will be first created and intialized. If + CcMeasurementProtocol is called to do the measure boot, then CcEvent + points to Tcg2Event and the MrIndex is adjusted. + + Cc: Michael D Kinney + Cc: Liming Gao + Cc: Zhiguang Liu + Cc: Jiewen Yao + Cc: Jian J Wang + Cc: Sami Mujawar + Cc: Gerd Hoffmann + Reviewed-by: Sami Mujawar + Reviewed-by: Jiewen Yao + Signed-off-by: Min Xu + +Signed-off-by: Jon Maloy +--- + .../DxeTpm2MeasureBootLib.c | 347 ++++++++++++++---- + .../DxeTpm2MeasureBootLib.inf | 3 +- + 2 files changed, 271 insertions(+), 79 deletions(-) + +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +index 95682ac567..7abacdbc0a 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c +@@ -1,5 +1,6 @@ + /** @file +- The library instance provides security service of TPM2 measure boot. ++ The library instance provides security service of TPM2 measure boot and ++ Confidential Computing (CC) measure boot. + + Caution: This file requires additional review when modified. + This library will have external input - PE/COFF image and GPT partition. +@@ -41,6 +42,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + #include + #include + #include ++#include ++ ++typedef struct { ++ EFI_TCG2_PROTOCOL *Tcg2Protocol; ++ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; ++} MEASURE_BOOT_PROTOCOLS; + + // + // Flag to check GPT partition. It only need be measured once. +@@ -109,7 +116,7 @@ DxeTpm2MeasureBootLibImageRead ( + Caution: This function may receive untrusted input. + The GPT partition table is external input, so this function should parse partition data carefully. + +- @param Tcg2Protocol Pointer to the located TCG2 protocol instance. ++ @param MeasureBootProtocols Pointer to the located MeasureBoot protocol instances (i.e. TCG2/CC protocol). + @param GptHandle Handle that GPT partition was installed. + + @retval EFI_SUCCESS Successfully measure GPT table. +@@ -121,26 +128,48 @@ DxeTpm2MeasureBootLibImageRead ( + EFI_STATUS + EFIAPI + Tcg2MeasureGptTable ( +- IN EFI_TCG2_PROTOCOL *Tcg2Protocol, +- IN EFI_HANDLE GptHandle ++ IN MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols, ++ IN EFI_HANDLE GptHandle + ) + { +- EFI_STATUS Status; +- EFI_BLOCK_IO_PROTOCOL *BlockIo; +- EFI_DISK_IO_PROTOCOL *DiskIo; +- EFI_PARTITION_TABLE_HEADER *PrimaryHeader; +- EFI_PARTITION_ENTRY *PartitionEntry; +- UINT8 *EntryPtr; +- UINTN NumberOfPartition; +- UINT32 Index; +- EFI_TCG2_EVENT *Tcg2Event; +- EFI_GPT_DATA *GptData; +- UINT32 EventSize; ++ EFI_STATUS Status; ++ EFI_BLOCK_IO_PROTOCOL *BlockIo; ++ EFI_DISK_IO_PROTOCOL *DiskIo; ++ EFI_PARTITION_TABLE_HEADER *PrimaryHeader; ++ EFI_PARTITION_ENTRY *PartitionEntry; ++ UINT8 *EntryPtr; ++ UINTN NumberOfPartition; ++ UINT32 Index; ++ UINT8 *EventPtr; ++ EFI_TCG2_EVENT *Tcg2Event; ++ EFI_CC_EVENT *CcEvent; ++ EFI_GPT_DATA *GptData; ++ UINT32 EventSize; ++ EFI_TCG2_PROTOCOL *Tcg2Protocol; ++ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; ++ EFI_CC_MR_INDEX MrIndex; + + if (mTcg2MeasureGptCount > 0) { + return EFI_SUCCESS; + } + ++ PrimaryHeader = NULL; ++ EntryPtr = NULL; ++ EventPtr = NULL; ++ ++ Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol; ++ CcProtocol = MeasureBootProtocols->CcProtocol; ++ ++ if ((Tcg2Protocol == NULL) && (CcProtocol == NULL)) { ++ ASSERT (FALSE); ++ return EFI_UNSUPPORTED; ++ } ++ ++ if (sizeof (EFI_CC_EVENT) != sizeof (EFI_TCG2_EVENT)) { ++ ASSERT (FALSE); ++ return EFI_UNSUPPORTED; ++ } ++ + Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; +@@ -168,6 +197,16 @@ Tcg2MeasureGptTable ( + FreePool (PrimaryHeader); + return EFI_DEVICE_ERROR; + } ++ ++ // ++ // PrimaryHeader->SizeOfPartitionEntry should not be zero ++ // ++ if (PrimaryHeader->SizeOfPartitionEntry == 0) { ++ DEBUG ((DEBUG_ERROR, "SizeOfPartitionEntry should not be zero!\n")); ++ FreePool (PrimaryHeader); ++ return EFI_BAD_BUFFER_SIZE; ++ } ++ + // + // Read the partition entry. + // +@@ -202,11 +241,17 @@ Tcg2MeasureGptTable ( + } + + // +- // Prepare Data for Measurement ++ // Prepare Data for Measurement (CcProtocol and Tcg2Protocol) + // + EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry); +- Tcg2Event = (EFI_TCG2_EVENT *) AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event)); ++ EventPtr = (UINT8 *)AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)); ++ if (EventPtr == NULL) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto Exit; ++ } ++ ++ Tcg2Event = (EFI_TCG2_EVENT *)EventPtr; + if (Tcg2Event == NULL) { + FreePool (PrimaryHeader); + FreePool (EntryPtr); +@@ -243,22 +288,66 @@ Tcg2MeasureGptTable ( + } + + // +- // Measure the GPT data ++ // Only one of TCG2_PROTOCOL or CC_MEASUREMENT_PROTOCOL is exposed. ++ // So Measure the GPT data with one of the protocol. + // +- Status = Tcg2Protocol->HashLogExtendEvent ( +- Tcg2Protocol, +- 0, +- (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) GptData, +- (UINT64) EventSize, +- Tcg2Event +- ); +- if (!EFI_ERROR (Status)) { +- mTcg2MeasureGptCount++; ++ if (CcProtocol != NULL) { ++ // ++ // EFI_CC_EVENT share the same data structure with EFI_TCG2_EVENT ++ // except the MrIndex and PCRIndex in Header. ++ // Tcg2Event has been created and initialized before. So only the MrIndex need ++ // be adjusted. ++ // ++ Status = CcProtocol->MapPcrToMrIndex (CcProtocol, Tcg2Event->Header.PCRIndex, &MrIndex); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "Cannot map PcrIndex(%d) to MrIndex\n", Tcg2Event->Header.PCRIndex)); ++ goto Exit; ++ } ++ ++ CcEvent = (EFI_CC_EVENT *)EventPtr; ++ CcEvent->Header.MrIndex = MrIndex; ++ Status = CcProtocol->HashLogExtendEvent ( ++ CcProtocol, ++ 0, ++ (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData, ++ (UINT64)EventSize, ++ CcEvent ++ ); ++ if (!EFI_ERROR (Status)) { ++ mTcg2MeasureGptCount++; ++ } ++ ++ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Cc MeasureGptTable - %r\n", Status)); ++ } else if (Tcg2Protocol != NULL) { ++ // ++ // If Tcg2Protocol is installed, then Measure GPT data with this protocol. ++ // ++ Status = Tcg2Protocol->HashLogExtendEvent ( ++ Tcg2Protocol, ++ 0, ++ (EFI_PHYSICAL_ADDRESS)(UINTN)(VOID *)GptData, ++ (UINT64)EventSize, ++ Tcg2Event ++ ); ++ if (!EFI_ERROR (Status)) { ++ mTcg2MeasureGptCount++; ++ } ++ ++ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2 MeasureGptTable - %r\n", Status)); + } + +- FreePool (PrimaryHeader); +- FreePool (EntryPtr); +- FreePool (Tcg2Event); ++Exit: ++ if (PrimaryHeader != NULL) { ++ FreePool (PrimaryHeader); ++ } ++ ++ if (EntryPtr != NULL) { ++ FreePool (EntryPtr); ++ } ++ ++ if (EventPtr != NULL) { ++ FreePool (EventPtr); ++ } + + return Status; + } +@@ -271,12 +360,12 @@ Tcg2MeasureGptTable ( + PE/COFF image is external input, so this function will validate its data structure + within this image buffer before use. + +- @param[in] Tcg2Protocol Pointer to the located TCG2 protocol instance. +- @param[in] ImageAddress Start address of image buffer. +- @param[in] ImageSize Image size +- @param[in] LinkTimeBase Address that the image is loaded into memory. +- @param[in] ImageType Image subsystem type. +- @param[in] FilePath File path is corresponding to the input image. ++ @param[in] MeasureBootProtocols Pointer to the located MeasureBoot protocol instances. ++ @param[in] ImageAddress Start address of image buffer. ++ @param[in] ImageSize Image size ++ @param[in] LinkTimeBase Address that the image is loaded into memory. ++ @param[in] ImageType Image subsystem type. ++ @param[in] FilePath File path is corresponding to the input image. + + @retval EFI_SUCCESS Successfully measure image. + @retval EFI_OUT_OF_RESOURCES No enough resource to measure image. +@@ -287,7 +376,7 @@ Tcg2MeasureGptTable ( + EFI_STATUS + EFIAPI + Tcg2MeasurePeImage ( +- IN EFI_TCG2_PROTOCOL *Tcg2Protocol, ++ IN MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols, + IN EFI_PHYSICAL_ADDRESS ImageAddress, + IN UINTN ImageSize, + IN UINTN LinkTimeBase, +@@ -295,26 +384,46 @@ Tcg2MeasurePeImage ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ) + { +- EFI_STATUS Status; +- EFI_TCG2_EVENT *Tcg2Event; +- EFI_IMAGE_LOAD_EVENT *ImageLoad; +- UINT32 FilePathSize; +- UINT32 EventSize; ++ EFI_STATUS Status; ++ EFI_TCG2_EVENT *Tcg2Event; ++ EFI_IMAGE_LOAD_EVENT *ImageLoad; ++ UINT32 FilePathSize; ++ UINT32 EventSize; ++ EFI_CC_EVENT *CcEvent; ++ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; ++ EFI_TCG2_PROTOCOL *Tcg2Protocol; ++ UINT8 *EventPtr; ++ EFI_CC_MR_INDEX MrIndex; ++ ++ Status = EFI_UNSUPPORTED; ++ ImageLoad = NULL; ++ EventPtr = NULL; ++ ++ Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol; ++ CcProtocol = MeasureBootProtocols->CcProtocol; ++ ++ if ((Tcg2Protocol == NULL) && (CcProtocol == NULL)) { ++ ASSERT (FALSE); ++ return EFI_UNSUPPORTED; ++ } ++ ++ if (sizeof (EFI_CC_EVENT) != sizeof (EFI_TCG2_EVENT)) { ++ ASSERT (FALSE); ++ return EFI_UNSUPPORTED; ++ } + +- Status = EFI_UNSUPPORTED; +- ImageLoad = NULL; + FilePathSize = (UINT32) GetDevicePathSize (FilePath); + + // + // Determine destination PCR by BootPolicy + // + EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize; +- Tcg2Event = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event)); +- if (Tcg2Event == NULL) { ++ EventPtr = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)); ++ if (EventPtr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + +- Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof(Tcg2Event->Event); ++ Tcg2Event = (EFI_TCG2_EVENT *)EventPtr; + Tcg2Event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER); + Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION; + ImageLoad = (EFI_IMAGE_LOAD_EVENT *) Tcg2Event->Event; +@@ -352,13 +461,35 @@ Tcg2MeasurePeImage ( + // + // Log the PE data + // +- Status = Tcg2Protocol->HashLogExtendEvent ( +- Tcg2Protocol, +- PE_COFF_IMAGE, +- ImageAddress, +- ImageSize, +- Tcg2Event +- ); ++ if (CcProtocol != NULL) { ++ Status = CcProtocol->MapPcrToMrIndex (CcProtocol, Tcg2Event->Header.PCRIndex, &MrIndex); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "Cannot map PcrIndex(%d) to MrIndex\n", Tcg2Event->Header.PCRIndex)); ++ goto Finish; ++ } ++ ++ CcEvent = (EFI_CC_EVENT *)EventPtr; ++ CcEvent->Header.MrIndex = MrIndex; ++ ++ Status = CcProtocol->HashLogExtendEvent ( ++ CcProtocol, ++ PE_COFF_IMAGE, ++ ImageAddress, ++ ImageSize, ++ CcEvent ++ ); ++ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Cc MeasurePeImage - %r\n", Status)); ++ } else if (Tcg2Protocol != NULL) { ++ Status = Tcg2Protocol->HashLogExtendEvent ( ++ Tcg2Protocol, ++ PE_COFF_IMAGE, ++ ImageAddress, ++ ImageSize, ++ Tcg2Event ++ ); ++ DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2 MeasurePeImage - %r\n", Status)); ++ } ++ + if (Status == EFI_VOLUME_FULL) { + // + // Volume full here means the image is hashed and its result is extended to PCR. +@@ -369,11 +500,77 @@ Tcg2MeasurePeImage ( + } + + Finish: +- FreePool (Tcg2Event); ++ if (EventPtr != NULL) { ++ FreePool (EventPtr); ++ } + + return Status; + } + ++/** ++ Get the measure boot protocols. ++ ++ There are 2 measure boot, TCG2 protocol based and Cc measurement protocol based. ++ ++ @param MeasureBootProtocols Pointer to the located measure boot protocol instances. ++ ++ @retval EFI_SUCCESS Sucessfully locate the measure boot protocol instances (at least one instance). ++ @retval EFI_UNSUPPORTED Measure boot is not supported. ++**/ ++EFI_STATUS ++EFIAPI ++GetMeasureBootProtocols ( ++ MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_TCG2_PROTOCOL *Tcg2Protocol; ++ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; ++ EFI_TCG2_BOOT_SERVICE_CAPABILITY Tcg2ProtocolCapability; ++ EFI_CC_BOOT_SERVICE_CAPABILITY CcProtocolCapability; ++ ++ CcProtocol = NULL; ++ Status = gBS->LocateProtocol (&gEfiCcMeasurementProtocolGuid, NULL, (VOID **)&CcProtocol); ++ if (EFI_ERROR (Status)) { ++ // ++ // Cc Measurement protocol is not installed. ++ // ++ DEBUG ((DEBUG_VERBOSE, "CcMeasurementProtocol is not installed. - %r\n", Status)); ++ } else { ++ ZeroMem (&CcProtocolCapability, sizeof (CcProtocolCapability)); ++ CcProtocolCapability.Size = sizeof (CcProtocolCapability); ++ Status = CcProtocol->GetCapability (CcProtocol, &CcProtocolCapability); ++ if (EFI_ERROR (Status) || (CcProtocolCapability.CcType.Type == EFI_CC_TYPE_NONE)) { ++ DEBUG ((DEBUG_ERROR, " CcProtocol->GetCapability returns : %x, %r\n", CcProtocolCapability.CcType.Type, Status)); ++ CcProtocol = NULL; ++ } ++ } ++ ++ Tcg2Protocol = NULL; ++ Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol); ++ if (EFI_ERROR (Status)) { ++ // ++ // Tcg2 protocol is not installed. So, TPM2 is not present. ++ // ++ DEBUG ((DEBUG_VERBOSE, "Tcg2Protocol is not installed. - %r\n", Status)); ++ } else { ++ Tcg2ProtocolCapability.Size = (UINT8)sizeof (Tcg2ProtocolCapability); ++ Status = Tcg2Protocol->GetCapability (Tcg2Protocol, &Tcg2ProtocolCapability); ++ if (EFI_ERROR (Status) || (!Tcg2ProtocolCapability.TPMPresentFlag)) { ++ // ++ // TPM device doesn't work or activate. ++ // ++ DEBUG ((DEBUG_ERROR, "TPMPresentFlag=FALSE %r\n", Status)); ++ Tcg2Protocol = NULL; ++ } ++ } ++ ++ MeasureBootProtocols->Tcg2Protocol = Tcg2Protocol; ++ MeasureBootProtocols->CcProtocol = CcProtocol; ++ ++ return (Tcg2Protocol == NULL && CcProtocol == NULL) ? EFI_UNSUPPORTED : EFI_SUCCESS; ++} ++ + /** + The security handler is used to abstract platform-specific policy + from the DXE core response to an attempt to use a file that returns a +@@ -422,9 +619,8 @@ DxeTpm2MeasureBootHandler ( + IN BOOLEAN BootPolicy + ) + { +- EFI_TCG2_PROTOCOL *Tcg2Protocol; ++ MEASURE_BOOT_PROTOCOLS MeasureBootProtocols; + EFI_STATUS Status; +- EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability; + EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode; + EFI_HANDLE Handle; +@@ -435,29 +631,25 @@ DxeTpm2MeasureBootHandler ( + EFI_PHYSICAL_ADDRESS FvAddress; + UINT32 Index; + +- Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol); ++ MeasureBootProtocols.Tcg2Protocol = NULL; ++ MeasureBootProtocols.CcProtocol = NULL; ++ ++ Status = GetMeasureBootProtocols (&MeasureBootProtocols); ++ + if (EFI_ERROR (Status)) { + // +- // Tcg2 protocol is not installed. So, TPM2 is not present. ++ // None of Measured boot protocols (Tcg2, Cc) is installed. + // Don't do any measurement, and directly return EFI_SUCCESS. + // +- DEBUG ((DEBUG_VERBOSE, "DxeTpm2MeasureBootHandler - Tcg2 - %r\n", Status)); ++ DEBUG ((DEBUG_INFO, "None of Tcg2Protocol/CcMeasurementProtocol is installed.\n")); + return EFI_SUCCESS; + } +- +- ProtocolCapability.Size = (UINT8) sizeof (ProtocolCapability); +- Status = Tcg2Protocol->GetCapability ( +- Tcg2Protocol, +- &ProtocolCapability +- ); +- if (EFI_ERROR (Status) || (!ProtocolCapability.TPMPresentFlag)) { +- // +- // TPM device doesn't work or activate. +- // +- DEBUG ((DEBUG_ERROR, "DxeTpm2MeasureBootHandler (%r) - TPMPresentFlag - %x\n", Status, ProtocolCapability.TPMPresentFlag)); +- return EFI_SUCCESS; +- } +- ++ DEBUG (( ++ DEBUG_INFO, ++ "Tcg2Protocol = %p, CcMeasurementProtocol = %p\n", ++ MeasureBootProtocols.Tcg2Protocol, ++ MeasureBootProtocols.CcProtocol ++ )); + // + // Copy File Device Path + // +@@ -502,8 +694,8 @@ DxeTpm2MeasureBootHandler ( + // + // Measure GPT disk. + // +- Status = Tcg2MeasureGptTable (Tcg2Protocol, Handle); +- DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasureGptTable - %r\n", Status)); ++ Status = Tcg2MeasureGptTable (&MeasureBootProtocols, Handle); ++ + if (!EFI_ERROR (Status)) { + // + // GPT disk check done. +@@ -647,14 +839,13 @@ DxeTpm2MeasureBootHandler ( + // Measure PE image into TPM log. + // + Status = Tcg2MeasurePeImage ( +- Tcg2Protocol, ++ &MeasureBootProtocols, + (EFI_PHYSICAL_ADDRESS) (UINTN) FileBuffer, + FileSize, + (UINTN) ImageContext.ImageAddress, + ImageContext.ImageType, + DevicePathNode + ); +- DEBUG ((DEBUG_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasurePeImage - %r\n", Status)); + } + + // +diff --git a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf +index 2506abbe7c..6dca79a20c 100644 +--- a/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf ++++ b/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf +@@ -1,5 +1,5 @@ + ## @file +-# Provides security service for TPM 2.0 measured boot ++# Provides security service for TPM 2.0 measured boot and Confidential Computing measure boot. + # + # Spec Compliance Info: + # "TCG PC Client Platform Firmware Profile Specification for TPM Family 2.0 Level 00 Revision 1.03 v51" +@@ -61,6 +61,7 @@ + + [Protocols] + gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES ++ gEfiCcMeasurementProtocolGuid ## SOMETIMES_CONSUMES + gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiDiskIoProtocolGuid ## SOMETIMES_CONSUMES +-- +2.41.0 + diff --git a/edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpmM.patch b/edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpmM.patch new file mode 100644 index 0000000..9764d7f --- /dev/null +++ b/edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpmM.patch @@ -0,0 +1,255 @@ +From a35a08c5c8d9308ba2b63a15a40e4ddc3e265dbd Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 13 Feb 2024 16:30:10 -0500 +Subject: [PATCH 05/17] SecurityPkg: Support CcMeasurementProtocol in + DxeTpmMeasurementLib + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [5/13] fa844740ca589cabb52ae7dfa0dd329315dc168f (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21154 +CVE: CVE-2022-36763 +Upstream: Merged +Conflicts: Only cosmetic, due to the uncrustify changes made + in the newer version. + +commit 314ff1dc8c9a9597280b50e44a5c861cb6a58517 (HEAD -> CVE-2022-36763_RHEL-21154_rhel-8.10.0) +Author: Min Xu +Date: Sat Dec 11 21:08:42 2021 +0800 + + SecurityPkg: Support CcMeasurementProtocol in DxeTpmMeasurementLib + + BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3625 + + DxeTpmMeasurementLib supports TPM based measurement in DXE phase. + After CcMeasurementProtocol is introduced, CC based measurement needs + to be supported in DxeTpmMeasurementLib as well. + + A platform should have only one RTS/RTR. Only one of (virtual)TPM1.2, + (virtual)TPM2.0 and CC MR exists. Then only one TCG_SERVICE_PROTOCOL, + TCG2_PROTOCOL, CC_MEASUREMENT_PROTOCOL is exposed. + + In this library when do measurement only one of above 3 protocols will + be called. + + Cc: Michael D Kinney + Cc: Liming Gao + Cc: Zhiguang Liu + Cc: Jiewen Yao + Cc: Jian J Wang + Cc: Sami Mujawar + Cc: Gerd Hoffmann + Reviewed-by: Sami Mujawar + Reviewed-by: Jiewen Yao + Signed-off-by: Min Xu + +Signed-off-by: Jon Maloy +--- + .../DxeTpmMeasurementLib.c | 122 +++++++++++++++--- + .../DxeTpmMeasurementLib.inf | 9 +- + 2 files changed, 111 insertions(+), 20 deletions(-) + +diff --git a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c +index 061136ee78..802bc3c3cd 100644 +--- a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c ++++ b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.c +@@ -1,5 +1,6 @@ + /** @file +- This library is used by other modules to measure data to TPM. ++ This library is used by other modules to measure data to TPM and Confidential ++ Computing (CC) measure registers. + + Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +@@ -19,6 +20,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + + #include + #include ++#include + + + +@@ -37,6 +39,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + **/ ++STATIC + EFI_STATUS + Tpm12MeasureAndLogData ( + IN UINT32 PcrIndex, +@@ -103,6 +106,7 @@ Tpm12MeasureAndLogData ( + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + **/ ++STATIC + EFI_STATUS + Tpm20MeasureAndLogData ( + IN UINT32 PcrIndex, +@@ -149,6 +153,73 @@ Tpm20MeasureAndLogData ( + return Status; + } + ++/** ++ Cc measure and log data, and extend the measurement result into a ++ specific CC MR. ++ ++ @param[in] CcProtocol Instance of CC measurement protocol ++ @param[in] PcrIndex PCR Index. ++ @param[in] EventType Event type. ++ @param[in] EventLog Measurement event log. ++ @param[in] LogLen Event log length in bytes. ++ @param[in] HashData The start of the data buffer to be hashed, extended. ++ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData ++ ++ @retval EFI_SUCCESS Operation completed successfully. ++ @retval EFI_UNSUPPORTED CC guest not available. ++ @retval EFI_OUT_OF_RESOURCES Out of memory. ++ @retval EFI_DEVICE_ERROR The operation was unsuccessful. ++ @retval EFI_INVALID_PARAMETER The input parameter is invalid. ++**/ ++STATIC ++EFI_STATUS ++CcMeasureAndLogData ( ++ IN EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol, ++ IN UINT32 PcrIndex, ++ IN UINT32 EventType, ++ IN VOID *EventLog, ++ IN UINT32 LogLen, ++ IN VOID *HashData, ++ IN UINT64 HashDataLen ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_CC_EVENT *EfiCcEvent; ++ EFI_CC_MR_INDEX MrIndex; ++ ++ if (CcProtocol == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ Status = CcProtocol->MapPcrToMrIndex (CcProtocol, PcrIndex, &MrIndex); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } ++ ++ EfiCcEvent = (EFI_CC_EVENT *)AllocateZeroPool (LogLen + sizeof (EFI_CC_EVENT)); ++ if (EfiCcEvent == NULL) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ EfiCcEvent->Size = (UINT32)LogLen + sizeof (EFI_CC_EVENT) - sizeof (EfiCcEvent->Event); ++ EfiCcEvent->Header.HeaderSize = sizeof (EFI_CC_EVENT_HEADER); ++ EfiCcEvent->Header.HeaderVersion = EFI_CC_EVENT_HEADER_VERSION; ++ EfiCcEvent->Header.MrIndex = MrIndex; ++ EfiCcEvent->Header.EventType = EventType; ++ CopyMem (&EfiCcEvent->Event[0], EventLog, LogLen); ++ ++ Status = CcProtocol->HashLogExtendEvent ( ++ CcProtocol, ++ 0, ++ (EFI_PHYSICAL_ADDRESS)(UINTN)HashData, ++ HashDataLen, ++ EfiCcEvent ++ ); ++ FreePool (EfiCcEvent); ++ ++ return Status; ++} ++ + /** + Tpm measure and log data, and extend the measurement result into a specific PCR. + +@@ -175,25 +246,16 @@ TpmMeasureAndLogData ( + IN UINT64 HashDataLen + ) + { +- EFI_STATUS Status; +- +- // +- // Try to measure using Tpm20 protocol +- // +- Status = Tpm20MeasureAndLogData( +- PcrIndex, +- EventType, +- EventLog, +- LogLen, +- HashData, +- HashDataLen +- ); ++ EFI_STATUS Status; ++ EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; + +- if (EFI_ERROR (Status)) { ++ Status = gBS->LocateProtocol (&gEfiCcMeasurementProtocolGuid, NULL, (VOID **)&CcProtocol); ++ if (!EFI_ERROR (Status)) { + // +- // Try to measure using Tpm1.2 protocol ++ // Try to measure using Cc measurement protocol + // +- Status = Tpm12MeasureAndLogData( ++ Status = CcMeasureAndLogData ( ++ CcProtocol, + PcrIndex, + EventType, + EventLog, +@@ -201,6 +263,32 @@ TpmMeasureAndLogData ( + HashData, + HashDataLen + ); ++ } else { ++ // ++ // Try to measure using Tpm20 protocol ++ // ++ Status = Tpm20MeasureAndLogData ( ++ PcrIndex, ++ EventType, ++ EventLog, ++ LogLen, ++ HashData, ++ HashDataLen ++ ); ++ ++ if (EFI_ERROR (Status)) { ++ // ++ // Try to measure using Tpm1.2 protocol ++ // ++ Status = Tpm12MeasureAndLogData ( ++ PcrIndex, ++ EventType, ++ EventLog, ++ LogLen, ++ HashData, ++ HashDataLen ++ ); ++ } + } + + return Status; +diff --git a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf +index 7d41bc41f9..3af3d4e33b 100644 +--- a/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf ++++ b/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf +@@ -1,5 +1,7 @@ + ## @file +-# Provides TPM measurement functions for TPM1.2 and TPM 2.0 ++# Provides below measurement functions: ++# 1. TPM measurement functions for TPM1.2 and TPM 2.0 ++# 2. Confidential Computing (CC) measurement functions + # + # This library provides TpmMeasureAndLogData() to measure and log data, and + # extend the measurement result into a specific PCR. +@@ -40,5 +42,6 @@ + UefiBootServicesTableLib + + [Protocols] +- gEfiTcgProtocolGuid ## SOMETIMES_CONSUMES +- gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES ++ gEfiTcgProtocolGuid ## SOMETIMES_CONSUMES ++ gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES ++ gEfiCcMeasurementProtocolGuid ## SOMETIMES_CONSUMES +-- +2.41.0 + diff --git a/edk2-SecurityPkg-Updating-SecurityFixes.yaml-after-symbol.patch b/edk2-SecurityPkg-Updating-SecurityFixes.yaml-after-symbol.patch new file mode 100644 index 0000000..ce0441b --- /dev/null +++ b/edk2-SecurityPkg-Updating-SecurityFixes.yaml-after-symbol.patch @@ -0,0 +1,84 @@ +From fa892c7112cfb5aa742f358544da3788a831e431 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 13 Feb 2024 16:30:10 -0500 +Subject: [PATCH 13/17] SecurityPkg: : Updating SecurityFixes.yaml after symbol + rename + +RH-Author: Jon Maloy +RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable() +RH-Jira: RHEL-21154 RHEL-21156 +RH-Acked-by: Laszlo Ersek +RH-Commit: [13/13] 3bf59dbb583b67eddb54361781054cc650398309 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21156 +CVE: CVE-2022-36764 +Upstream: Merged + +commit 264636d8e6983e0f6dc6be2fca9d84ec81315954 +Author: Doug Flick +Date: Wed Jan 17 14:47:22 2024 -0800 + + SecurityPkg: : Updating SecurityFixes.yaml after symbol rename + + Adding the new commit titles for the symbol renames + + Cc: Jiewen Yao + Cc: Rahul Kumar + + Signed-off-by: Doug Flick [MSFT] + Message-Id: <5e0e851e97459e183420178888d4fcdadc2f1ae1.1705529990.git.doug.edk2@gmail.com> + Reviewed-by: Jiewen Yao + +Signed-off-by: Jon Maloy +--- + SecurityPkg/SecurityFixes.yaml | 31 ++++++++++++++++++++++++++----- + 1 file changed, 26 insertions(+), 5 deletions(-) + +diff --git a/SecurityPkg/SecurityFixes.yaml b/SecurityPkg/SecurityFixes.yaml +index f9e3e7be74..dc1bb83489 100644 +--- a/SecurityPkg/SecurityFixes.yaml ++++ b/SecurityPkg/SecurityFixes.yaml +@@ -9,14 +9,35 @@ CVE_2022_36763: + - "SecurityPkg: DxeTpm2Measurement: SECURITY PATCH 4117 - CVE 2022-36763" + - "SecurityPkg: DxeTpmMeasurement: SECURITY PATCH 4117 - CVE 2022-36763" + - "SecurityPkg: : Adding CVE 2022-36763 to SecurityFixes.yaml" ++ - "SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117/4118 symbol rename" ++ - "SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117/4118 symbol rename" ++ - "SecurityPkg: : Updating SecurityFixes.yaml after symbol rename" + cve: CVE-2022-36763 + date_reported: 2022-10-25 11:31 UTC + description: (CVE-2022-36763) - Heap Buffer Overflow in Tcg2MeasureGptTable() + note: This patch is related to and supersedes TCBZ2168 + files_impacted: +- - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c +- - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c ++ - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c ++ - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c + links: +- - https://bugzilla.tianocore.org/show_bug.cgi?id=4117 +- - https://bugzilla.tianocore.org/show_bug.cgi?id=2168 +- - https://bugzilla.tianocore.org/show_bug.cgi?id=1990 ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4117 ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=2168 ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=1990 ++CVE_2022_36764: ++ commit_titles: ++ - "SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764" ++ - "SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764" ++ - "SecurityPkg: : Adding CVE 2022-36764 to SecurityFixes.yaml" ++ - "SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4117/4118 symbol rename" ++ - "SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4117/4118 symbol rename" ++ - "SecurityPkg: : Updating SecurityFixes.yaml after symbol rename" ++ cve: CVE-2022-36764 ++ date_reported: 2022-10-25 12:23 UTC ++ description: Heap Buffer Overflow in Tcg2MeasurePeImage() ++ note: ++ files_impacted: ++ - Library\DxeTpm2MeasureBootLib\DxeTpm2MeasureBootLib.c ++ - Library\DxeTpmMeasureBootLib\DxeTpmMeasureBootLib.c ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4118 ++ +-- +2.41.0 + diff --git a/edk2-StandaloneMmPkg-Hob-Integer-Overflow-in-CreateHob.patch b/edk2-StandaloneMmPkg-Hob-Integer-Overflow-in-CreateHob.patch new file mode 100644 index 0000000..f5fdb5d --- /dev/null +++ b/edk2-StandaloneMmPkg-Hob-Integer-Overflow-in-CreateHob.patch @@ -0,0 +1,150 @@ +From 155eceaf831492dcd77172833350072e4156e1c9 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 5 Mar 2024 16:38:49 -0500 +Subject: [PATCH 2/2] StandaloneMmPkg/Hob: Integer Overflow in CreateHob() + +RH-Author: Jon Maloy +RH-MergeRequest: 66: EmbeddedPkg/Hob: Integer Overflow in CreateHob() +RH-Jira: RHEL-21158 +RH-Acked-by: Oliver Steffen +RH-Acked-by: Gerd Hoffmann +RH-Commit: [2/2] be7ee11a65a56faec07c249a35940cf9b95b9ec1 + +JIRA: https://issues.redhat.com/browse/RHEL-21158 +CVE: CVE-2022-36765 +Upstream: Merged + +commit 9a75b030cf27d2530444e9a2f9f11867f79bf679 +Author: Gua Guo +Date: Thu Jan 11 13:03:26 2024 +0800 + + StandaloneMmPkg/Hob: Integer Overflow in CreateHob() + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4166 + + Fix integer overflow in various CreateHob instances. + Fixes: CVE-2022-36765 + + The CreateHob() function aligns the requested size to 8 + performing the following operation: + ``` + HobLength = (UINT16)((HobLength + 0x7) & (~0x7)); + ``` + + No checks are performed to ensure this value doesn't + overflow, and could lead to CreateHob() returning a smaller + HOB than requested, which could lead to OOB HOB accesses. + + Reported-by: Marc Beatove + Reviewed-by: Ard Biesheuvel + Cc: Sami Mujawar + Reviewed-by: Ray Ni + Cc: John Mathew + Authored-by: Gerd Hoffmann + Signed-off-by: Gua Guo + + Signed-off-by: Jon Maloy +--- + .../Arm/StandaloneMmCoreHobLib.c | 37 ++++++++++++++++++- + 1 file changed, 36 insertions(+), 1 deletion(-) + +diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c +index 0ec2d4ad6f..3b13249e33 100644 +--- a/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c ++++ b/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Arm/StandaloneMmCoreHobLib.c +@@ -34,6 +34,13 @@ CreateHob ( + + HandOffHob = GetHobList (); + ++ // ++ // Check Length to avoid data overflow. ++ // ++ if (HobLength > MAX_UINT16 - 0x7) { ++ return NULL; ++ } ++ + HobLength = (UINT16)((HobLength + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom; +@@ -87,6 +94,10 @@ BuildModuleHob ( + ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid); + Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; +@@ -127,6 +138,9 @@ BuildResourceDescriptorHob ( + + Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); + ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; +@@ -164,7 +178,12 @@ BuildGuidHob ( + // + ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE))); + +- Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength)); ++ Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16)(sizeof (EFI_HOB_GUID_TYPE) + DataLength)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return NULL; ++ } ++ + CopyGuid (&Hob->Name, Guid); + return Hob + 1; + } +@@ -225,6 +244,10 @@ BuildFvHob ( + EFI_HOB_FIRMWARE_VOLUME *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +@@ -255,6 +278,10 @@ BuildFv2Hob ( + EFI_HOB_FIRMWARE_VOLUME2 *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +@@ -283,6 +310,10 @@ BuildCpuHob ( + EFI_HOB_CPU *Hob; + + Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + Hob->SizeOfMemorySpace = SizeOfMemorySpace; + Hob->SizeOfIoSpace = SizeOfIoSpace; +@@ -318,6 +349,10 @@ BuildMemoryAllocationHob ( + ((Length & (EFI_PAGE_SIZE - 1)) == 0)); + + Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION)); ++ ASSERT (Hob != NULL); ++ if (Hob == NULL) { ++ return; ++ } + + ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID)); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; +-- +2.39.3 + diff --git a/edk2-ovmf-cc.json b/edk2-ovmf-cc.json index 2e52745..64c38d0 100644 --- a/edk2-ovmf-cc.json +++ b/edk2-ovmf-cc.json @@ -18,6 +18,7 @@ { "architecture": "x86_64", "machines": [ + "pc-q35-rhel8.6.0", "pc-q35-rhel8.5.0" ] } diff --git a/edk2.spec b/edk2.spec index edcb979..fca9d85 100644 --- a/edk2.spec +++ b/edk2.spec @@ -1,4 +1,3 @@ -%define anolis_release .0.2 ExclusiveArch: x86_64 aarch64 %define GITDATE 20220126 @@ -8,7 +7,7 @@ ExclusiveArch: x86_64 aarch64 Name: edk2 Version: %{GITDATE}git%{GITCOMMIT} -Release: 6%{anolis_release}%{?dist} +Release: 13%{?dist} Summary: UEFI firmware for 64-bit virtual machines Group: Applications/Emulators License: BSD-2-Clause-Patent and OpenSSL and MIT @@ -20,7 +19,7 @@ URL: http://www.tianocore.org # | xz -9ev >/tmp/edk2-$COMMIT.tar.xz Source0: http://batcave.lab.eng.brq.redhat.com/www/edk2-%{GITCOMMIT}.tar.xz Source1: ovmf-whitepaper-c770f8c.txt -Source2: openssl-rhel-d00c3c5b8a9d6d3ea3dabfcafdf36afd61ba8bcc.tar.xz +Source2: openssl-rhel-cf317b2bb227899cb2e761b9163210f62cab1b1e.tar.xz Source3: ovmf-vars-generator Source4: LICENSE.qosb Source5: RedHatSecureBootPkKek1.pem @@ -61,31 +60,207 @@ Patch28: edk2-rh-openssl-add-crypto-bn-rsa_sup_mul.c-to-file-list.patch Patch29: edk2-SecurityPkg-DxeImageVerificationLib-Check-result-of-.patch # For bz#2150267 - ovmf must consider max cpu count not boot cpu count for apic mode [rhel-8] Patch30: edk2-UefiCpuPkg-MpInitLib-fix-apic-mode-for-cpu-hotplug.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch31: edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariableG.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch32: edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variables.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch33: edk2-OvmfPkg-VirtNorFlashDxe-clone-ArmPlatformPkg-s-NOR-f.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch34: edk2-OvmfPkg-VirtNorFlashDxe-remove-CheckBlockLocked-feat.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch35: edk2-OvmfPkg-VirtNorFlashDxe-remove-disk-I-O-protocol-imp.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch36: edk2-OvmfPkg-VirtNorFlashDxe-drop-block-I-O-protocol-impl.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch37: edk2-OvmfPkg-VirtNorFlashDxe-avoid-array-mode-switch-afte.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch38: edk2-OvmfPkg-VirtNorFlashDxe-avoid-switching-between-mode.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch39: edk2-OvmfPkg-VirtNorFlashDxe-use-EFI_MEMORY_WC-and-drop-A.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch40: edk2-OvmfPkg-VirtNorFlashDxe-map-flash-memory-as-uncachea.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch41: edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariable2.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch42: edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variable2.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch43: edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch44: edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch45: edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch46: edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch47: edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch48: edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch49: edk2-ArmVirtPkg-ArmVirtQemu-migrate-to-OVMF-s-VirtNorFlas.patch +# For RHEL-17587 - [rhel8] guest fails to boot due to ASSERT error +Patch50: edk2-OvmfPkg-clone-NorFlashPlatformLib-into-VirtNorFlashP.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch51: edk2-SecurityPkg-Change-use-of-EFI_D_-to-DEBUG_.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch52: edk2-SecurityPkg-Change-OPTIONAL-keyword-usage-style.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch53: edk2-MdePkg-Introduce-CcMeasurementProtocol-for-CC-Guest-.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch54: edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpm2.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch55: edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpmM.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch56: edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch57: edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4117.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch58: edk2-SecurityPkg-Adding-CVE-2022-36763-to-SecurityFixes.y.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch59: edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-418.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch60: edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4118.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch61: edk2-SecurityPkg-DxeTpm2MeasureBootLib-SEC-PATCH-4118-2.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch62: edk2-SecurityPkg-DxeTpmMeasureBootLib-SEC-PATCH-4117-2.patch +# For RHEL-21154 - CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8] +# For RHEL-21156 - CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8] +Patch63: edk2-SecurityPkg-Updating-SecurityFixes.yaml-after-symbol.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21842 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-8] +Patch64: edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21842 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-8] +Patch65: edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21842 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-8] +Patch66: edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21842 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-8] +Patch67: edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch68: edk2-Apply-uncrustify-changes-to-.c-.h-files-in-the-Netwo.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch69: edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch70: edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch71: edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch72: edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch73: edk2-NetworkPkg-Apply-uncrustify-changes.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch74: edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch75: edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch76: edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch77: edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch78: edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch79: edk2-NetworkPkg-Apply-uncrustify-changes-p2.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch80: edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch81: edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch +# For RHEL-21840 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21844 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8] +# For RHEL-21846 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8] +# For RHEL-21848 - CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8] +# For RHEL-21850 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8] +# For RHEL-21852 - CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8] +Patch82: edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch +# For RHEL-21158 - CVE-2022-36765 edk2: integer overflow in CreateHob() could lead to HOB OOB R/W [rhel-8] +Patch83: edk2-EmbeddedPkg-Hob-Integer-Overflow-in-CreateHob.patch +# For RHEL-21158 - CVE-2022-36765 edk2: integer overflow in CreateHob() could lead to HOB OOB R/W [rhel-8] +Patch84: edk2-StandaloneMmPkg-Hob-Integer-Overflow-in-CreateHob.patch -# Support hygon csv3 feature -Patch1000: 0029-anolis-UefiCpuPkg-Add-StandardSignatureIsHygonGenuin.patch -Patch1001: 0030-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch -Patch1002: 0031-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch -Patch1003: 0032-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch -Patch1004: 0033-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch -Patch1005: 0034-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch -Patch1006: 0035-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch -Patch1007: 0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch -Patch1008: 0037-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch -Patch1009: 0038-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch -# Support SEV live migration -Patch1010: 0039-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch -Patch1011: 0040-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch -Patch1012: 0041-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch -Patch1013: 0042-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch -Patch1014: 0043-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch -Patch1015: 0044-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch -Patch1016: 0045-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch -Patch1017: 0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch -# Fix the isue that interrupt is enabled in MMIO VC handler -Patch1018: 0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch - -Patch1019: 0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch # python3-devel and libuuid-devel are required for building tools. # python3-devel is also needed for varstore template generation and @@ -231,6 +406,8 @@ sed \ %{SOURCE5} \ > PkKek1.oemstr +# Hack to ensure git lock is removed before chmod starts to not fail +sleep 5 # Done by %setup, but we do not use it for the auxiliary tarballs chmod -Rf a+rX,u+w,g-w,o-w . @@ -529,17 +706,105 @@ true %endif %changelog -* Wed Jan 24 2024 Baoshun Fang - 20220126gitbb1bba3d77-6.0.3 -- 0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch -- Resolves: bz#8033 - -* Thu Jan 11 2024 Xin Jiang - 20220126gitbb1bba3d77-6.0.2 -- 0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch -- Fix the isue that interrupt is enabled in MMIO VC handler - -* Thu Dec 14 2023 Jiang Xin - 20220126gitbb1bba3d77-6.0.1 -- Support hygon CSV3 feature -- Support SEV live migration +* Thu Mar 14 2024 Miroslav Rezanina - 20220126gitbb1bba3d77-13 +- edk2-EmbeddedPkg-Hob-Integer-Overflow-in-CreateHob.patch [RHEL-21158] +- edk2-StandaloneMmPkg-Hob-Integer-Overflow-in-CreateHob.patch [RHEL-21158] +- Resolves: RHEL-21158 + (CVE-2022-36765 edk2: integer overflow in CreateHob() could lead to HOB OOB R/W [rhel-8]) + +* Tue Feb 27 2024 Miroslav Rezanina - 20220126gitbb1bba3d77-12 +- edk2-Apply-uncrustify-changes-to-.c-.h-files-in-the-Netwo.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-Apply-uncrustify-changes.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-Apply-uncrustify-changes-p2.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch [RHEL-21840 RHEL-21844 RHEL-21846 RHEL-21848 RHEL-21850 RHEL-21852] +- Resolves: RHEL-21840 + (CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8]) +- Resolves: RHEL-21844 + (CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-8]) +- Resolves: RHEL-21846 + (CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-8]) +- Resolves: RHEL-21848 + (CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-8]) +- Resolves: RHEL-21850 + (CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8]) +- Resolves: RHEL-21852 + (CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-8]) + +* Wed Feb 14 2024 Jon Maloy - 20220126gitbb1bba3d77-11 +- edk2-SecurityPkg-Change-use-of-EFI_D_-to-DEBUG_.patch [RHEL-21154 RHEL-21156] +- edk2-SecurityPkg-Change-OPTIONAL-keyword-usage-style.patch [RHEL-21154 RHEL-21156] +- edk2-MdePkg-Introduce-CcMeasurementProtocol-for-CC-Guest-.patch [RHEL-21154 RHEL-21156] +- edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpm2.patch [RHEL-21154 RHEL-21156] +- edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpmM.patch [RHEL-21154 RHEL-21156] +- edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch [RHEL-21154 RHEL-21156] +- edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4117.patch [RHEL-21154 RHEL-21156] +- edk2-SecurityPkg-Adding-CVE-2022-36763-to-SecurityFixes.y.patch [RHEL-21154 RHEL-21156] +- edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-418.patch [RHEL-21154 RHEL-21156] +- edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4118.patch [RHEL-21154 RHEL-21156] +- edk2-SecurityPkg-DxeTpm2MeasureBootLib-SEC-PATCH-4118-2.patch [RHEL-21154 RHEL-21156] +- edk2-SecurityPkg-DxeTpmMeasureBootLib-SEC-PATCH-4117-2.patch [RHEL-21154 RHEL-21156] +- edk2-SecurityPkg-Updating-SecurityFixes.yaml-after-symbol.patch [RHEL-21154 RHEL-21156] +- edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch [RHEL-21840 RHEL-21842] +- edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch [RHEL-21840 RHEL-21842] +- edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch [RHEL-21840 RHEL-21842] +- edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch [RHEL-21840 RHEL-21842] +- Resolves: RHEL-21154 + (CVE-2022-36763 edk2: heap buffer overflow in Tcg2MeasureGptTable() [rhel-8]) +- Resolves: RHEL-21156 + (CVE-2022-36764 edk2: heap buffer overflow in Tcg2MeasurePeImage() [rhel-8]) +- Resolves: RHEL-21840 + (CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-8]) +- Resolves: RHEL-21842 + (CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-8]) + +* Sat Feb 03 2024 Jon Maloy - 20220126gitbb1bba3d77-10 +- edk2-OvmfPkg-VirtNorFlashDxe-clone-ArmPlatformPkg-s-NOR-f.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-remove-CheckBlockLocked-feat.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-remove-disk-I-O-protocol-imp.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-drop-block-I-O-protocol-impl.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-avoid-array-mode-switch-afte.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-avoid-switching-between-mode.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-use-EFI_MEMORY_WC-and-drop-A.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-map-flash-memory-as-uncachea.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariable2.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variable2.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch [RHEL-17587] +- edk2-ArmVirtPkg-ArmVirtQemu-migrate-to-OVMF-s-VirtNorFlas.patch [RHEL-17587] +- edk2-OvmfPkg-clone-NorFlashPlatformLib-into-VirtNorFlashP.patch [RHEL-17587] +- Resolves: RHEL-17587 + ([rhel8] guest fails to boot due to ASSERT error) + +* Wed Jan 24 2024 Jon Maloy - 20220126gitbb1bba3d77-9 +- edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariableG.patch [RHEL-17587] +- edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variables.patch [RHEL-17587] +- Resolves: RHEL-17587 + ([rhel8] guest fails to boot due to ASSERT error) + +* Fri Jan 05 2024 Jon Maloy - 20220126gitbb1bba3d77-8 +- edk2-Bumped-openssl-submodule-version-to-cf317b2bb227.patch [RHEL-7560] +- Resolves: RHEL-7560 + (CVE-2023-3446 edk2: openssl: Excessive time spent checking DH keys and parameters [rhel-8]) + +* Wed Nov 22 2023 Miroslav Rezanina - 20220126gitbb1bba3d77-7 +- edk2-add-8.6-machine-type-to-edk2-ovmf-cc.json.patch [RHEL-12626] +- Resolves: RHEL-12626 + (Missing firmware descriptor with secureboot disabled in RHEL 8) * Fri Aug 04 2023 Jon Maloy - 20220126gitbb1bba3d77-6 - edk2-UefiCpuPkg-MpInitLib-fix-apic-mode-for-cpu-hotplug.patch [bz#2150267] -- Gitee From 5f3464d614838e925fbdc52c0601a8bf53997456 Mon Sep 17 00:00:00 2001 From: Xin Jiang Date: Mon, 11 Dec 2023 14:05:11 +0800 Subject: [PATCH 2/4] Support Hygon CSV3 feaure and SEV live migration Signed-off-by: Xin Jiang --- ...g-Add-StandardSignatureIsHygonGenuin.patch | 140 ++++ ...g-LocalApicLib-Exclude-second-SendIp.patch | 83 ++ ...dd-CSV-secure-call-library-on-Hygon-.patch | 672 ++++++++++++++++ ...cg-Add-CsvLib-for-TpmMmioSevDecryptP.patch | 27 + ...esetVector-Support-CSV-in-ResetVecto.patch | 222 ++++++ ...latformPei-Initialize-CSV-VM-s-memor.patch | 202 +++++ ...aseMemcryptSevLib-update-page-status.patch | 75 ++ 0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch | 616 +++++++++++++++ ...mfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch | 724 ++++++++++++++++++ ...eserve-a-CPUID-table-page-for-CSV-gu.patch | 137 ++++ ...ncryptLib-Detect-SEV-live-migration-.patch | 325 ++++++++ ...ncryptLib-Hypercall-API-for-page-enc.patch | 298 +++++++ ...ncryptLib-Invoke-page-encryption-sta.patch | 91 +++ ...ib-Encryption-state-change-hypercall.patch | 46 ++ ...Pei-Mark-SEC-GHCB-page-as-unencrypte.patch | 43 ++ ...e-Add-support-for-SEV-live-migration.patch | 185 +++++ ...aseMemcryptSevLib-Correct-the-calcul.patch | 35 + ...aseMemEncryptLib-Return-SUCCESS-if-n.patch | 36 + edk2.spec | 27 +- 19 files changed, 3983 insertions(+), 1 deletion(-) create mode 100644 0029-anolis-UefiCpuPkg-Add-StandardSignatureIsHygonGenuin.patch create mode 100644 0030-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch create mode 100644 0031-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch create mode 100644 0032-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch create mode 100644 0033-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch create mode 100644 0034-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch create mode 100644 0035-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch create mode 100644 0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch create mode 100644 0037-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch create mode 100644 0038-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch create mode 100644 0039-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch create mode 100644 0040-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch create mode 100644 0041-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch create mode 100644 0042-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch create mode 100644 0043-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch create mode 100644 0044-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch create mode 100644 0045-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch create mode 100644 0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch diff --git a/0029-anolis-UefiCpuPkg-Add-StandardSignatureIsHygonGenuin.patch b/0029-anolis-UefiCpuPkg-Add-StandardSignatureIsHygonGenuin.patch new file mode 100644 index 0000000..5abf6fc --- /dev/null +++ b/0029-anolis-UefiCpuPkg-Add-StandardSignatureIsHygonGenuin.patch @@ -0,0 +1,140 @@ +From c5906a1813f0a370e76d0e4910f1959edd552af4 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Thu, 21 Apr 2022 16:03:08 +0800 +Subject: [PATCH 29/46] anolis: UefiCpuPkg: Add + StandardSignatureIsHygonGenuine() in BaseUefiCpuLib + +This function allows IA32/X64 code to determine if it is running on an +Hygon brand processor. + +Signed-off-by: Xin Jiang +Change-Id: I72594196f0ce6003fce43856120e3ca4609b8bb2 +--- + UefiCpuPkg/Include/Library/UefiCpuLib.h | 13 +++++ + UefiCpuPkg/Include/Register/Hygon/Cpuid.h | 47 +++++++++++++++++++ + .../Library/BaseUefiCpuLib/BaseUefiCpuLib.c | 24 ++++++++++ + 3 files changed, 84 insertions(+) + create mode 100644 UefiCpuPkg/Include/Register/Hygon/Cpuid.h + +diff --git a/UefiCpuPkg/Include/Library/UefiCpuLib.h b/UefiCpuPkg/Include/Library/UefiCpuLib.h +index 092c1d2..c64fe26 100644 +--- a/UefiCpuPkg/Include/Library/UefiCpuLib.h ++++ b/UefiCpuPkg/Include/Library/UefiCpuLib.h +@@ -43,6 +43,19 @@ StandardSignatureIsAuthenticAMD ( + VOID + ); + ++/** ++ Determine if the standard CPU signature is "HygonGenuine". ++ ++ @retval TRUE The CPU signature matches. ++ @retval FALSE The CPU signature does not match. ++ ++**/ ++BOOLEAN ++EFIAPI ++StandardSignatureIsHygonGenuine ( ++ VOID ++ ); ++ + /** + Return the 32bit CPU family and model value. + +diff --git a/UefiCpuPkg/Include/Register/Hygon/Cpuid.h b/UefiCpuPkg/Include/Register/Hygon/Cpuid.h +new file mode 100644 +index 0000000..e8a2c76 +--- /dev/null ++++ b/UefiCpuPkg/Include/Register/Hygon/Cpuid.h +@@ -0,0 +1,47 @@ ++/** @file ++ CPUID leaf definitions. ++ ++ Provides defines for CPUID leaf indexes. Data structures are provided for ++ registers returned by a CPUID leaf that contain one or more bit fields. ++ If a register returned is a single 32-bit value, then a data structure is ++ not provided for that register. ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++**/ ++ ++#ifndef __HYGON_CPUID_H__ ++#define __HYGON_CPUID_H__ ++ ++/** ++CPUID Signature Information ++ ++@param EAX CPUID_SIGNATURE (0x00) ++ ++@retval EAX Returns the highest value the CPUID instruction recognizes for ++ returning basic processor information. The value is returned is ++ processor specific. ++@retval EBX First 4 characters of a vendor identification string. ++@retval ECX Last 4 characters of a vendor identification string. ++@retval EDX Middle 4 characters of a vendor identification string. ++ ++**/ ++ ++/// ++/// @{ CPUID signature values returned by HYGON processors ++/// ++#define CPUID_SIGNATURE_AUTHENTIC_HYGON_EBX SIGNATURE_32 ('H', 'y', 'g', 'o') ++#define CPUID_SIGNATURE_AUTHENTIC_HYGON_EDX SIGNATURE_32 ('n', 'G', 'e', 'n') ++#define CPUID_SIGNATURE_AUTHENTIC_HYGON_ECX SIGNATURE_32 ('u', 'i', 'n', 'e') ++/// ++/// @} ++/// ++ ++#endif +diff --git a/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c b/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c +index 5089161..700d633 100644 +--- a/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c ++++ b/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c +@@ -11,6 +11,7 @@ + + #include + #include ++#include + + #include + #include +@@ -38,6 +39,29 @@ StandardSignatureIsAuthenticAMD ( + RegEdx == CPUID_SIGNATURE_AUTHENTIC_AMD_EDX); + } + ++/** ++ Determine if the standard CPU signature is "HygonGenuine". ++ ++ @retval TRUE The CPU signature matches. ++ @retval FALSE The CPU signature does not match. ++ ++**/ ++BOOLEAN ++EFIAPI ++StandardSignatureIsHygonGenuine ( ++ VOID ++ ) ++{ ++ UINT32 RegEbx; ++ UINT32 RegEcx; ++ UINT32 RegEdx; ++ ++ AsmCpuid (CPUID_SIGNATURE, NULL, &RegEbx, &RegEcx, &RegEdx); ++ return (RegEbx == CPUID_SIGNATURE_AUTHENTIC_HYGON_EBX && ++ RegEcx == CPUID_SIGNATURE_AUTHENTIC_HYGON_ECX && ++ RegEdx == CPUID_SIGNATURE_AUTHENTIC_HYGON_EDX); ++} ++ + /** + Return the 32bit CPU family and model value. + +-- +2.17.1 + diff --git a/0030-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch b/0030-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch new file mode 100644 index 0000000..ccb5fd6 --- /dev/null +++ b/0030-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch @@ -0,0 +1,83 @@ +From 573b40aeb685842d7fd4e7985cd197fc79fe8cff Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Sun, 10 Apr 2022 21:50:15 -0400 +Subject: [PATCH 30/46] anolis: UefiCpuPkg/LocalApicLib: Exclude second SendIpi + sequence on HYGON hardware + +On HYGON processors the second SendIpi in the SendInitSipiSipi and +SendInitSipiSipiAllExcludingSelf routines is not required, and may cause +undesired side-effects during MP initialization. + +This patch leverages the StandardSignatureIsHygonGenuine check to exclude +the second SendIpi and its associated MicroSecondDelay (200). + +Signed-off-by: Xin Jiang +Change-Id: I59defdaf10fb36981c5dfb7e3b69e8bf5aaf46cc +--- + UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c | 5 +++-- + UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c | 5 +++-- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c +index 52bd90d..fac41bd 100644 +--- a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c ++++ b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + // + // Library internal functions +@@ -527,7 +528,7 @@ SendInitSipiSipi ( + IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; + IcrLow.Bits.Level = 1; + SendIpi (IcrLow.Uint32, ApicId); +- if (!StandardSignatureIsAuthenticAMD ()) { ++ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { + MicroSecondDelay (200); + SendIpi (IcrLow.Uint32, ApicId); + } +@@ -563,7 +564,7 @@ SendInitSipiSipiAllExcludingSelf ( + IcrLow.Bits.Level = 1; + IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; + SendIpi (IcrLow.Uint32, 0); +- if (!StandardSignatureIsAuthenticAMD ()) { ++ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { + MicroSecondDelay (200); + SendIpi (IcrLow.Uint32, 0); + } +diff --git a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c +index cdcbca0..a8fea8b 100644 +--- a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c ++++ b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + // + // Library internal functions +@@ -622,7 +623,7 @@ SendInitSipiSipi ( + IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP; + IcrLow.Bits.Level = 1; + SendIpi (IcrLow.Uint32, ApicId); +- if (!StandardSignatureIsAuthenticAMD ()) { ++ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { + MicroSecondDelay (200); + SendIpi (IcrLow.Uint32, ApicId); + } +@@ -658,7 +659,7 @@ SendInitSipiSipiAllExcludingSelf ( + IcrLow.Bits.Level = 1; + IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF; + SendIpi (IcrLow.Uint32, 0); +- if (!StandardSignatureIsAuthenticAMD ()) { ++ if (!StandardSignatureIsAuthenticAMD () && !StandardSignatureIsHygonGenuine ()) { + MicroSecondDelay (200); + SendIpi (IcrLow.Uint32, 0); + } +-- +2.17.1 + diff --git a/0031-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch b/0031-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch new file mode 100644 index 0000000..72ebc6f --- /dev/null +++ b/0031-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch @@ -0,0 +1,672 @@ +From 98354124fe8c4cd7e6aed0fb6feabbe3a4de1836 Mon Sep 17 00:00:00 2001 +From: Liu Zixing +Date: Fri, 25 Feb 2022 14:25:11 +0800 +Subject: [PATCH 31/46] anolis: OvmfPkg: Add CSV secure call library on Hygon + CPU + +CSV is the secure virtualization feature on Hygon CPU. +A CSV virtual machine is composed of private memory and shared memory. +The private memory or shared memory can be converted to the other by +the following steps: + - guest clear/set the c-bit in the guest page table + - guest send a update command to Hygon Secure Processor + +While the update command has to be forwarded by the VMM to the Secure +Processor, to prevent the malicious VMM from attacking the update +command, a reliable command channel is required between the CSV VM +and the Hygon Secure Processor. + +The secure call library is created to build a secure command channel +between the VM and the Secure Processor by #NPF on a special private +page which the VMM is not able to access. +This special page is called secure call page. +The VM puts command in the secure call page and triggers a #NPF +to reach the Secure Processor. +The Secure Processor then puts the response in the same page and +finishes the #NPF. +The information is protected in the secure call page all the way. + +CsvLib is added to implement the functionality and new PCDs are added +accordingly. + +Signed-off-by: Xin Jiang +Change-Id: If62f0cb37faf003a79ed8a117bf582f8b90cdf89 +--- + OvmfPkg/Include/Library/CsvLib.h | 84 +++++++ + OvmfPkg/Library/CsvLib/CsvLib.c | 82 ++++++ + OvmfPkg/Library/CsvLib/CsvLib.inf | 55 ++++ + .../Library/CsvLib/Ia32/UpdateMemoryCsvLib.c | 53 ++++ + .../Library/CsvLib/X64/UpdateMemoryCsvLib.c | 238 ++++++++++++++++++ + OvmfPkg/OvmfPkg.dec | 8 + + OvmfPkg/OvmfPkgIa32.dsc | 1 + + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + + OvmfPkg/OvmfPkgX64.dsc | 1 + + OvmfPkg/OvmfPkgX64.fdf | 3 + + 10 files changed, 526 insertions(+) + create mode 100644 OvmfPkg/Include/Library/CsvLib.h + create mode 100644 OvmfPkg/Library/CsvLib/CsvLib.c + create mode 100644 OvmfPkg/Library/CsvLib/CsvLib.inf + create mode 100644 OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c + create mode 100644 OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c + +diff --git a/OvmfPkg/Include/Library/CsvLib.h b/OvmfPkg/Include/Library/CsvLib.h +new file mode 100644 +index 0000000..0cb6218 +--- /dev/null ++++ b/OvmfPkg/Include/Library/CsvLib.h +@@ -0,0 +1,84 @@ ++/** @file ++ ++ CSV base library helper function ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _CSV_LIB_H_ ++#define _CSV_LIB_H_ ++ ++#include ++ ++typedef struct { ++ IN UINT64 BaseAddress; ++ IN UINT64 Size; ++} CSV_SECURE_CMD_SHARED_REGION; ++ ++typedef enum { ++ CsvSecureCmdEnc = 1, ++ CsvSecureCmdDec, ++ CsvSecureCmdReset, ++ CsvSecureCmdUpdateSecureCallTable, ++ CsvSecureCmdMapLowerMemory, //secure memory range below 4G ++ CsvSecureCmdMapUpperMemory //secure memory range above 4G ++} CSV_SECURE_COMMAND_TYPE; ++ ++/** ++ Returns a boolean to indicate whether CSV is enabled ++ ++ @retval TRUE CSV is enabled ++ @retval FALSE CSV is not enabled ++**/ ++BOOLEAN ++EFIAPI ++CsvIsEnabled ( ++ VOID ++ ); ++ ++#define CSV_SHARED_MEMORY_SIGNATURE SIGNATURE_32('C','S','V',' ') ++ ++typedef struct { ++ UINTN Signature; ++ LIST_ENTRY Link; ++ UINT64 Start; ++ UINT64 Length; ++} CsvSharedMemoryEntry; ++ ++VOID ++EFIAPI ++CsvUpdateMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages, ++ IN BOOLEAN Dec ++); ++ ++VOID ++EFIAPI ++CsvResetMemory ( ++ VOID ++); ++ ++VOID ++EFIAPI ++CsvUpdateMapLowerMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++); ++ ++VOID ++EFIAPI ++CsvUpdateMapUpperMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++); ++#endif // _CSV_LIB_H_ +diff --git a/OvmfPkg/Library/CsvLib/CsvLib.c b/OvmfPkg/Library/CsvLib/CsvLib.c +new file mode 100644 +index 0000000..7e7f8ef +--- /dev/null ++++ b/OvmfPkg/Library/CsvLib/CsvLib.c +@@ -0,0 +1,82 @@ ++/** @file ++ ++ CSV library helper function ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++STATIC BOOLEAN mCsvStatus = FALSE; ++STATIC BOOLEAN mCsvStatusChecked = FALSE; ++ ++/** ++ ++ Reads and sets the status of CSV features ++ **/ ++STATIC ++VOID ++EFIAPI ++InternalCsvStatus ( ++ VOID ++ ) ++{ ++ UINT32 RegEax; ++ ++ // ++ // Check if memory encryption leaf exist ++ // ++ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); ++ if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) { ++ if(StandardSignatureIsHygonGenuine ()){ ++ // ++ // Check MSR_0xC0010131 Bit 30 (Csv Enabled) ++ // ++ MSR_SEV_STATUS_REGISTER Msr; ++ Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS); ++ if (Msr.Uint32 & (1 << 30)) { ++ mCsvStatus = TRUE; ++ DEBUG ((EFI_D_INFO, "CSV is enabled\n")); ++ } ++ } ++ } ++ mCsvStatusChecked = TRUE; ++} ++ ++/** ++ Returns a boolean to indicate whether CSV is enabled ++ ++ @retval TRUE CSV is enabled ++ @retval FALSE CSV is not enabled ++**/ ++BOOLEAN ++EFIAPI ++CsvIsEnabled ( ++ VOID ++ ) ++{ ++ if (!mCsvStatusChecked) { ++ InternalCsvStatus (); ++ } ++ ++ return MemEncryptSevEsIsEnabled () && mCsvStatus; ++} +diff --git a/OvmfPkg/Library/CsvLib/CsvLib.inf b/OvmfPkg/Library/CsvLib/CsvLib.inf +new file mode 100644 +index 0000000..25859c3 +--- /dev/null ++++ b/OvmfPkg/Library/CsvLib/CsvLib.inf +@@ -0,0 +1,55 @@ ++## @file ++# Library provides the helper functions for CSV guest ++# ++# Copyright (c) 2022 HYGON. All rights reserved.
++# ++# This program and the accompanying materials ++# are licensed and made available under the terms and conditions of the BSD ++# License which accompanies this distribution. The full text of the license ++# may be found at http://opensource.org/licenses/bsd-license.php ++# ++# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR ++# IMPLIED. ++# ++# ++## ++ ++[Defines] ++ INF_VERSION = 1.25 ++ BASE_NAME = CsvLib ++ FILE_GUID = 9460ef3a-b9c3-11e9-8324-7371ac35e1e3 ++ MODULE_TYPE = BASE ++ VERSION_STRING = 1.0 ++ LIBRARY_CLASS = CsvLib|PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER ++ ++# ++# The following information is for reference only and not required by the build ++# tools. ++# ++# VALID_ARCHITECTURES = Ia32 X64 ++# ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ OvmfPkg/OvmfPkg.dec ++ UefiCpuPkg/UefiCpuPkg.dec ++ ++[Sources] ++ CsvLib.c ++ ++[Sources.X64] ++ X64/UpdateMemoryCsvLib.c ++[Sources.IA32] ++ Ia32/UpdateMemoryCsvLib.c ++ ++[LibraryClasses] ++ BaseLib ++ CpuLib ++ DebugLib ++ MemEncryptSevLib ++ UefiCpuLib ++ ++[Pcd] ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize +diff --git a/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c b/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c +new file mode 100644 +index 0000000..15d3aa8 +--- /dev/null ++++ b/OvmfPkg/Library/CsvLib/Ia32/UpdateMemoryCsvLib.c +@@ -0,0 +1,53 @@ ++/** @file ++ ++ CSV library helper function ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include ++ ++VOID ++EFIAPI ++CsvUpdateMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages, ++ IN BOOLEAN Dec ++) ++{ ++} ++ ++VOID ++EFIAPI ++CsvResetMemory ( ++ VOID ++) ++{ ++} ++ ++VOID ++EFIAPI ++CsvUpdateMapLowerMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++} ++ ++VOID ++EFIAPI ++CsvUpdateMapUpperMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++} +diff --git a/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c b/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c +new file mode 100644 +index 0000000..13d06d7 +--- /dev/null ++++ b/OvmfPkg/Library/CsvLib/X64/UpdateMemoryCsvLib.c +@@ -0,0 +1,238 @@ ++/** @file ++ ++ CSV library helper function ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SECURE_CALL_ENTRY_MAX (254) ++ ++ ++typedef struct { ++ union { ++ UINT8 Guid[16]; ++ UINT64 Guid64[2]; ++ }; ++ UINT32 CmdType; ++ UINT32 Nums; ++ UINT64 Unused; ++ struct { ++ UINT64 BaseAddress; ++ UINT64 Size; ++ } Entry[SECURE_CALL_ENTRY_MAX]; ++} CSV_SECURE_CALL_CMD; ++ ++STATIC UINT32 SecureCallPageIdx = 0; ++ ++STATIC UINTN MemorySizeBelow4G = (UINTN)-1; ++STATIC UINTN MemorySizeAbove4G = (UINTN)-1; ++ ++STATIC ++VOID ++EFIAPI ++CsvSecureCall( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages, ++ IN CSV_SECURE_COMMAND_TYPE CmdType ++) ++{ ++ volatile CSV_SECURE_COMMAND_TYPE CmdAck = 0; ++ ++ CSV_SECURE_CALL_CMD *SecureCallPageRead; ++ CSV_SECURE_CALL_CMD *SecureCallPageWrite; ++ UINTN SecureCallBase = 0; ++ ++ if (CsvIsEnabled () == FALSE) { ++ return ; ++ } ++ ++ SecureCallBase = FixedPcdGet32 (PcdCsvDefaultSecureCallBase); ++ ++ SecureCallPageRead = ++ (CSV_SECURE_CALL_CMD *)(UINT64) ++ (EFI_PAGE_SIZE * SecureCallPageIdx + SecureCallBase); ++ ++ SecureCallPageWrite = ++ (CSV_SECURE_CALL_CMD *) ++ (UINT64)(EFI_PAGE_SIZE * (1 - SecureCallPageIdx) + SecureCallBase); ++ ++ while(1) { ++ SecureCallPageWrite->CmdType = (UINT32)CmdType; ++ SecureCallPageWrite->Nums = 1; ++ SecureCallPageWrite->Entry[0].BaseAddress = (UINT64)BaseAddress; ++ SecureCallPageWrite->Entry[0].Size = (UINT64)NumPages << EFI_PAGE_SHIFT; ++ ++ MemoryFence (); ++ ++ CmdAck = SecureCallPageRead->CmdType; ++ if (CmdAck != CmdType) ++ break; ++ } ++ SecureCallPageIdx = 1 - SecureCallPageIdx; ++} ++ ++STATIC ++UINT8 ++CmosRead8 ( ++ IN UINTN Index ++ ) ++{ ++ IoWrite8 (0x70, (UINT8) Index); ++ return IoRead8 (0x71); ++} ++ ++ ++STATIC ++VOID ++EFIAPI ++CsvGetSystemMemory( ++ VOID ++ ) ++{ ++ UINT8 Cmos0x34; ++ UINT8 Cmos0x35; ++ UINT32 Size; ++ UINTN CmosIndex; ++ ++ // ++ // system memory below 4GB MB ++ // ++ ++ Cmos0x34 = (UINT8) CmosRead8 (0x34); ++ Cmos0x35 = (UINT8) CmosRead8 (0x35); ++ ++ MemorySizeBelow4G = ++ (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB); ++ ++ // ++ // system memory above 4GB MB ++ // ++ ++ Size = 0; ++ for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) { ++ Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex); ++ } ++ ++ MemorySizeAbove4G = LShiftU64 (Size, 16); ++} ++ ++STATIC ++BOOLEAN ++EFIAPI ++CsvIsDRAM( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++ ) ++{ ++ UINTN Size = EFI_PAGES_TO_SIZE (NumPages); ++ PHYSICAL_ADDRESS EndAddress; ++ ++ Size = EFI_PAGES_TO_SIZE (NumPages); ++ EndAddress = BaseAddress + Size; ++ ++ if (MemorySizeBelow4G == (UINTN)-1 || ++ MemorySizeAbove4G == (UINTN)-1) { ++ CsvGetSystemMemory (); ++ } ++ ++ if (BaseAddress < MemorySizeBelow4G) { ++ return TRUE; ++ } else if (BaseAddress >= BASE_4GB && ++ BaseAddress < (BASE_4GB + MemorySizeAbove4G)) { ++ return TRUE; ++ } else if (EndAddress > BASE_4GB && ++ EndAddress <= (BASE_4GB + MemorySizeAbove4G)) { ++ return TRUE; ++ } else { ++ return FALSE; ++ } ++} ++ ++STATIC ++VOID ++EFIAPI ++CsvUpdateEncryptMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++ PHYSICAL_ADDRESS PageAddress = BaseAddress & ~EFI_PAGE_MASK; ++ ++ if (CsvIsDRAM (PageAddress, NumPages)) { ++ CsvSecureCall (PageAddress, NumPages, CsvSecureCmdEnc); ++ } ++} ++ ++STATIC ++VOID ++EFIAPI ++CsvUpdateDecryptMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++ PHYSICAL_ADDRESS PageAddress = BaseAddress & ~EFI_PAGE_MASK; ++ ++ if (CsvIsDRAM (PageAddress, NumPages)) { ++ CsvSecureCall (PageAddress, NumPages, CsvSecureCmdDec); ++ } ++} ++ ++VOID ++EFIAPI ++CsvUpdateMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages, ++ IN BOOLEAN Dec ++ ) ++{ ++ if (Dec) ++ CsvUpdateDecryptMemory (BaseAddress, NumPages); ++ else ++ CsvUpdateEncryptMemory (BaseAddress, NumPages); ++} ++ ++VOID ++EFIAPI ++CsvResetMemory ( ++ VOID ++) ++{ ++ CsvSecureCall (0, 0, CsvSecureCmdReset); ++} ++ ++VOID ++EFIAPI ++CsvUpdateMapLowerMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++ CsvSecureCall (BaseAddress, NumPages, CsvSecureCmdMapLowerMemory); ++} ++ ++VOID ++EFIAPI ++CsvUpdateMapUpperMemory ( ++ IN PHYSICAL_ADDRESS BaseAddress, ++ IN UINTN NumPages ++) ++{ ++ CsvSecureCall (BaseAddress, NumPages, CsvSecureCmdMapUpperMemory); ++} +diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec +index 340d83f..6f4afb8 100644 +--- a/OvmfPkg/OvmfPkg.dec ++++ b/OvmfPkg/OvmfPkg.dec +@@ -109,6 +109,10 @@ + # + XenPlatformLib|Include/Library/XenPlatformLib.h + ++ ## @libraryclass CSV Library ++ # ++ CsvLib|Include/Library/CsvLib.h ++ + [Guids] + gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}} + gEfiXenInfoGuid = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}} +@@ -350,6 +354,10 @@ + gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataOffset|0|UINT32|0x56 + gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataSize|0|UINT32|0x57 + ++ ## the base address of the secure call pages used by CSV. ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|0|UINT32|0x58 ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize|0|UINT32|0x59 ++ + [PcdsDynamic, PcdsDynamicEx] + gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 +diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc +index a066693..d623ed3 100644 +--- a/OvmfPkg/OvmfPkgIa32.dsc ++++ b/OvmfPkg/OvmfPkgIa32.dsc +@@ -176,6 +176,7 @@ + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf ++ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf + !if $(SMM_REQUIRE) == FALSE + LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf + !endif +diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc +index 5efeb42..9e4dcce 100644 +--- a/OvmfPkg/OvmfPkgIa32X64.dsc ++++ b/OvmfPkg/OvmfPkgIa32X64.dsc +@@ -180,6 +180,7 @@ + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf ++ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf + !if $(SMM_REQUIRE) == FALSE + LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf + !endif +diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc +index 10fb7d7..e62b533 100644 +--- a/OvmfPkg/OvmfPkgX64.dsc ++++ b/OvmfPkg/OvmfPkgX64.dsc +@@ -180,6 +180,7 @@ + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf ++ CsvLib|OvmfPkg/Library/CsvLib/CsvLib.inf + !if $(SMM_REQUIRE) == FALSE + LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf + !endif +diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf +index 85b4b23..a3634dd 100644 +--- a/OvmfPkg/OvmfPkgX64.fdf ++++ b/OvmfPkg/OvmfPkgX64.fdf +@@ -88,6 +88,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvm + 0x00C000|0x001000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize + ++0x00D000|0x002000 ++gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize ++ + 0x010000|0x010000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + +-- +2.17.1 + diff --git a/0032-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch b/0032-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch new file mode 100644 index 0000000..c00ebcd --- /dev/null +++ b/0032-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch @@ -0,0 +1,27 @@ +From 40c0763c88a6a895d4fc58158f3c0f9a17798049 Mon Sep 17 00:00:00 2001 +From: Xin Jiang +Date: Fri, 18 Aug 2023 16:48:03 +0800 +Subject: [PATCH 32/46] anolis: OvmfPkg/Tcg: Add CsvLib for + TpmMmioSevDecryptPei + +Signed-off-by: Xin Jiang +Change-Id: I4a11065abcc679538aabcb7602185f785df60496 +--- + OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf +index 51ad6d0..402e4c9 100644 +--- a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf ++++ b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf +@@ -29,6 +29,7 @@ + PcdLib + PeimEntryPoint + PeiServicesLib ++ CsvLib + + [Ppis] + gOvmfTpmMmioAccessiblePpiGuid ## PRODUCES +-- +2.17.1 + diff --git a/0033-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch b/0033-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch new file mode 100644 index 0000000..b30e7df --- /dev/null +++ b/0033-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch @@ -0,0 +1,222 @@ +From b08f9e4b2d4aa1f1baec02ecda6ae481ed58c64f Mon Sep 17 00:00:00 2001 +From: Liu Zixing +Date: Fri, 25 Feb 2022 15:55:44 +0800 +Subject: [PATCH 33/46] anolis: OvmfPkg/ResetVector: Support CSV in ResetVector + phase + +- A GUID is written along with the first secure call page address, +by which the Secure Processor can locate the first secure call page +address. + +- Check whether the VM is a CSV VM when setting the first page table + +- CSV VM will update first shared GHCB page address to Secure Processor +by secure call page + +Signed-off-by: Xin Jiang +Change-Id: I422bff00dc88d6738d1dae2d9f6c5c49ec601e95 +--- + OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 15 +++ + OvmfPkg/ResetVector/Ia32/AmdSev.asm | 10 ++ + OvmfPkg/ResetVector/Ia32/CsvInit.asm | 107 +++++++++++++++++++ + OvmfPkg/ResetVector/ResetVector.inf | 2 + + OvmfPkg/ResetVector/ResetVector.nasmb | 4 + + 5 files changed, 138 insertions(+) + create mode 100644 OvmfPkg/ResetVector/Ia32/CsvInit.asm + +diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm +index dee2e3f..c32b608 100644 +--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm ++++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm +@@ -48,6 +48,21 @@ TIMES (15 - ((guidedStructureEnd - guidedStructureStart + 15) % 16)) DB 0 + guidedStructureStart: + + %ifdef ARCH_X64 ++; ++; CSV secure call table ++; ++; Provide secure call pages when boot up for CSV guest. ++; ++; GUID : 9a5d926f-2fa5-ceba-ab21-6b275d5556a5 ++; ++csvSecureCallBase: ++ DD CSV_DEFAULT_SECURE_CALL_SIZE ++ DD CSV_DEFAULT_SECURE_CALL_BASE ++ DW csvSecureCallEnd - csvSecureCallBase ++ DB 0x6F, 0x92, 0x5D, 0x9A, 0xA5, 0x2F, 0xBA, 0xCE ++ DB 0xAB, 0x21, 0x6B, 0x27, 0x5D, 0x55, 0x56, 0xA5 ++csvSecureCallEnd: ++ + ; + ; TDX Metadata offset block + ; +diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm +index 250ac8d..8ce5eb0 100644 +--- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm ++++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm +@@ -177,6 +177,16 @@ pageTableEntries4kLoop: + mov ecx, (GHCB_BASE & 0x1F_FFFF) >> 12 + mov [ecx * 8 + GHCB_PT_ADDR + 4], strict dword 0 + ++ OneTimeCall CheckCsvFeature ++ test eax, eax ++ jz clearGhcbStart ++ ++ OneTimeCall CsvInit ++ mov eax, 1 ++ test ecx, ecx ++ jz SevEsUnexpectedRespTerminate ++ ++clearGhcbStart: + mov ecx, GHCB_SIZE / 4 + xor eax, eax + clearGhcbMemoryLoop: +diff --git a/OvmfPkg/ResetVector/Ia32/CsvInit.asm b/OvmfPkg/ResetVector/Ia32/CsvInit.asm +new file mode 100644 +index 0000000..0744a35 +--- /dev/null ++++ b/OvmfPkg/ResetVector/Ia32/CsvInit.asm +@@ -0,0 +1,107 @@ ++;------------------------------------------------------------------------------ ++; @file ++; Provide the functions to check whether CSV is enabled. ++; ++; Copyright (c) 2022, HYGON. All rights reserved.
++; SPDX-License-Identifier: BSD-2-Clause-Patent ++; ++;------------------------------------------------------------------------------ ++ ++BITS 32 ++ ++; If Secure Command returns ok then ECX will be non-zero. ++; If Secure Command returns error then ECX will be zero. ++CsvInit: ++ mov esp, SEV_ES_VC_TOP_OF_STACK ++ push esi ++ push edi ++ ++ ; copy SECURE_CALL_GUID to CSV_DEFAULT_SECURE_CALL_BASE + 4096 ++ cld ++ mov esi, ADDR_OF(SECURE_CALL_GUID) ++ mov edi, CSV_DEFAULT_SECURE_CALL_BASE ++ add edi, 4096 ++ mov ecx, 4 ++ rep movsd ++ ++ ; secure call begin ++ mov esi, CSV_DEFAULT_SECURE_CALL_BASE ++ ; write secure cmd to page B ++ ; 16 bytes of page A/B is GUID, just ignore ++ mov [esi + 4096 + 16], DWORD 2 ; dec command ++ mov [esi + 4096 + 20], DWORD 1 ; 1 entry ++ ; 8 bytes is unused ++ mov [esi + 4096 + 32], DWORD GHCB_BASE; lower address ++ mov [esi + 4096 + 36], DWORD 0 ; upper address ++ mov [esi + 4096 + 40], DWORD 4096 ; lower 32 bit of page size ++ mov [esi + 4096 + 44], DWORD 0 ; upper 32 bit of page size ++ mfence ++ ; read from page A ++ mov ecx, [esi + 16] ++ ; check if the response comes ++ cmp ecx, 2 ++ jne SecureCommandDone ++ ; no secure command response, clean ecx ++ xor ecx, ecx ++ ; secure call end ++ ++SecureCommandDone: ++ pop edi ++ pop esi ++ mov esp, 0 ++ ++ OneTimeCallRet CsvInit ++ ++; Check if CSV feature is enabled. ++; ++; Modified: EAX, EBX, ECX, EDX ++; ++; If CSV is enabled then EAX will be non-zero. ++; If CSV is disabled then EAX will be zero. ++; ++CheckCsvFeature: ++ mov esp, SEV_ES_VC_TOP_OF_STACK ++ mov eax, ADDR_OF(Idtr) ++ lidt [cs:eax] ++ ++ ; Check if vendor Hygon CPUID_SIGNATURE(0x0) ++ ; CPUID raises a #VC exception if running as an SEV-ES guest ++ mov eax, 0 ++ cpuid ++ ++ cmp ebx, 0x6f677948 ++ jne NoCsv ++ cmp ecx, 0x656e6975 ++ jne NoCsv ++ cmp edx, 0x6e65476e ++ jne NoCsv ++ ++ ; Check if CSV is enabled ++ ; MSR_0xC0010131 - Bit 30 (CSV enabled) ++ mov ecx, 0xc0010131 ++ rdmsr ++ and eax, 0x40000000 ++ jmp CsvExit ++ ++NoCsv: ++ xor eax, eax ++ ++CsvExit: ++ ; ++ ; Clear exception handlers and stack ++ ; ++ push eax ++ mov eax, ADDR_OF(IdtrClear) ++ lidt [cs:eax] ++ pop eax ++ mov esp, 0 ++ ++ OneTimeCallRet CheckCsvFeature ++ ++SECURE_CALL_GUID: ++; low 0xceba2fa59a5d926f ++; high 0xa556555d276b21ab ++ dd 0x9a5d926f ++ dd 0xceba2fa5 ++ dd 0x276b21ab ++ dd 0xa556555d +diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf +index 320e5f2..38c1720 100644 +--- a/OvmfPkg/ResetVector/ResetVector.inf ++++ b/OvmfPkg/ResetVector/ResetVector.inf +@@ -35,6 +35,8 @@ + + [Pcd] + gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase +diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb +index 87effed..ca00f64 100644 +--- a/OvmfPkg/ResetVector/ResetVector.nasmb ++++ b/OvmfPkg/ResetVector/ResetVector.nasmb +@@ -104,11 +104,15 @@ + %define SEV_ES_WORK_AREA_ENC_MASK (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 16) + %define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize)) + ++ %define CSV_DEFAULT_SECURE_CALL_BASE FixedPcdGet32 (PcdCsvDefaultSecureCallBase) ++ %define CSV_DEFAULT_SECURE_CALL_SIZE FixedPcdGet32 (PcdCsvDefaultSecureCallSize) ++ + %include "X64/IntelTdxMetadata.asm" + %include "Ia32/Flat32ToFlat64.asm" + %include "Ia32/AmdSev.asm" + %include "Ia32/PageTables64.asm" + %include "Ia32/IntelTdx.asm" ++%include "Ia32/CsvInit.asm" + %endif + + %include "Ia16/Real16ToFlat32.asm" +-- +2.17.1 + diff --git a/0034-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch b/0034-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch new file mode 100644 index 0000000..3a55e93 --- /dev/null +++ b/0034-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch @@ -0,0 +1,202 @@ +From 9c52c4e45c2fc51308628c8118edb3740bbfae47 Mon Sep 17 00:00:00 2001 +From: Liu Zixing +Date: Fri, 25 Feb 2022 16:12:38 +0800 +Subject: [PATCH 34/46] anolis: OvmfPkg/PlatformPei: Initialize CSV VM's memory + +For CSV VM, the Secure Processor builds a temporary nested +page table to help the guest to run into the PEI phase. + +In PEI phase, CSV VM detects the start address and size of the +guest physical memory. + +The CSV VM sends the memory information to the Secure Processor +to build the permanent nested page table. + +Signed-off-by: Xin Jiang +Change-Id: I853d17ffa4146037038018d934f224fcbf79be1a +--- + OvmfPkg/PlatformPei/Csv.c | 81 +++++++++++++++++++++++++++++ + OvmfPkg/PlatformPei/MemDetect.c | 2 - + OvmfPkg/PlatformPei/Platform.c | 2 + + OvmfPkg/PlatformPei/Platform.h | 14 +++++ + OvmfPkg/PlatformPei/PlatformPei.inf | 4 ++ + 5 files changed, 101 insertions(+), 2 deletions(-) + create mode 100644 OvmfPkg/PlatformPei/Csv.c + +diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c +new file mode 100644 +index 0000000..44e81e1 +--- /dev/null ++++ b/OvmfPkg/PlatformPei/Csv.c +@@ -0,0 +1,81 @@ ++/** @file ++ ++ CSV initialization in PEI ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "Platform.h" ++ ++VOID ++CsvInitializeMemInfo ( ++ VOID ++ ) ++{ ++ UINT64 LowerMemorySize; ++ UINT64 UpperMemorySize; ++ ++ if (!CsvIsEnabled ()) { ++ return ; ++ } ++ ++ LowerMemorySize = GetSystemMemorySizeBelow4gb (); ++ UpperMemorySize = GetSystemMemorySizeAbove4gb (); ++ ++ CsvUpdateMapLowerMemory ( ++ 0, ++ LowerMemorySize >> EFI_PAGE_SHIFT ++ ); ++ ++ if (UpperMemorySize > 0) { ++ CsvUpdateMapUpperMemory ( ++ BASE_4GB, ++ UpperMemorySize >> EFI_PAGE_SHIFT ++ ); ++ } ++ ++ BuildMemoryAllocationHob ( ++ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallBase), ++ (UINT64)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallSize), ++ EfiReservedMemoryType ++ ); ++} ++ ++VOID ++CsvInitializeGhcb ( ++ VOID ++ ) ++{ ++ RETURN_STATUS EncryptStatus; ++ ++ if (!CsvIsEnabled ()) { ++ return ; ++ } ++ ++ // ++ // Encrypt the SecGhcb as it's not a Ghcb any more ++ // ++ EncryptStatus = MemEncryptSevSetPageEncMask( ++ 0, ++ PcdGet32 (PcdOvmfSecGhcbBase), ++ 1 ++ ); ++ ASSERT_RETURN_ERROR (EncryptStatus); ++} +diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c +index d736b85..c2c3cf7 100644 +--- a/OvmfPkg/PlatformPei/MemDetect.c ++++ b/OvmfPkg/PlatformPei/MemDetect.c +@@ -301,8 +301,6 @@ GetSystemMemorySizeBelow4gb ( + return (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB); + } + +- +-STATIC + UINT64 + GetSystemMemorySizeAbove4gb ( + ) +diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c +index d0e2c08..79bf4e7 100644 +--- a/OvmfPkg/PlatformPei/Platform.c ++++ b/OvmfPkg/PlatformPei/Platform.c +@@ -743,6 +743,7 @@ InitializePlatform ( + QemuUc32BaseInitialization (); + + InitializeRamRegions (); ++ CsvInitializeMemInfo (); + + if (mBootMode != BOOT_ON_S3_RESUME) { + if (!FeaturePcdGet (PcdSmmSmramRequire)) { +@@ -757,6 +758,7 @@ InitializePlatform ( + + InstallClearCacheCallback (); + AmdSevInitialize (); ++ CsvInitializeGhcb (); + MiscInitialization (); + InstallFeatureControlCallback (); + +diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h +index 8b1d270..89c3bd8 100644 +--- a/OvmfPkg/PlatformPei/Platform.h ++++ b/OvmfPkg/PlatformPei/Platform.h +@@ -102,6 +102,20 @@ AmdSevInitialize ( + VOID + ); + ++VOID ++CsvInitializeMemInfo ( ++ VOID ++); ++ ++VOID ++CsvInitializeGhcb ( ++ VOID ++); ++ ++UINT64 ++GetSystemMemorySizeAbove4gb ( ++); ++ + extern EFI_BOOT_MODE mBootMode; + + extern BOOLEAN mS3Supported; +diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf +index 69eb3ed..cb0582c 100644 +--- a/OvmfPkg/PlatformPei/PlatformPei.inf ++++ b/OvmfPkg/PlatformPei/PlatformPei.inf +@@ -33,6 +33,7 @@ + MemTypeInfo.c + Platform.c + Platform.h ++ Csv.c + + [Packages] + EmbeddedPkg/EmbeddedPkg.dec +@@ -62,6 +63,7 @@ + MtrrLib + MemEncryptSevLib + PcdLib ++ CsvLib + + [Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase +@@ -119,6 +121,8 @@ + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize + + [FeaturePcd] + gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable +-- +2.17.1 + diff --git a/0035-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch b/0035-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch new file mode 100644 index 0000000..1938b99 --- /dev/null +++ b/0035-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch @@ -0,0 +1,75 @@ +From 16936ea22fc052576844dfdad6987531aa27a8ec Mon Sep 17 00:00:00 2001 +From: Liu Zixing +Date: Sat, 26 Feb 2022 14:39:06 +0800 +Subject: [PATCH 35/46] anolis: OvmfPkg/BaseMemcryptSevLib: update page status + to Secure Processor for CSV + +For CSV VM, when encrypting/decrypting a shared/private memory region, +guest needs to + - set/clear the c-bit in guest page table + - the Secure Processor should be updated accordingly + +The BaseMemcryptSevLib has done the first step. +Calling the secure call library for second step. + +Signed-off-by: Xin Jiang +Change-Id: Icab502ee201d887d6056bcb0116b2e5a1b9eb6b9 +--- + .../BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf | 1 + + .../BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +index f2e162d..dc32929 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +@@ -49,6 +49,7 @@ + DebugLib + MemoryAllocationLib + PcdLib ++ CsvLib + + [FeaturePcd] + gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +index c696745..6726010 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +@@ -18,6 +18,8 @@ + + #include "VirtualMemory.h" + ++#include ++ + STATIC BOOLEAN mAddressEncMaskChecked = FALSE; + STATIC UINT64 mAddressEncMask; + STATIC PAGE_TABLE_POOL *mPageTablePool = NULL; +@@ -585,6 +587,11 @@ SetMemoryEncDec ( + UINT64 AddressEncMask; + BOOLEAN IsWpEnabled; + RETURN_STATUS Status; ++ PHYSICAL_ADDRESS PageAddress; ++ UINTN PageNum; ++ ++ PageAddress = PhysicalAddress; ++ PageNum = EFI_SIZE_TO_PAGES (Length); + + // + // Set PageMapLevel4Entry to suppress incorrect compiler/analyzer warnings. +@@ -816,6 +823,13 @@ Done: + EnableReadOnlyPageWriteProtect (); + } + ++ if (CsvIsEnabled () && Status == EFI_SUCCESS) { ++ if (Mode == ClearCBit) ++ CsvUpdateMemory (PageAddress, PageNum, TRUE); ++ else ++ CsvUpdateMemory (PageAddress, PageNum, FALSE); ++ } ++ + return Status; + } + +-- +2.17.1 + diff --git a/0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch b/0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch new file mode 100644 index 0000000..0bf6d40 --- /dev/null +++ b/0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch @@ -0,0 +1,616 @@ +From 4569ddd201843a1fd1e9b0431e971cd4edefff5d Mon Sep 17 00:00:00 2001 +From: Liu Zixing +Date: Fri, 25 Feb 2022 16:34:25 +0800 +Subject: [PATCH 36/46] anolis: OvmfPkg: Add CsvDxe driver + +CsvDxe creates and installs the CsvSharedMemory protocol. + +CSV VM needs the shared memory to exchange data with external devices. + +To improve the performance, CsvSharedMemory protocol pre-allocates +huge shared memory chunk as a pool. + +When reqeusted, it allocates small pieces of shared memory from the +pool and records the allocated memory in a list. + +When finished, the shared memory pieces are returned to the pool and +removed from the record list. + +Signed-off-by: Xin Jiang +Change-Id: I6b41c6e1af34b4f8ad58a61cce2e7fd8e8b5795b +--- + OvmfPkg/CsvDxe/CsvDxe.c | 104 +++++++++++ + OvmfPkg/CsvDxe/CsvDxe.inf | 45 +++++ + OvmfPkg/CsvDxe/CsvSharedMemory.c | 208 +++++++++++++++++++++ + OvmfPkg/CsvDxe/CsvSharedMemory.h | 29 +++ + OvmfPkg/Include/Protocol/CsvSharedMemory.h | 99 ++++++++++ + OvmfPkg/OvmfPkg.dec | 1 + + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + + OvmfPkg/OvmfPkgIa32X64.fdf | 1 + + OvmfPkg/OvmfPkgX64.dsc | 1 + + OvmfPkg/OvmfPkgX64.fdf | 1 + + 10 files changed, 490 insertions(+) + create mode 100644 OvmfPkg/CsvDxe/CsvDxe.c + create mode 100644 OvmfPkg/CsvDxe/CsvDxe.inf + create mode 100644 OvmfPkg/CsvDxe/CsvSharedMemory.c + create mode 100644 OvmfPkg/CsvDxe/CsvSharedMemory.h + create mode 100644 OvmfPkg/Include/Protocol/CsvSharedMemory.h + +diff --git a/OvmfPkg/CsvDxe/CsvDxe.c b/OvmfPkg/CsvDxe/CsvDxe.c +new file mode 100644 +index 0000000..552f3cf +--- /dev/null ++++ b/OvmfPkg/CsvDxe/CsvDxe.c +@@ -0,0 +1,104 @@ ++/** @file ++ ++ Hygon CSV DXE. ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT ++ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "CsvSharedMemory.h" ++ ++ ++#define HUGE_PAGE_SIZE 0x200000ULL ++ ++EFI_STATUS ++EFIAPI ++CsvDxeEntryPoint ( ++ IN EFI_HANDLE ImageHandle, ++ IN EFI_SYSTEM_TABLE *SystemTable ++ ) ++{ ++ EFI_STATUS Status; ++ RETURN_STATUS DecryptStatus; ++ CSV_SHARED_MEMORY_PROTOCOL *SharedMemory; ++ EFI_PHYSICAL_ADDRESS Memory; ++ EFI_PHYSICAL_ADDRESS EndMemory; ++ EFI_ALLOCATE_TYPE AllocateType; ++ UINT64 Size; ++ ++ Status = CsvInstallSharedMemoryProtocol (); ++ ++ if (EFI_ERROR (Status)) { ++ DEBUG ((EFI_D_ERROR, "fail to install CsvSharedMemory protocol\n")); ++ return Status; ++ } ++ ++ // ++ // Do nothing more when CSV is not enabled ++ // ++ if (!CsvIsEnabled ()) { ++ return EFI_SUCCESS; ++ } ++ ++ Status = gBS->LocateProtocol ( ++ &gCsvSharedMemoryProtocolGuid, ++ NULL, ++ (VOID**)&SharedMemory ++ ); ++ ++ if (Status == EFI_SUCCESS) { ++ ++ AllocateType = AllocateMaxAddress; ++ Memory = BASE_4GB - 1; ++ ++ Status = gBS->AllocatePages ( ++ AllocateType, ++ EfiBootServicesData, ++ CSV_SHARED_MEMORY_PAGE_NUMBER, ++ &Memory ++ ); ++ ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "fail to allocate CsvSharedMemory\n", SharedMemory)); ++ } else { ++ //Align to huge page ++ EndMemory = (Memory + CSV_SHARED_MEMORY_SIZE) & (~(HUGE_PAGE_SIZE - 1)); ++ Memory = ALIGN_VALUE(Memory, HUGE_PAGE_SIZE); ++ Size = (EndMemory > Memory) ? EndMemory - Memory : 0; ++ DecryptStatus = MemEncryptSevClearPageEncMask ( ++ 0, ++ Memory, ++ Size >> EFI_PAGE_SHIFT ++ ); ++ ASSERT_RETURN_ERROR (DecryptStatus); ++ ++ SharedMemory->CsvInitializeSharedMemoryList ( ++ SharedMemory, ++ (UINT64)Memory, ++ Size ++ ); ++ } ++ } else { ++ DEBUG ((DEBUG_ERROR, "fail to LocateProtocol gCsvSharedMemoryProtocolGuid\n")); ++ } ++ ++ return EFI_SUCCESS; ++} +diff --git a/OvmfPkg/CsvDxe/CsvDxe.inf b/OvmfPkg/CsvDxe/CsvDxe.inf +new file mode 100644 +index 0000000..89e3703 +--- /dev/null ++++ b/OvmfPkg/CsvDxe/CsvDxe.inf +@@ -0,0 +1,45 @@ ++#/** @file ++# ++# Secure Isolated Virtualization ++# ++# Copyright (c) 2022, HYGON Inc. All rights reserved.
++# ++# This program and the accompanying materials are licensed and made available ++# under the terms and conditions of the BSD License which accompanies this ++# distribution. The full text of the license may be found at ++# http://opensource.org/licenses/bsd-license.php ++# ++# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR ++# IMPLIED. ++# ++#**/ ++ ++[Defines] ++ INF_VERSION = 1.25 ++ BASE_NAME = CsvDxe ++ FILE_GUID = 829310c0-b9c4-11e9-9e16-9b10d744f884 ++ MODULE_TYPE = DXE_DRIVER ++ VERSION_STRING = 1.0 ++ ENTRY_POINT = CsvDxeEntryPoint ++ ++[Sources] ++ CsvDxe.c ++ CsvSharedMemory.c ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ OvmfPkg/OvmfPkg.dec ++ ++[LibraryClasses] ++ BaseLib ++ BaseMemoryLib ++ DebugLib ++ CsvLib ++ UefiDriverEntryPoint ++ ++[Depex] ++ TRUE ++ ++[Protocols] ++ gCsvSharedMemoryProtocolGuid +diff --git a/OvmfPkg/CsvDxe/CsvSharedMemory.c b/OvmfPkg/CsvDxe/CsvSharedMemory.c +new file mode 100644 +index 0000000..8674eaf +--- /dev/null ++++ b/OvmfPkg/CsvDxe/CsvSharedMemory.c +@@ -0,0 +1,208 @@ ++/** @file ++ ++ The protocol provides allocate, free the CSV shared memory. ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++STATIC LIST_ENTRY CsvSharedMemoryList = INITIALIZE_LIST_HEAD_VARIABLE (CsvSharedMemoryList); ++ ++// ++// Insert the initial shared memory address and length to list. ++// ++ ++EFI_STATUS ++EFIAPI ++CsvInitializeSharedMemoryList ( ++ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol, ++ IN UINT64 Address, ++ IN UINT64 Length ++ ) ++{ ++ CsvSharedMemoryEntry *Entry; ++ ++ if (Length == 0) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ Entry = AllocatePool (sizeof (*Entry)); ++ if (Entry == NULL) { ++ DEBUG((DEBUG_ERROR, "CsvInitializeSharedMemoryList AllocatePool error\n")); ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ Entry->Start = Address; ++ Entry->Length = Length; ++ Entry->Signature = CSV_SHARED_MEMORY_SIGNATURE; ++ ++ InsertTailList (&CsvSharedMemoryList, &Entry->Link); ++ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++CsvAllocateSharedMemory ( ++ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol, ++ IN UINTN NumberOfPages, ++ OUT UINT64 *Memory ++ ) ++{ ++ LIST_ENTRY *Link; ++ CsvSharedMemoryEntry *Entry; ++ UINT64 MemoryLength; ++ ++ MemoryLength = (UINT64)NumberOfPages << EFI_PAGE_SHIFT; ++ ++ for (Link = CsvSharedMemoryList.ForwardLink; Link != &CsvSharedMemoryList; Link = Link->ForwardLink) { ++ Entry = CR (Link, CsvSharedMemoryEntry, Link, CSV_SHARED_MEMORY_SIGNATURE); ++ if (Entry->Length > MemoryLength) { ++ *Memory = (EFI_PHYSICAL_ADDRESS)Entry->Start; ++ Entry->Start = *Memory + MemoryLength; ++ Entry->Length -= MemoryLength; ++ break; ++ } else if (Entry->Length == MemoryLength) { ++ *Memory = (EFI_PHYSICAL_ADDRESS)Entry->Start; ++ RemoveEntryList (&Entry->Link); ++ FreePool (Entry); ++ break; ++ } ++ } ++ ++ ++ ++ if (Link == &CsvSharedMemoryList) { ++ DEBUG ((EFI_D_ERROR, "CsvAllocateSharedMemory fail to allocate %u pages\n", NumberOfPages)); ++ return EFI_NOT_FOUND; ++ } ++ else { ++ return EFI_SUCCESS; ++ } ++} ++ ++ ++ ++EFI_STATUS ++EFIAPI ++CsvFreeSharedMemory ( ++ IN CSV_SHARED_MEMORY_PROTOCOL *Protocol, ++ IN UINTN Pages, ++ IN UINT64 HostAddress ++ ) ++{ ++ LIST_ENTRY *Link; ++ CsvSharedMemoryEntry *Entry; ++ CsvSharedMemoryEntry *NewEntry; ++ UINT64 Memory; ++ UINT64 MemoryLength; ++ CsvSharedMemoryEntry *Previous = NULL; ++ BOOLEAN Inserted = FALSE; ++ ++ Memory = (UINT64)HostAddress; ++ MemoryLength = (UINT64)Pages << EFI_PAGE_SHIFT; ++ ++ for (Link = CsvSharedMemoryList.ForwardLink; ++ Link != &CsvSharedMemoryList; ++ Link = Link->ForwardLink) { ++ Entry = CR (Link, CsvSharedMemoryEntry, Link, CSV_SHARED_MEMORY_SIGNATURE); ++ if (Inserted) ++ goto Merge; ++ if (Entry->Start + Entry->Length == Memory) { ++ Entry->Length += MemoryLength; ++ Inserted = TRUE; ++ goto Merge; ++ } else if (Memory + MemoryLength < Entry->Start) { ++ NewEntry = AllocatePool (sizeof *NewEntry); ++ if (NewEntry == NULL) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ NewEntry->Start = Memory; ++ NewEntry->Length = MemoryLength; ++ NewEntry->Signature = CSV_SHARED_MEMORY_SIGNATURE; ++ ++ InsertTailList (&Entry->Link, &NewEntry->Link); ++ break; ++ } else if (Memory + MemoryLength == Entry->Start) { ++ Entry->Start = Memory; ++ Entry->Length += MemoryLength; ++ break; ++ } else if (Link->ForwardLink == &CsvSharedMemoryList) { ++ // ++ // Insert to tail ++ // ++ NewEntry = AllocatePool (sizeof *NewEntry); ++ if (NewEntry == NULL) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ NewEntry->Start = Memory; ++ NewEntry->Length = MemoryLength; ++ NewEntry->Signature = CSV_SHARED_MEMORY_SIGNATURE; ++ InsertHeadList (Link, &NewEntry->Link); ++ break; ++ } ++ ++Merge: ++ if (Previous) { ++ if (Previous->Start + Previous->Length == Entry->Start) { ++ Entry->Start = Previous->Start; ++ Entry->Length += Previous->Length; ++ RemoveEntryList (&Previous->Link); ++ FreePool (Previous); ++ } ++ break; ++ } else { ++ Previous = Entry; ++ } ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++CSV_SHARED_MEMORY_PROTOCOL mCsvSharedMemory = { ++ CsvInitializeSharedMemoryList, ++ CsvAllocateSharedMemory, ++ CsvFreeSharedMemory ++}; ++ ++/** ++ Initialize CsvSharedMemory Protocol. ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvInstallSharedMemoryProtocol ( ++ VOID ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_HANDLE Handle; ++ ++ Handle = NULL; ++ Status = gBS->InstallMultipleProtocolInterfaces ( ++ &Handle, ++ &gCsvSharedMemoryProtocolGuid, ++ &mCsvSharedMemory, ++ NULL ++ ); ++ return Status; ++} +diff --git a/OvmfPkg/CsvDxe/CsvSharedMemory.h b/OvmfPkg/CsvDxe/CsvSharedMemory.h +new file mode 100644 +index 0000000..8828515 +--- /dev/null ++++ b/OvmfPkg/CsvDxe/CsvSharedMemory.h +@@ -0,0 +1,29 @@ ++/** @file ++ CSV shared memory management protocol ++ ++ Copyright (C) 2022 HYGON. ++ ++ This program and the accompanying materials ++ are licensed and made available under the terms and conditions of the BSD License ++ which accompanies this distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _CSV_SHARED_MEMORY_H_ ++#define _CSV_SHARED_MEMORY_H_ ++ ++// ++// Install SHARED_MEMORY protocol . ++// ++ ++EFI_STATUS ++EFIAPI ++CsvInstallSharedMemoryProtocol ( ++ VOID ++ ); ++ ++#endif +diff --git a/OvmfPkg/Include/Protocol/CsvSharedMemory.h b/OvmfPkg/Include/Protocol/CsvSharedMemory.h +new file mode 100644 +index 0000000..0c3f23d +--- /dev/null ++++ b/OvmfPkg/Include/Protocol/CsvSharedMemory.h +@@ -0,0 +1,99 @@ ++/** @file ++ CSV shared memory management protocol ++ ++ Copyright (C) 2022 HYGON. ++ ++ This program and the accompanying materials ++ are licensed and made available under the terms and conditions of the BSD License ++ which accompanies this distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef __PROTOCOL_CSV_SHARED_MEMORY_H__ ++#define __PROTOCOL_CSV_SHARED_MEMORY_H__ ++ ++#define CSV_SHARED_MEMORY_PAGE_NUMBER (16384ULL) ++#define CSV_SHARED_MEMORY_SIZE ((CSV_SHARED_MEMORY_PAGE_NUMBER)*(SIZE_4KB)) ++ ++/// ++/// Forward declaration ++/// ++typedef struct _CSV_SHARED_MEMORY_PROTOCOL CSV_SHARED_MEMORY_PROTOCOL; ++ ++ ++/// ++/// Function prototypes ++/// ++ ++/** ++ Initialize the list to manage the CSV shared memory. ++ Insert the start address and length. ++ ++ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance. ++ @param Address The start address of the shared memory. ++ @param Length The length of the shared memory. ++ ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *CSV_INITIALIZE_SHARED_MEMORY_LIST)( ++ IN CSV_SHARED_MEMORY_PROTOCOL *This, ++ IN UINT64 Address, ++ IN UINT64 Length ++ ); ++ ++/** ++ Allocate buffer from the shared memory. ++ ++ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance. ++ @param NumberOfPages The length of page number. ++ @param Memory When success, allocated memory will be stored in. ++ ++ @return On success, EFI_SUCCESS. Otherwise an errno value ++ indicating the type of failure. ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *CSV_ALLOCATE_SHARED_MEMORY)( ++ IN CSV_SHARED_MEMORY_PROTOCOL *This, ++ IN UINTN NumberOfPages, ++ OUT UINT64 *Memory ++ ); ++ ++/** ++ Free buffer to the shared memory. ++ ++ @param This A pointer to CSV_SHARED_MEMORY_PROTOCOL instance. ++ @param NumberOfPages The page number. ++ @param Memory The allocated memory to be freed. ++ ++ @return On success, EFI_SUCCESS. Otherwise an errno value ++ indicating the type of failure. ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *CSV_FREE_SHARED_MEMORY)( ++ IN CSV_SHARED_MEMORY_PROTOCOL *This, ++ IN UINTN NumberOfPages, ++ IN UINT64 Memory ++ ); ++ ++/// ++/// Protocol structure ++/// ++struct _CSV_SHARED_MEMORY_PROTOCOL { ++ // ++ // Protocol data fields ++ // ++ CSV_INITIALIZE_SHARED_MEMORY_LIST CsvInitializeSharedMemoryList; ++ CSV_ALLOCATE_SHARED_MEMORY CsvAllocateSharedMemory; ++ CSV_FREE_SHARED_MEMORY CsvFreeSharedMemory; ++}; ++ ++extern EFI_GUID gCsvSharedMemoryProtocolGuid; ++ ++#endif +diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec +index 6f4afb8..d8f9be3 100644 +--- a/OvmfPkg/OvmfPkg.dec ++++ b/OvmfPkg/OvmfPkg.dec +@@ -152,6 +152,7 @@ + gEfiLegacyInterruptProtocolGuid = {0x31ce593d, 0x108a, 0x485d, {0xad, 0xb2, 0x78, 0xf2, 0x1f, 0x29, 0x66, 0xbe}} + gEfiVgaMiniPortProtocolGuid = {0xc7735a2f, 0x88f5, 0x4882, {0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3}} + gOvmfLoadedX86LinuxKernelProtocolGuid = {0xa3edc05d, 0xb618, 0x4ff6, {0x95, 0x52, 0x76, 0xd7, 0x88, 0x63, 0x43, 0xc8}} ++ gCsvSharedMemoryProtocolGuid = {0x0c795ed0, 0xbf0a, 0x11e9, {0x99, 0xbe, 0x50, 0x9a, 0x4c, 0x01, 0x1e, 0xd1}} + + [PcdsFixedAtBuild] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0 +diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc +index 9e4dcce..edc0f0e 100644 +--- a/OvmfPkg/OvmfPkgIa32X64.dsc ++++ b/OvmfPkg/OvmfPkgIa32X64.dsc +@@ -982,6 +982,7 @@ + OvmfPkg/PlatformDxe/Platform.inf + OvmfPkg/AmdSevDxe/AmdSevDxe.inf + OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++ OvmfPkg/CsvDxe/CsvDxe.inf + + !if $(SMM_REQUIRE) == TRUE + OvmfPkg/SmmAccess/SmmAccess2Dxe.inf +diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf +index e33a40c..f05405b 100644 +--- a/OvmfPkg/OvmfPkgIa32X64.fdf ++++ b/OvmfPkg/OvmfPkgIa32X64.fdf +@@ -339,6 +339,7 @@ INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf + INF OvmfPkg/PlatformDxe/Platform.inf + INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf + INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++INF OvmfPkg/CsvDxe/CsvDxe.inf + + !if $(SMM_REQUIRE) == TRUE + INF OvmfPkg/SmmAccess/SmmAccess2Dxe.inf +diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc +index e62b533..763214d 100644 +--- a/OvmfPkg/OvmfPkgX64.dsc ++++ b/OvmfPkg/OvmfPkgX64.dsc +@@ -980,6 +980,7 @@ + OvmfPkg/PlatformDxe/Platform.inf + OvmfPkg/AmdSevDxe/AmdSevDxe.inf + OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++ OvmfPkg/CsvDxe/CsvDxe.inf + + !if $(SMM_REQUIRE) == TRUE + OvmfPkg/SmmAccess/SmmAccess2Dxe.inf +diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf +index a3634dd..0f04acb 100644 +--- a/OvmfPkg/OvmfPkgX64.fdf ++++ b/OvmfPkg/OvmfPkgX64.fdf +@@ -358,6 +358,7 @@ INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf + INF OvmfPkg/PlatformDxe/Platform.inf + INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf + INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++INF OvmfPkg/CsvDxe/CsvDxe.inf + + !if $(SMM_REQUIRE) == TRUE + INF OvmfPkg/SmmAccess/SmmAccess2Dxe.inf +-- +2.17.1 + diff --git a/0037-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch b/0037-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch new file mode 100644 index 0000000..9b4b800 --- /dev/null +++ b/0037-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch @@ -0,0 +1,724 @@ +From 8f82f4b8d86ca1b10b9353b484c403c628b3b560 Mon Sep 17 00:00:00 2001 +From: Liu Zixing +Date: Fri, 25 Feb 2022 16:54:44 +0800 +Subject: [PATCH 37/46] anolis: OvmfPkg/IoMmuDxe: Add CsvIoMmu protocol + +Create the dedicated IoMmu protocol for CSV virtual machine. +And Install it during CSV VM boots up. + +It calls the CsvSharedMemoryProtocol to allocate shared memory +for DMA operations. + +- AllocateBuffer() allocates the shared memory. + +- FreeBuffer() frees the shared memory. + +- Map() does nothing when BusMasterCommonBuffer[64] is requested + Otherwise, Map() allocates shared memory. + +- Unmap() does nothing when cleaning up a BusMasterCommonBuffer[64] + operation. Otherwise, Unmap() frees the shared memory. + +Signed-off-by: Xin Jiang +Change-Id: If49857f45c639341a96605722b06babfa1553874 +--- + OvmfPkg/IoMmuDxe/CsvIoMmu.c | 592 ++++++++++++++++++++++++++++++++++ + OvmfPkg/IoMmuDxe/CsvIoMmu.h | 29 ++ + OvmfPkg/IoMmuDxe/IoMmuDxe.c | 10 + + OvmfPkg/IoMmuDxe/IoMmuDxe.inf | 6 +- + 4 files changed, 636 insertions(+), 1 deletion(-) + create mode 100644 OvmfPkg/IoMmuDxe/CsvIoMmu.c + create mode 100644 OvmfPkg/IoMmuDxe/CsvIoMmu.h + +diff --git a/OvmfPkg/IoMmuDxe/CsvIoMmu.c b/OvmfPkg/IoMmuDxe/CsvIoMmu.c +new file mode 100644 +index 0000000..c5df6b9 +--- /dev/null ++++ b/OvmfPkg/IoMmuDxe/CsvIoMmu.c +@@ -0,0 +1,592 @@ ++/** @file ++ ++ The protocol provides support to allocate, free, map and umap a DMA buffer ++ for bus master (e.g PciHostBridge). When CSV is enabled, the DMA operations ++ must be performed on non-secure memory so we have to allocate the DMA buffer ++ from non-secure memory. ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "CsvIoMmu.h" ++ ++#define MAP_INFO_SIG SIGNATURE_64 ('M', 'A', 'P', '_', 'I', 'N', 'F', 'O') ++ ++typedef struct { ++ UINT64 Signature; ++ LIST_ENTRY Link; ++ EDKII_IOMMU_OPERATION Operation; ++ UINTN NumberOfBytes; ++ UINTN NumberOfPages; ++ EFI_PHYSICAL_ADDRESS SecureAddress; ++ EFI_PHYSICAL_ADDRESS UnSecureAddress; ++} MAP_INFO; ++ ++// ++// List of the MAP_INFO structures that have been set up by IoMmuMap() and not ++// yet torn down by IoMmuUnmap(). The list represents the full set of mappings ++// currently in effect. ++// ++STATIC LIST_ENTRY mMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (mMapInfos); ++ ++// ++// ASCII names for EDKII_IOMMU_OPERATION constants, for debug logging. ++// ++STATIC CONST CHAR8 * CONST ++mBusMasterOperationName[EdkiiIoMmuOperationMaximum] = { ++ "Read", ++ "Write", ++ "CommonBuffer", ++ "Read64", ++ "Write64", ++ "CommonBuffer64" ++}; ++ ++STATIC CSV_SHARED_MEMORY_PROTOCOL *SharedMemory; ++STATIC ++EFI_STATUS ++EFIAPI ++CsvAllocSharedPage( ++ IN UINTN Pages, ++ OUT EFI_PHYSICAL_ADDRESS *Address ++ ) ++{ ++ EFI_STATUS Status; ++ ++ Status = SharedMemory->CsvAllocateSharedMemory ( ++ SharedMemory, ++ Pages, ++ (UINT64*)Address ++ ); ++ ++ return Status; ++} ++ ++STATIC ++EFI_STATUS ++EFIAPI ++CsvFreeSharedPage( ++ IN UINTN Pages, ++ IN VOID *HostAddress ++ ) ++{ ++ EFI_STATUS Status; ++ ++ Status = SharedMemory->CsvFreeSharedMemory ( ++ SharedMemory, ++ Pages, ++ (UINTN)HostAddress ++ ); ++ ++ return Status; ++} ++ ++/** ++ Provides the controller-specific addresses required to access system memory ++ from a DMA bus master. ++ On CSV guest, the DMA openerations must be done on non-secure memory which ++ is the shared memory between the guest and QEMU. ++ ++ @param This The protocol instance pointer. ++ @param Operation Indicates if the bus master is going to read or ++ write to system memory. ++ @param HostAddress The system memory address to map to the PCI ++ controller. ++ @param NumberOfBytes On input the number of bytes to map. On output ++ the number of bytes that were mapped. ++ @param DeviceAddress The resulting map address for the bus master ++ PCI controller to use to access the hosts ++ HostAddress. ++ @param Mapping A resulting value to pass to Unmap(). ++ ++ @retval EFI_SUCCESS The range was mapped for the returned ++ NumberOfBytes. ++ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common ++ buffer. ++ @retval EFI_INVALID_PARAMETER One or more parameters are invalid. ++ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a ++ lack of resources. ++ @retval EFI_DEVICE_ERROR The system hardware could not map the requested ++ address. ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvIoMmuMap ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN EDKII_IOMMU_OPERATION Operation, ++ IN VOID *HostAddress, ++ IN OUT UINTN *NumberOfBytes, ++ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, ++ OUT VOID **Mapping ++ ) ++{ ++ EFI_STATUS Status; ++ MAP_INFO *MapInfo; ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: Operation=%a Operation=%u Host=0x%p Bytes=0x%Lx\n", ++ __FUNCTION__, ++ ((Operation >= 0 && ++ Operation < ARRAY_SIZE (mBusMasterOperationName)) ? ++ mBusMasterOperationName[Operation] : ++ "Invalid"), ++ Operation, ++ HostAddress, ++ (UINT64)((NumberOfBytes == NULL) ? 0 : *NumberOfBytes) ++ )); ++ ++ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || ++ Mapping == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is ++ // called later. ++ // ++ MapInfo = AllocatePool (sizeof (MAP_INFO)); ++ if (MapInfo == NULL) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto Failed; ++ } ++ ++ ZeroMem (&MapInfo->Link, sizeof MapInfo->Link); ++ MapInfo->Operation = Operation; ++ MapInfo->NumberOfBytes = *NumberOfBytes; ++ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes); ++ MapInfo->Signature = MAP_INFO_SIG; ++ ++ switch (Operation) { ++ // ++ // For BusMasterRead[64] and BusMasterWrite[64] operations, a bounce buffer ++ // is necessary regardless of whether the original (crypted) buffer crosses ++ // the 4GB limit or not -- we have to allocate a separate plaintext buffer. ++ // The only variable is whether the plaintext buffer should be under 4GB. ++ // ++ case EdkiiIoMmuOperationBusMasterRead: ++ case EdkiiIoMmuOperationBusMasterWrite: ++ // ++ // fall through ++ // ++ case EdkiiIoMmuOperationBusMasterRead64: ++ case EdkiiIoMmuOperationBusMasterWrite64: ++ // ++ // Allocate the implicit plaintext bounce buffer. ++ // ++ Status = CsvAllocSharedPage ( ++ MapInfo->NumberOfPages, ++ &MapInfo->UnSecureAddress ++ ); ++ if (EFI_ERROR (Status)) { ++ goto FreeMapInfo; ++ } ++ MapInfo->SecureAddress = (UINTN)HostAddress; ++ if (Operation == EdkiiIoMmuOperationBusMasterRead || ++ Operation == EdkiiIoMmuOperationBusMasterRead64) { ++ CopyMem ( ++ (VOID *) (UINTN) MapInfo->UnSecureAddress, ++ (VOID *) (UINTN) MapInfo->SecureAddress, ++ MapInfo->NumberOfBytes ++ ); ++ } ++ break; ++ ++ // ++ // For BusMasterCommonBuffer[64] operations, ++ // AllocateBuffer already returns the plain-text, ++ // No need to decrypt the data. ++ // ++ case EdkiiIoMmuOperationBusMasterCommonBuffer: ++ case EdkiiIoMmuOperationBusMasterCommonBuffer64: ++ MapInfo->UnSecureAddress = (UINTN)HostAddress; ++ MapInfo->SecureAddress = (UINTN)HostAddress; ++ break; ++ ++ default: ++ // ++ // Operation is invalid ++ // ++ Status = EFI_INVALID_PARAMETER; ++ goto FreeMapInfo; ++ } ++ ++ // ++ // Track all MAP_INFO structures. ++ // ++ InsertHeadList (&mMapInfos, &MapInfo->Link); ++ // ++ // Populate output parameters. ++ // ++ *DeviceAddress = MapInfo->UnSecureAddress; ++ *Mapping = MapInfo; ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: Mapping=0x%p Device=0x%Lx Host=0x%Lx Pages=0x%Lx\n", ++ __FUNCTION__, ++ MapInfo, ++ MapInfo->UnSecureAddress, ++ MapInfo->SecureAddress, ++ (UINT64)MapInfo->NumberOfPages ++ )); ++ ++ return EFI_SUCCESS; ++ ++FreeMapInfo: ++ FreePool (MapInfo); ++ ++Failed: ++ *NumberOfBytes = 0; ++ return Status; ++} ++ ++/** ++ Completes the Map() operation and releases any corresponding resources. ++ ++ This is an internal worker function that only extends the Map() API with ++ the MemoryMapLocked parameter. ++ ++ @param This The protocol instance pointer. ++ @param Mapping The mapping value returned from Map(). ++ @param MemoryMapLocked The function is executing on the stack of ++ gBS->ExitBootServices(); changes to the UEFI ++ memory map are forbidden. ++ ++ @retval EFI_SUCCESS The range was unmapped. ++ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by ++ Map(). ++ @retval EFI_DEVICE_ERROR The data was not committed to the target system ++ memory. ++**/ ++STATIC ++EFI_STATUS ++EFIAPI ++CsvIoMmuUnmapWorker ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN VOID *Mapping, ++ IN BOOLEAN MemoryMapLocked ++ ) ++{ ++ MAP_INFO *MapInfo; ++ EDKII_IOMMU_OPERATION Operation; ++ ++ if (Mapping == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ MapInfo = (MAP_INFO *)Mapping; ++ Operation = MapInfo->Operation; ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: Mapping=0x%p MemoryMapLocked=%d Operation %a Operation %d\n", ++ __FUNCTION__, ++ Mapping, ++ MemoryMapLocked, ++ ((Operation >= 0 && ++ Operation < ARRAY_SIZE (mBusMasterOperationName)) ? ++ mBusMasterOperationName[Operation] : ++ "Invalid"), ++ Operation ++ )); ++ ++ switch (MapInfo->Operation) { ++ case EdkiiIoMmuOperationBusMasterWrite: ++ case EdkiiIoMmuOperationBusMasterWrite64: ++ CopyMem ( ++ (VOID *) (UINTN) MapInfo->SecureAddress, ++ (VOID *) (UINTN) MapInfo->UnSecureAddress, ++ MapInfo->NumberOfBytes ++ ); ++ case EdkiiIoMmuOperationBusMasterRead: ++ case EdkiiIoMmuOperationBusMasterRead64: ++ ZeroMem ( ++ (VOID *)(UINTN)MapInfo->UnSecureAddress, ++ EFI_PAGES_TO_SIZE (MapInfo->NumberOfPages) ++ ); ++ CsvFreeSharedPage( ++ MapInfo->NumberOfPages, ++ (VOID*)(UINTN)MapInfo->UnSecureAddress ++ ); ++ ++ default: ++ break; ++ } ++ ++ // ++ // Forget the MAP_INFO structure, then free it (unless the UEFI memory map is ++ // locked). ++ // ++ RemoveEntryList (&MapInfo->Link); ++ if (!MemoryMapLocked) { ++ FreePool (MapInfo); ++ } ++ ++ return EFI_SUCCESS; ++ ++} ++ ++/** ++ Completes the Map() operation and releases any corresponding resources. ++ ++ @param This The protocol instance pointer. ++ @param Mapping The mapping value returned from Map(). ++ ++ @retval EFI_SUCCESS The range was unmapped. ++ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by ++ Map(). ++ @retval EFI_DEVICE_ERROR The data was not committed to the target system ++ memory. ++**/ ++EFI_STATUS ++EFIAPI ++CsvIoMmuUnmap ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN VOID *Mapping ++ ) ++{ ++ return CsvIoMmuUnmapWorker ( ++ This, ++ Mapping, ++ FALSE // MemoryMapLocked ++ ); ++} ++ ++/** ++ Allocates pages that are suitable for an OperationBusMasterCommonBuffer or ++ OperationBusMasterCommonBuffer64 mapping. ++ ++ @param This The protocol instance pointer. ++ @param Type This parameter is not used and must be ignored. ++ @param MemoryType The type of memory to allocate, ++ EfiBootServicesData or EfiRuntimeServicesData. ++ @param Pages The number of pages to allocate. ++ @param HostAddress A pointer to store the base system memory ++ address of the allocated range. ++ @param Attributes The requested bit mask of attributes for the ++ allocated range. ++ ++ @retval EFI_SUCCESS The requested memory pages were allocated. ++ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal ++ attribute bits are MEMORY_WRITE_COMBINE and ++ MEMORY_CACHED. ++ @retval EFI_INVALID_PARAMETER One or more parameters are invalid. ++ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvIoMmuAllocateBuffer ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN EFI_ALLOCATE_TYPE Type, ++ IN EFI_MEMORY_TYPE MemoryType, ++ IN UINTN Pages, ++ IN OUT VOID **HostAddress, ++ IN UINT64 Attributes ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_PHYSICAL_ADDRESS PhysicalAddress; ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: MemoryType=%u Pages=0x%Lx Attributes=0x%Lx\n", ++ __FUNCTION__, ++ (UINT32)MemoryType, ++ (UINT64)Pages, ++ Attributes ++ )); ++ ++ // ++ // Validate Attributes ++ // ++ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) { ++ return EFI_UNSUPPORTED; ++ } ++ ++ // ++ // Check for invalid inputs ++ // ++ if (HostAddress == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // The only valid memory types are EfiBootServicesData and ++ // EfiRuntimeServicesData ++ // ++ if (MemoryType != EfiBootServicesData && ++ MemoryType != EfiRuntimeServicesData) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // We'll need a header page for the COMMON_BUFFER_HEADER structure. ++ // ++ if (Pages > MAX_UINTN - 1) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ Status = CsvAllocSharedPage (Pages,&PhysicalAddress); ++ if (Status != EFI_SUCCESS){ ++ goto error; ++ } ++ ++ ++ *HostAddress = (VOID *)(UINTN)PhysicalAddress; ++ ++ return EFI_SUCCESS; ++ ++error: ++ return Status; ++} ++ ++/** ++ Frees memory that was allocated with AllocateBuffer(). ++ ++ @param This The protocol instance pointer. ++ @param Pages The number of pages to free. ++ @param HostAddress The base system memory address of the allocated ++ range. ++ ++ @retval EFI_SUCCESS The requested memory pages were freed. ++ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and ++ Pages was not allocated with AllocateBuffer(). ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvIoMmuFreeBuffer ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN UINTN Pages, ++ IN VOID *HostAddress ++ ) ++{ ++ ++ EFI_STATUS Status; ++ ++ if (HostAddress == NULL || Pages == 0) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "%a: Host=0x%p Pages=0x%Lx\n", ++ __FUNCTION__, ++ HostAddress, ++ (UINT64)Pages ++ )); ++ ++ Status = CsvFreeSharedPage (Pages, HostAddress); ++ ++ return Status; ++} ++ ++ ++/** ++ Set IOMMU attribute for a system memory. ++ ++ @param[in] This The protocol instance pointer. ++ @param[in] DeviceHandle The device who initiates the DMA access ++ request. ++ @param[in] Mapping The mapping value returned from Map(). ++ @param[in] IoMmuAccess The IOMMU access. ++ ++ @retval EFI_SUCCESS The IoMmuAccess is set for the memory range ++ specified by DeviceAddress and Length. ++ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle. ++ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by ++ Map(). ++ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination ++ of access. ++ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU. ++ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported ++ by the IOMMU. ++ @retval EFI_UNSUPPORTED The IOMMU does not support the memory range ++ specified by Mapping. ++ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to ++ modify the IOMMU access. ++ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while ++ attempting the operation. ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvIoMmuSetAttribute ( ++ IN EDKII_IOMMU_PROTOCOL *This, ++ IN EFI_HANDLE DeviceHandle, ++ IN VOID *Mapping, ++ IN UINT64 IoMmuAccess ++ ) ++{ ++ return EFI_UNSUPPORTED; ++} ++ ++EDKII_IOMMU_PROTOCOL mCsv = { ++ EDKII_IOMMU_PROTOCOL_REVISION, ++ CsvIoMmuSetAttribute, ++ CsvIoMmuMap, ++ CsvIoMmuUnmap, ++ CsvIoMmuAllocateBuffer, ++ CsvIoMmuFreeBuffer, ++}; ++ ++/** ++ Initialize Iommu Protocol. ++ ++**/ ++EFI_STATUS ++EFIAPI ++CsvInstallIoMmuProtocol ( ++ VOID ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_HANDLE Handle; ++ ++ Status = gBS->LocateProtocol ( ++ &gCsvSharedMemoryProtocolGuid, ++ NULL, ++ (VOID**)&SharedMemory ++ ); ++ ++ if (EFI_ERROR (Status)) { ++ goto error; ++ } ++ ++ Handle = NULL; ++ Status = gBS->InstallMultipleProtocolInterfaces ( ++ &Handle, ++ &gEdkiiIoMmuProtocolGuid, ++ &mCsv, ++ NULL ++ ); ++ if (EFI_ERROR (Status)) { ++ goto error; ++ } ++ ++ return EFI_SUCCESS; ++ ++error: ++ return Status; ++} +diff --git a/OvmfPkg/IoMmuDxe/CsvIoMmu.h b/OvmfPkg/IoMmuDxe/CsvIoMmu.h +new file mode 100644 +index 0000000..d48a02c +--- /dev/null ++++ b/OvmfPkg/IoMmuDxe/CsvIoMmu.h +@@ -0,0 +1,29 @@ ++/** @file ++ ++ The protocol provides support to allocate, free, map and umap a DMA buffer ++ for bus master (e.g PciHostBridge). When CSV is enabled, the DMA operations ++ must be performed on unencrypted buffer hence protocol clear the encryption ++ bit from the DMA buffer. ++ ++ Copyright (c) 2022, HYGON. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _CSV_IOMMU_H_ ++#define _CSV_IOMMU_H_ ++ ++EFI_STATUS ++EFIAPI ++CsvInstallIoMmuProtocol ( ++ VOID ++ ); ++ ++#endif +diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.c b/OvmfPkg/IoMmuDxe/IoMmuDxe.c +index 13df8ba..35e5df9 100644 +--- a/OvmfPkg/IoMmuDxe/IoMmuDxe.c ++++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.c +@@ -9,7 +9,9 @@ + + **/ + ++#include + #include "AmdSevIoMmu.h" ++#include "CsvIoMmu.h" + + EFI_STATUS + EFIAPI +@@ -21,6 +23,14 @@ IoMmuDxeEntryPoint ( + EFI_STATUS Status; + EFI_HANDLE Handle; + ++ if (CsvIsEnabled ()) { ++ Status = CsvInstallIoMmuProtocol (); ++ if (Status != EFI_SUCCESS) { ++ DEBUG((EFI_D_ERROR, "fail to install CSV IOMMU\n")); ++ } ++ return Status; ++ } ++ + // + // When SEV is enabled, install IoMmu protocol otherwise install the + // placeholder protocol so that other dependent module can run. +diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf +index 2ebd74e..6b89c6a 100644 +--- a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf ++++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf +@@ -21,6 +21,8 @@ + AmdSevIoMmu.c + AmdSevIoMmu.h + IoMmuDxe.c ++ CsvIoMmu.c ++ CsvIoMmu.h + + [Packages] + MdePkg/MdePkg.dec +@@ -35,10 +37,12 @@ + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint ++ CsvLib + + [Protocols] + gEdkiiIoMmuProtocolGuid ## SOMETIME_PRODUCES + gIoMmuAbsentProtocolGuid ## SOMETIME_PRODUCES ++ gCsvSharedMemoryProtocolGuid + + [Depex] +- TRUE ++ gCsvSharedMemoryProtocolGuid +-- +2.17.1 + diff --git a/0038-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch b/0038-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch new file mode 100644 index 0000000..6aeeadf --- /dev/null +++ b/0038-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch @@ -0,0 +1,137 @@ +From 8a7ac3e25c1e8a62852a64d0a303e948b0e1499a Mon Sep 17 00:00:00 2001 +From: Xin Jiang +Date: Tue, 15 Aug 2023 17:15:53 +0800 +Subject: [PATCH 38/46] anolis: OvmfPkg: Reserve a CPUID table page for CSV + guest + +Reserve a page for CPUID table which will be initialized by firmware. +In future, A CSV guest should get CPUID value from a CPUID table +which has been validated by firmware rather than requesting them from +hypervisor via a VMGEXIT. + +Signed-off-by: Xin Jiang +Change-Id: Ic09af8667c65ac83eef5a2a4a1e69d0506cd89d7 +--- + OvmfPkg/OvmfPkg.dec | 4 ++++ + OvmfPkg/OvmfPkgX64.fdf | 3 +++ + OvmfPkg/PlatformPei/Csv.c | 6 ++++++ + OvmfPkg/PlatformPei/PlatformPei.inf | 2 ++ + OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 15 +++++++++++++++ + OvmfPkg/ResetVector/ResetVector.inf | 2 ++ + OvmfPkg/ResetVector/ResetVector.nasmb | 2 ++ + 7 files changed, 34 insertions(+) + +diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec +index d8f9be3..7e6a6a2 100644 +--- a/OvmfPkg/OvmfPkg.dec ++++ b/OvmfPkg/OvmfPkg.dec +@@ -359,6 +359,10 @@ + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|0|UINT32|0x58 + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize|0|UINT32|0x59 + ++ ## the base address of the cpuid table page used by CSV. ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|0|UINT32|0x60 ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize|0|UINT32|0x61 ++ + [PcdsDynamic, PcdsDynamicEx] + gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 +diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf +index 0f04acb..04efa62 100644 +--- a/OvmfPkg/OvmfPkgX64.fdf ++++ b/OvmfPkg/OvmfPkgX64.fdf +@@ -91,6 +91,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.P + 0x00D000|0x002000 + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize + ++0x00F000|0x001000 ++gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize ++ + 0x010000|0x010000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + +diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c +index 44e81e1..f7c87ac 100644 +--- a/OvmfPkg/PlatformPei/Csv.c ++++ b/OvmfPkg/PlatformPei/Csv.c +@@ -56,6 +56,12 @@ CsvInitializeMemInfo ( + (UINT64)(UINTN) FixedPcdGet32 (PcdCsvDefaultSecureCallSize), + EfiReservedMemoryType + ); ++ ++ BuildMemoryAllocationHob ( ++ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdOvmfCsvCpuidBase), ++ (UINT64)(UINTN) FixedPcdGet32 (PcdOvmfCsvCpuidSize), ++ EfiReservedMemoryType ++ ); + } + + VOID +diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf +index cb0582c..bed4dcf 100644 +--- a/OvmfPkg/PlatformPei/PlatformPei.inf ++++ b/OvmfPkg/PlatformPei/PlatformPei.inf +@@ -123,6 +123,8 @@ + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize + + [FeaturePcd] + gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable +diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm +index c32b608..f282692 100644 +--- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm ++++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm +@@ -63,6 +63,21 @@ csvSecureCallBase: + DB 0xAB, 0x21, 0x6B, 0x27, 0x5D, 0x55, 0x56, 0xA5 + csvSecureCallEnd: + ++; ++; CSV cpuid table ++; ++; Provide cpuid table page when boot up for CSV guest ++; ++; GUID : 1b4c70e6-07e6-4e4e-8f28-0eaf871a0752 ++; ++csvCpuidTableBase: ++ DD CSV_CPUID_TABLE_SIZE ++ DD CSV_CPUID_TABLE_BASE ++ DW csvCpuidTableEnd - csvCpuidTableBase ++ DB 0xE6, 0x70, 0x4C, 0x1B, 0xE6, 0x07, 0x4E, 0x4E ++ DB 0x8F, 0x28, 0x0E, 0xAF, 0x87, 0x1A, 0x07, 0x52 ++csvCpuidTableEnd: ++ + ; + ; TDX Metadata offset block + ; +diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf +index 38c1720..e35c17b 100644 +--- a/OvmfPkg/ResetVector/ResetVector.inf ++++ b/OvmfPkg/ResetVector/ResetVector.inf +@@ -37,6 +37,8 @@ + gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase +diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb +index ca00f64..4e7c7ad 100644 +--- a/OvmfPkg/ResetVector/ResetVector.nasmb ++++ b/OvmfPkg/ResetVector/ResetVector.nasmb +@@ -106,6 +106,8 @@ + + %define CSV_DEFAULT_SECURE_CALL_BASE FixedPcdGet32 (PcdCsvDefaultSecureCallBase) + %define CSV_DEFAULT_SECURE_CALL_SIZE FixedPcdGet32 (PcdCsvDefaultSecureCallSize) ++ %define CSV_CPUID_TABLE_BASE FixedPcdGet32 (PcdOvmfCsvCpuidBase) ++ %define CSV_CPUID_TABLE_SIZE FixedPcdGet32 (PcdOvmfCsvCpuidSize) + + %include "X64/IntelTdxMetadata.asm" + %include "Ia32/Flat32ToFlat64.asm" +-- +2.17.1 + diff --git a/0039-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch b/0039-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch new file mode 100644 index 0000000..a8c2c34 --- /dev/null +++ b/0039-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch @@ -0,0 +1,325 @@ +From 118d8bd819dfd2300798481d8c89a9c37e54a32c Mon Sep 17 00:00:00 2001 +From: Ashish Kalra +Date: Thu, 19 Aug 2021 12:35:50 +0000 +Subject: [PATCH 39/46] OvmfPkg/BaseMemEncryptLib: Detect SEV live migration + feature. + +Add support to check if we are running inside KVM HVM and +KVM HVM supports SEV Live Migration feature. + +Cc: Jordan Justen +Cc: Ard Biesheuvel +Signed-off-by: Ashish Kalra +Change-Id: I29fa5047198c9c3c6965c36b5e221b48c277dfc9 +--- + OvmfPkg/Include/Library/MemEncryptSevLib.h | 12 ++++ + .../DxeMemEncryptSevLibInternal.c | 41 +++++++++++++ + .../PeiDxeMemEncryptSevLibInternal.c | 57 +++++++++++++++++++ + .../PeiDxeMemEncryptSevLibInternal.h | 31 ++++++++++ + .../PeiMemEncryptSevLibInternal.c | 41 +++++++++++++ + .../SecMemEncryptSevLibInternal.c | 18 ++++++ + 6 files changed, 200 insertions(+) + create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h + +diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h +index adc490e..ea251f1 100644 +--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h ++++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h +@@ -71,6 +71,18 @@ MemEncryptSevIsEnabled ( + VOID + ); + ++/** ++ Returns a boolean to indicate whether SEV live migration is enabled. ++ ++ @retval TRUE SEV live migration is enabled ++ @retval FALSE SEV live migration is not enabled ++**/ ++BOOLEAN ++EFIAPI ++MemEncryptSevLiveMigrationIsEnabled ( ++ VOID ++ ); ++ + /** + This function clears memory encryption bit for the memory region specified by + BaseAddress and NumPages from the current page table context. +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c +index 2816f85..df73a83 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c +@@ -17,9 +17,13 @@ + #include + #include + ++#include "PeiDxeMemEncryptSevLibInternal.h" ++ + STATIC BOOLEAN mSevStatus = FALSE; + STATIC BOOLEAN mSevEsStatus = FALSE; + STATIC BOOLEAN mSevStatusChecked = FALSE; ++STATIC BOOLEAN mSevLiveMigrationStatus = FALSE; ++STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE; + + STATIC UINT64 mSevEncryptionMask = 0; + STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE; +@@ -106,6 +110,24 @@ MemEncryptSevEsIsEnabled ( + return mSevEsStatus; + } + ++/** ++ Figures out if we are running inside KVM HVM and ++ KVM HVM supports SEV Live Migration feature. ++**/ ++STATIC ++VOID ++EFIAPI ++InternalDetectSevLiveMigrationFeature ( ++ VOID ++ ) ++{ ++ if (KvmDetectSevLiveMigrationFeature ()) { ++ mSevLiveMigrationStatus = TRUE; ++ } ++ ++ mSevLiveMigrationStatusChecked = TRUE; ++} ++ + /** + Returns a boolean to indicate whether SEV is enabled. + +@@ -125,6 +147,25 @@ MemEncryptSevIsEnabled ( + return mSevStatus; + } + ++/** ++ Returns a boolean to indicate whether SEV live migration is enabled. ++ ++ @retval TRUE SEV live migration is enabled ++ @retval FALSE SEV live migration is not enabled ++**/ ++BOOLEAN ++EFIAPI ++MemEncryptSevLiveMigrationIsEnabled ( ++ VOID ++ ) ++{ ++ if (!mSevLiveMigrationStatusChecked) { ++ InternalDetectSevLiveMigrationFeature (); ++ } ++ ++ return mSevLiveMigrationStatus; ++} ++ + /** + Returns the SEV encryption mask. + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c +index b4a9f46..30f2d90 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c +@@ -16,6 +16,8 @@ + #include + #include + ++#include "PeiDxeMemEncryptSevLibInternal.h" ++ + /** + Locate the page range that covers the initial (pre-SMBASE-relocation) SMRAM + Save State Map. +@@ -61,3 +63,58 @@ MemEncryptSevLocateInitialSmramSaveStateMapPages ( + + return RETURN_SUCCESS; + } ++ ++/** ++ Figures out if we are running inside KVM HVM and ++ KVM HVM supports SEV Live Migration feature. ++ ++ @retval TRUE SEV live migration is supported. ++ @retval FALSE SEV live migration is not supported. ++**/ ++BOOLEAN ++EFIAPI ++KvmDetectSevLiveMigrationFeature ( ++ VOID ++ ) ++{ ++ CHAR8 Signature[13]; ++ UINT32 mKvmLeaf; ++ UINT32 RegEax; ++ UINT32 RegEbx; ++ UINT32 RegEcx; ++ UINT32 RegEdx; ++ ++ Signature[12] = '\0'; ++ for (mKvmLeaf = 0x40000000; mKvmLeaf < 0x40010000; mKvmLeaf += 0x100) { ++ AsmCpuid ( ++ mKvmLeaf, ++ NULL, ++ (UINT32 *) &Signature[0], ++ (UINT32 *) &Signature[4], ++ (UINT32 *) &Signature[8]); ++ ++ if (AsciiStrCmp (Signature, "KVMKVMKVM") == 0) { ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: KVM Detected, signature = %a\n", ++ __FUNCTION__, ++ Signature ++ )); ++ ++ RegEax = mKvmLeaf + 1; ++ RegEcx = 0; ++ AsmCpuid (mKvmLeaf + 1, &RegEax, &RegEbx, &RegEcx, &RegEdx); ++ if ((RegEax & KVM_FEATURE_MIGRATION_CONTROL) != 0) { ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: SEV Live Migration feature supported\n", ++ __FUNCTION__ ++ )); ++ ++ return TRUE; ++ } ++ } ++ } ++ ++ return FALSE; ++} +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h +new file mode 100644 +index 0000000..30cf5de +--- /dev/null ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h +@@ -0,0 +1,31 @@ ++/** @file ++ ++ Secure Encrypted Virtualization (SEV) library helper function ++ ++ Copyright (c) 2021, AMD Incorporated. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#ifndef PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_ ++#define PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_ ++ ++#include ++ ++#define KVM_FEATURE_MIGRATION_CONTROL BIT17 ++ ++/** ++ Figures out if we are running inside KVM HVM and ++ KVM HVM supports SEV Live Migration feature. ++ ++ @retval TRUE SEV live migration is supported. ++ @retval FALSE SEV live migration is not supported. ++**/ ++BOOLEAN ++EFIAPI ++KvmDetectSevLiveMigrationFeature( ++ VOID ++ ); ++ ++#endif // PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_ +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c +index e2fd109..9293b56 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c +@@ -17,9 +17,13 @@ + #include + #include + ++#include "PeiDxeMemEncryptSevLibInternal.h" ++ + STATIC BOOLEAN mSevStatus = FALSE; + STATIC BOOLEAN mSevEsStatus = FALSE; + STATIC BOOLEAN mSevStatusChecked = FALSE; ++STATIC BOOLEAN mSevLiveMigrationStatus = FALSE; ++STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE; + + STATIC UINT64 mSevEncryptionMask = 0; + STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE; +@@ -87,6 +91,24 @@ InternalMemEncryptSevStatus ( + mSevStatusChecked = TRUE; + } + ++/** ++ Figures out if we are running inside KVM HVM and ++ KVM HVM supports SEV Live Migration feature. ++**/ ++STATIC ++VOID ++EFIAPI ++InternalDetectSevLiveMigrationFeature ( ++ VOID ++ ) ++{ ++ if (KvmDetectSevLiveMigrationFeature ()) { ++ mSevLiveMigrationStatus = TRUE; ++ } ++ ++ mSevLiveMigrationStatusChecked = TRUE; ++} ++ + /** + Returns a boolean to indicate whether SEV-ES is enabled. + +@@ -125,6 +147,25 @@ MemEncryptSevIsEnabled ( + return mSevStatus; + } + ++/** ++ Returns a boolean to indicate whether SEV live migration is enabled. ++ ++ @retval TRUE SEV live migration is enabled ++ @retval FALSE SEV live migration is not enabled ++**/ ++BOOLEAN ++EFIAPI ++MemEncryptSevLiveMigrationIsEnabled ( ++ VOID ++ ) ++{ ++ if (!mSevLiveMigrationStatusChecked) { ++ InternalDetectSevLiveMigrationFeature (); ++ } ++ ++ return mSevLiveMigrationStatus; ++} ++ + /** + Returns the SEV encryption mask. + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c +index 56d8f3f..d9f7bef 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c +@@ -100,6 +100,24 @@ MemEncryptSevIsEnabled ( + return Msr.Bits.SevBit ? TRUE : FALSE; + } + ++/** ++ Returns a boolean to indicate whether SEV live migration is enabled. ++ ++ @retval TRUE SEV live migration is enabled ++ @retval FALSE SEV live migration is not enabled ++**/ ++BOOLEAN ++EFIAPI ++MemEncryptSevLiveMigrationIsEnabled ( ++ VOID ++ ) ++{ ++ // ++ // Not used in SEC phase. ++ // ++ return FALSE; ++} ++ + /** + Returns the SEV encryption mask. + +-- +2.17.1 + diff --git a/0040-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch b/0040-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch new file mode 100644 index 0000000..205c5b1 --- /dev/null +++ b/0040-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch @@ -0,0 +1,298 @@ +From f622069729e0abc9b676af25a90b9e142419cf1a Mon Sep 17 00:00:00 2001 +From: Ashish Kalra +Date: Thu, 19 Aug 2021 13:03:00 +0000 +Subject: [PATCH 40/46] OvmfPkg/BaseMemEncryptLib: Hypercall API for page + encryption state change + +Add API to issue hypercall on page encryption state change. + +By default all the SEV guest memory regions are considered encrypted, +if a guest changes the encryption attribute of the page (e.g mark a +page as decrypted) then notify hypervisor. Hypervisor will need to +track the unencrypted pages. The information will be used during +guest live migration, guest page migration and guest debugging. + +This hypercall is used to notify hypervisor when the page's +encryption state changes. + +Cc: Jordan Justen +Cc: Ard Biesheuvel +Signed-off-by: Brijesh Singh +Signed-off-by: Ashish Kalra +Change-Id: Ic0dcf854947f35f633137d2bb052dc79d111971f +--- + OvmfPkg/Include/Library/MemEncryptSevLib.h | 52 +++++++++++++++ + .../DxeMemEncryptSevLib.inf | 1 + + .../Ia32/MemEncryptSevLib.c | 27 ++++++++ + .../PeiMemEncryptSevLib.inf | 1 + + .../SecMemEncryptSevLibInternal.c | 20 ++++++ + .../X64/AsmHelperStub.nasm | 33 ++++++++++ + .../X64/MemEncryptSevLib.c | 64 +++++++++++++++++++ + 7 files changed, 198 insertions(+) + create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm + +diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h +index ea251f1..8ed6242 100644 +--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h ++++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h +@@ -215,4 +215,56 @@ MemEncryptSevClearMmioPageEncMask ( + IN UINTN NumPages + ); + ++/** ++ This hypercall is used to notify hypervisor when the page's encryption ++ state changes. ++ ++ @param[in] PhysicalAddress The physical address that is the start address ++ of a memory region. ++ @param[in] Pages Number of pages in memory region. ++ @param[in] IsEncrypted Encrypted or Decrypted. ++ ++ @retval RETURN_SUCCESS Hypercall returned success. ++ @retval RETURN_UNSUPPORTED Hypercall not supported. ++ @retval RETURN_NO_MAPPING Hypercall returned error. ++**/ ++RETURN_STATUS ++EFIAPI ++SetMemoryEncDecHypercall3 ( ++ IN UINTN PhysicalAddress, ++ IN UINTN Pages, ++ IN BOOLEAN IsEncrypted ++ ); ++ ++#define KVM_HC_MAP_GPA_RANGE 12 ++#define KVM_MAP_GPA_RANGE_PAGE_SZ_4K 0 ++#define KVM_MAP_GPA_RANGE_PAGE_SZ_2M BIT0 ++#define KVM_MAP_GPA_RANGE_PAGE_SZ_1G BIT1 ++#define KVM_MAP_GPA_RANGE_ENC_STATE(n) ((n) << 4) ++#define KVM_MAP_GPA_RANGE_ENCRYPTED KVM_MAP_GPA_RANGE_ENC_STATE(1) ++#define KVM_MAP_GPA_RANGE_DECRYPTED KVM_MAP_GPA_RANGE_ENC_STATE(0) ++ ++/** ++ Interface exposed by the ASM implementation of the core hypercall ++ ++ @param[in] HypercallNum KVM_HC_MAP_GPA_RANGE hypercall. ++ @param[in] PhysicalAddress The physical address that is the start address ++ of a memory region. ++ @param[in] Pages Number of pages in memory region. ++ @param[in] Attributes Bits 3:0 - preferred page size encoding, ++ 0 = 4kb, 1 = 2mb, 2 = 1gb, etc... ++ Bit 4 - plaintext = 0, encrypted = 1 ++ Bits 63:5 - reserved (must be zero) ++ ++ @retval Hypercall returned status. ++**/ ++UINTN ++EFIAPI ++SetMemoryEncDecHypercall3AsmStub ( ++ IN UINTN HypercallNum, ++ IN UINTN PhysicalAddress, ++ IN UINTN Pages, ++ IN UINTN Attributes ++ ); ++ + #endif // _MEM_ENCRYPT_SEV_LIB_H_ +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +index dc32929..8ea8d3a 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +@@ -38,6 +38,7 @@ + X64/PeiDxeVirtualMemory.c + X64/VirtualMemory.c + X64/VirtualMemory.h ++ X64/AsmHelperStub.nasm + + [Sources.IA32] + Ia32/MemEncryptSevLib.c +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c +index be260e0..516d639 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c +@@ -136,3 +136,30 @@ MemEncryptSevClearMmioPageEncMask ( + // + return RETURN_UNSUPPORTED; + } ++ ++/** ++ This hyercall is used to notify hypervisor when the page's encryption ++ state changes. ++ ++ @param[in] PhysicalAddress The physical address that is the start address ++ of a memory region. ++ @param[in] Pages Number of Pages in the memory region. ++ @param[in] IsEncrypted Encrypted or Decrypted. ++ ++ @retval RETURN_SUCCESS Hypercall returned success. ++ @retval RETURN_UNSUPPORTED Hypercall not supported. ++ @retval RETURN_NO_MAPPING Hypercall returned error. ++**/ ++RETURN_STATUS ++EFIAPI ++SetMemoryEncDecHypercall3 ( ++ IN UINTN PhysicalAddress, ++ IN UINTN Pages, ++ IN BOOLEAN IsEncrypted ++ ) ++{ ++ // ++ // Memory encryption bit is not accessible in 32-bit mode ++ // ++ return RETURN_UNSUPPORTED; ++} +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf +index 03a78c3..3233ca7 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf +@@ -38,6 +38,7 @@ + X64/PeiDxeVirtualMemory.c + X64/VirtualMemory.c + X64/VirtualMemory.h ++ X64/AsmHelperStub.nasm + + [Sources.IA32] + Ia32/MemEncryptSevLib.c +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c +index d9f7bef..ebb1c39 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c +@@ -118,6 +118,26 @@ MemEncryptSevLiveMigrationIsEnabled ( + return FALSE; + } + ++/** ++ Interface exposed by the ASM implementation of the core hypercall ++ ++ @retval Hypercall returned status. ++**/ ++UINTN ++EFIAPI ++SetMemoryEncDecHypercall3AsmStub ( ++ IN UINTN HypercallNum, ++ IN UINTN PhysicalAddress, ++ IN UINTN Pages, ++ IN UINTN Attributes ++ ) ++{ ++ // ++ // Not used in SEC phase. ++ // ++ return RETURN_UNSUPPORTED; ++} ++ + /** + Returns the SEV encryption mask. + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm +new file mode 100644 +index 0000000..0ec35dd +--- /dev/null ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm +@@ -0,0 +1,33 @@ ++/** @file ++ ++ ASM helper stub to invoke hypercall ++ ++ Copyright (c) 2021, AMD Incorporated. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++DEFAULT REL ++SECTION .text ++ ++; UINTN ++; EFIAPI ++; SetMemoryEncDecHypercall3AsmStub ( ++; IN UINTN HypercallNum, ++; IN UINTN Arg1, ++; IN UINTN Arg2, ++; IN UINTN Arg3 ++; ); ++global ASM_PFX(SetMemoryEncDecHypercall3AsmStub) ++ASM_PFX(SetMemoryEncDecHypercall3AsmStub): ++ ; UEFI calling conventions require RBX to ++ ; be nonvolatile/callee-saved. ++ push rbx ++ mov rax, rcx ; Copy HypercallNumber to rax ++ mov rbx, rdx ; Copy Arg1 to the register expected by KVM ++ mov rcx, r8 ; Copy Arg2 to register expected by KVM ++ mov rdx, r9 ; Copy Arg3 to register expected by KVM ++ vmmcall ; Call VMMCALL ++ pop rbx ++ ret +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c +index a57e8fd..a6246d4 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c +@@ -143,3 +143,67 @@ MemEncryptSevClearMmioPageEncMask ( + ); + + } ++ ++/** ++ This hyercall is used to notify hypervisor when the page's encryption ++ state changes. ++ ++ @param[in] PhysicalAddress The physical address that is the start address ++ of a memory region. ++ @param[in] Pages Number of Pages in the memory region. ++ @param[in] IsEncrypted Encrypted or Decrypted. ++ ++ @retval RETURN_SUCCESS Hypercall returned success. ++ @retval RETURN_UNSUPPORTED Hypercall not supported. ++ @retval RETURN_NO_MAPPING Hypercall returned error. ++**/ ++RETURN_STATUS ++EFIAPI ++SetMemoryEncDecHypercall3 ( ++ IN UINTN PhysicalAddress, ++ IN UINTN Pages, ++ IN BOOLEAN IsEncrypted ++ ) ++{ ++ RETURN_STATUS Ret; ++ UINTN Error; ++ UINTN EncryptState; ++ ++ Ret = RETURN_UNSUPPORTED; ++ ++ if (MemEncryptSevLiveMigrationIsEnabled ()) { ++ Ret = RETURN_SUCCESS; ++ // ++ // The encryption bit is set/clear on the smallest page size, hence ++ // use the 4k page size in MAP_GPA_RANGE hypercall below. ++ // ++ // Also, when the GCD map is being walked and the c-bit being cleared ++ // from MMIO and NonExistent memory spaces, the physical address ++ // range being passed may not be page-aligned and adding an assert ++ // here prevents booting. Hence, rounding it down when calling ++ // SetMemoryEncDecHypercall3AsmStub below. ++ // ++ ++ EncryptState = IsEncrypted ? KVM_MAP_GPA_RANGE_ENCRYPTED : ++ KVM_MAP_GPA_RANGE_DECRYPTED; ++ ++ Error = SetMemoryEncDecHypercall3AsmStub ( ++ KVM_HC_MAP_GPA_RANGE, ++ PhysicalAddress & ~EFI_PAGE_MASK, ++ Pages, ++ KVM_MAP_GPA_RANGE_PAGE_SZ_4K | EncryptState ++ ); ++ ++ if (Error != 0) { ++ DEBUG ((DEBUG_ERROR, ++ "SetMemoryEncDecHypercall3 failed, Phys = %x, Pages = %d, Err = %Ld\n", ++ PhysicalAddress, ++ Pages, ++ (INT64)Error)); ++ ++ Ret = RETURN_NO_MAPPING; ++ } ++ } ++ ++ return Ret; ++} +-- +2.17.1 + diff --git a/0041-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch b/0041-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch new file mode 100644 index 0000000..1c865a3 --- /dev/null +++ b/0041-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch @@ -0,0 +1,91 @@ +From ee0ca422f17da55350c4da25ef9ca38127d79e3f Mon Sep 17 00:00:00 2001 +From: Ashish Kalra +Date: Thu, 19 Aug 2021 13:04:56 +0000 +Subject: [PATCH 41/46] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state + change hypercall + +Invoke the hypercall API to notify hypervisor when the page's +encryption state changes. + +Cc: Jordan Justen +Cc: Ard Biesheuvel +Signed-off-by: Brijesh Singh +Signed-off-by: Ashish Kalra +Change-Id: Ia61155777fe3bf66f1d059978c0e8b1d1c833ef7 +--- + .../X64/PeiDxeVirtualMemory.c | 20 +++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +index 6726010..0b67577 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +@@ -582,10 +582,13 @@ SetMemoryEncDec ( + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; + PAGE_TABLE_ENTRY *PageDirectory2MEntry; ++ PHYSICAL_ADDRESS OrigPhysicalAddress; + PAGE_TABLE_4K_ENTRY *PageTableEntry; + UINT64 PgTableMask; + UINT64 AddressEncMask; + BOOLEAN IsWpEnabled; ++ BOOLEAN CBitChanged; ++ UINTN OrigLength; + RETURN_STATUS Status; + PHYSICAL_ADDRESS PageAddress; + UINTN PageNum; +@@ -642,6 +645,9 @@ SetMemoryEncDec ( + } + + Status = EFI_SUCCESS; ++ OrigLength = Length; ++ CBitChanged = FALSE; ++ OrigPhysicalAddress = PhysicalAddress; + + while (Length != 0) + { +@@ -702,6 +708,7 @@ SetMemoryEncDec ( + )); + PhysicalAddress += BIT30; + Length -= BIT30; ++ CBitChanged = TRUE; + } else { + // + // We must split the page +@@ -756,6 +763,7 @@ SetMemoryEncDec ( + SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode); + PhysicalAddress += BIT21; + Length -= BIT21; ++ CBitChanged = TRUE; + } else { + // + // We must split up this page into 4K pages +@@ -798,6 +806,7 @@ SetMemoryEncDec ( + SetOrClearCBit (&PageTableEntry->Uint64, Mode); + PhysicalAddress += EFI_PAGE_SIZE; + Length -= EFI_PAGE_SIZE; ++ CBitChanged = TRUE; + } + } + } +@@ -815,6 +824,17 @@ SetMemoryEncDec ( + // + CpuFlushTlb(); + ++ // ++ // Notify Hypervisor on C-bit status ++ // ++ if (CBitChanged) { ++ Status = SetMemoryEncDecHypercall3 ( ++ OrigPhysicalAddress, ++ EFI_SIZE_TO_PAGES (OrigLength), ++ (Mode == SetCBit) ? TRUE : FALSE ++ ); ++ } ++ + Done: + // + // Restore page table write protection, if any. +-- +2.17.1 + diff --git a/0042-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch b/0042-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch new file mode 100644 index 0000000..c37eb4a --- /dev/null +++ b/0042-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch @@ -0,0 +1,46 @@ +From b9e68850125194c9c183a0ab2239a6c73b1d67c3 Mon Sep 17 00:00:00 2001 +From: Ashish Kalra +Date: Thu, 19 Aug 2021 13:06:40 +0000 +Subject: [PATCH 42/46] OvmfPkg/VmgExitLib: Encryption state change hypercall + support in VC handler + +Make the #VC handler aware of the page encryption state +change hypercall by adding support to check KVM_HC_MAP_GPA_RANGE +hypercall and add the additional register values used by +hypercall in the GHCB. + +Cc: Jordan Justen +Cc: Ard Biesheuvel +Signed-off-by: Ashish Kalra +Change-Id: Iaab77f063455837393f290ee80962e6f3d2f5593 +--- + OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c +index 41b0c8c..2d06343 100644 +--- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c ++++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c +@@ -1171,6 +1171,19 @@ VmmCallExit ( + Ghcb->SaveArea.Cpl = (UINT8) (Regs->Cs & 0x3); + VmgSetOffsetValid (Ghcb, GhcbCpl); + ++ if (Regs->Rax == KVM_HC_MAP_GPA_RANGE) { ++ // ++ // KVM_HC_MAP_GPA_RANGE hypercall requires these ++ // extra registers. ++ // ++ Ghcb->SaveArea.Rbx = Regs->Rbx; ++ VmgSetOffsetValid (Ghcb, GhcbRbx); ++ Ghcb->SaveArea.Rcx = Regs->Rcx; ++ VmgSetOffsetValid (Ghcb, GhcbRcx); ++ Ghcb->SaveArea.Rdx = Regs->Rdx; ++ VmgSetOffsetValid (Ghcb, GhcbRdx); ++ } ++ + Status = VmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0); + if (Status != 0) { + return Status; +-- +2.17.1 + diff --git a/0043-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch b/0043-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch new file mode 100644 index 0000000..dd2ca14 --- /dev/null +++ b/0043-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch @@ -0,0 +1,43 @@ +From 4f2273d02335039e85d8b47b1e43715e3db86c33 Mon Sep 17 00:00:00 2001 +From: Ashish Kalra +Date: Thu, 19 Aug 2021 13:09:07 +0000 +Subject: [PATCH 43/46] OvmfPkg/PlatformPei: Mark SEC GHCB page as unencrypted + via hypercall + +Mark the SEC GHCB page (that is mapped as unencrypted in +ResetVector code) in the hypervisor's guest page encryption +state tracking. + +Cc: Jordan Justen +Cc: Ard Biesheuvel +Signed-off-by: Ashish Kalra +Change-Id: Iedcde6367e12106e44e0cb1cc07a4ed386f67c19 +--- + OvmfPkg/PlatformPei/AmdSev.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c +index a8bf610..1d38056 100644 +--- a/OvmfPkg/PlatformPei/AmdSev.c ++++ b/OvmfPkg/PlatformPei/AmdSev.c +@@ -52,6 +52,17 @@ AmdSevEsInitialize ( + PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE); + ASSERT_RETURN_ERROR (PcdStatus); + ++ // ++ // The SEC Ghcb setup during reset-vector needs to be marked as ++ // decrypted in the hypervisor's guest page encryption state ++ // tracking. ++ // ++ SetMemoryEncDecHypercall3 ( ++ FixedPcdGet32 (PcdOvmfSecGhcbBase), ++ EFI_SIZE_TO_PAGES(FixedPcdGet32 (PcdOvmfSecGhcbSize)), ++ FALSE ++ ); ++ + // + // Allocate GHCB and per-CPU variable pages. + // Since the pages must survive across the UEFI to OS transition +-- +2.17.1 + diff --git a/0044-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch b/0044-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch new file mode 100644 index 0000000..edb8b39 --- /dev/null +++ b/0044-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch @@ -0,0 +1,185 @@ +From f751df6533d370a14412fab4850ad05ce99b7b85 Mon Sep 17 00:00:00 2001 +From: Ashish Kalra +Date: Thu, 19 Aug 2021 13:14:31 +0000 +Subject: [PATCH 44/46] OvmfPkg/AmdSevDxe: Add support for SEV live migration. + +Check for SEV live migration feature support, if detected +setup a new UEFI enviroment variable to indicate OVMF +support for SEV live migration. + +This environment variable is created by UEFI but consumed +by the (guest) linux kernel. This is actually part of a +3-way negotiation of the live migration feature between +hypervisor, guest OVMF and guest kernel. Host indicates +support for live migration, which is detected by OVMF +and correspondingly OVMF sets this SetLiveMigrationEnabled +UEFI variable, which is read by the guest kernel and it +indicates to the guest kernel that both host and OVMF +support and have enabled the live migration feature. + +The new runtime UEFI environment variable is set via the +notification function registered for the +EFI_END_OF_DXE_EVENT_GROUP_GUID event in AmdSevDxe driver. + +AmdSevDxe module is an apriori driver so it gets loaded between PEI +and DXE phases and the SetVariable call will fail at the driver's +entry point as the Variable DXE module is still not loaded yet. +So we need to wait for an event notification which is signaled +after the Variable DXE module is loaded, hence, using the +EndOfDxe event notification to make this call. + +Signed-off-by: Ashish Kalra +Change-Id: Iff6eee8f56fd60d1aedf48a5253b7b09e9aa9c7e +--- + OvmfPkg/AmdSevDxe/AmdSevDxe.c | 64 ++++++++++++++++++++++ + OvmfPkg/AmdSevDxe/AmdSevDxe.inf | 4 ++ + OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h | 20 +++++++ + OvmfPkg/OvmfPkg.dec | 1 + + 4 files changed, 89 insertions(+) + create mode 100644 OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h + +diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c +index c66c4e9..0750949 100644 +--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c ++++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c +@@ -15,10 +15,47 @@ + #include + #include + #include ++#include + #include + #include ++#include ++#include ++#include + #include + ++STATIC ++VOID ++EFIAPI ++AmdSevDxeOnEndOfDxe ( ++ IN EFI_EVENT Event, ++ IN VOID *EventToSignal ++ ) ++{ ++ EFI_STATUS Status; ++ BOOLEAN SevLiveMigrationEnabled; ++ ++ SevLiveMigrationEnabled = MemEncryptSevLiveMigrationIsEnabled (); ++ ++ if (SevLiveMigrationEnabled) { ++ Status = gRT->SetVariable ( ++ L"SevLiveMigrationEnabled", ++ &gAmdSevMemEncryptGuid, ++ EFI_VARIABLE_NON_VOLATILE | ++ EFI_VARIABLE_BOOTSERVICE_ACCESS | ++ EFI_VARIABLE_RUNTIME_ACCESS, ++ sizeof SevLiveMigrationEnabled, ++ &SevLiveMigrationEnabled ++ ); ++ ++ DEBUG (( ++ DEBUG_INFO, ++ "%a: Setting SevLiveMigrationEnabled variable, status = %lx\n", ++ __FUNCTION__, ++ Status ++ )); ++ } ++} ++ + EFI_STATUS + EFIAPI + AmdSevDxeEntryPoint ( +@@ -30,6 +67,7 @@ AmdSevDxeEntryPoint ( + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *AllDescMap; + UINTN NumEntries; + UINTN Index; ++ EFI_EVENT Event; + + // + // Do nothing when SEV is not enabled +@@ -130,5 +168,31 @@ AmdSevDxeEntryPoint ( + } + } + ++ // ++ // AmdSevDxe module is an apriori driver so it gets loaded between PEI ++ // and DXE phases and the SetVariable call will fail at the driver's ++ // entry point as the Variable DXE module is still not loaded yet. ++ // So we need to wait for an event notification which is signaled ++ // after the Variable DXE module is loaded, hence, using the ++ // EndOfDxe event notification to make this call. ++ // ++ // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event. ++ // The notification function sets the runtime variable indicating OVMF ++ // support for SEV live migration. ++ // ++ Status = gBS->CreateEventEx ( ++ EVT_NOTIFY_SIGNAL, ++ TPL_CALLBACK, ++ AmdSevDxeOnEndOfDxe, ++ NULL, ++ &gEfiEndOfDxeEventGroupGuid, ++ &Event ++ ); ++ ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a: CreateEventEx(): %r\n", ++ __FUNCTION__, Status)); ++ } ++ + return EFI_SUCCESS; + } +diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.inf b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf +index 0676fcc..2ad1fb8 100644 +--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.inf ++++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf +@@ -45,3 +45,7 @@ + + [Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId ++ ++[Guids] ++ gAmdSevMemEncryptGuid ++ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event +diff --git a/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h b/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h +new file mode 100644 +index 0000000..1c948fb +--- /dev/null ++++ b/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h +@@ -0,0 +1,20 @@ ++/** @file ++ ++ AMD Memory Encryption GUID, define a new GUID for defining ++ new UEFI environment variables assocaiated with SEV Memory Encryption. ++ ++ Copyright (c) 2021, AMD Inc. All rights reserved.
++ ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#ifndef __AMD_SEV_MEMENCRYPT_LIB_H__ ++#define __AMD_SEV_MEMENCRYPT_LIB_H__ ++ ++#define AMD_SEV_MEMENCRYPT_GUID \ ++{0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}} ++ ++extern EFI_GUID gAmdSevMemEncryptGuid; ++ ++#endif +diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec +index 7e6a6a2..b6f88e0 100644 +--- a/OvmfPkg/OvmfPkg.dec ++++ b/OvmfPkg/OvmfPkg.dec +@@ -128,6 +128,7 @@ + gQemuKernelLoaderFsMediaGuid = {0x1428f772, 0xb64a, 0x441e, {0xb8, 0xc3, 0x9e, 0xbd, 0xd7, 0xf8, 0x93, 0xc7}} + gGrubFileGuid = {0xb5ae312c, 0xbc8a, 0x43b1, {0x9c, 0x62, 0xeb, 0xb8, 0x26, 0xdd, 0x5d, 0x07}} + gConfidentialComputingSecretGuid = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}} ++ gAmdSevMemEncryptGuid = {0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}} + + [Ppis] + # PPI whose presence in the PPI database signals that the TPM base address +-- +2.17.1 + diff --git a/0045-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch b/0045-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch new file mode 100644 index 0000000..d152d63 --- /dev/null +++ b/0045-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch @@ -0,0 +1,35 @@ +From 1f244d5fec68cbd76fd902819d906c5222577a69 Mon Sep 17 00:00:00 2001 +From: hanliyang +Date: Mon, 17 Jan 2022 01:19:21 -0500 +Subject: [PATCH 45/46] anolis: OvmfPkg/BaseMemcryptSevLib: Correct the + calculation of page range that notified to hypervisor + +Correct the calculation of page range that notified to hypervisor. + +Change-Id: Ie2ac4a4e894095ea9ae3b1d44afed04681b9d491 +--- + .../Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +index 0b67577..4dbf829 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c +@@ -828,9 +828,13 @@ SetMemoryEncDec ( + // Notify Hypervisor on C-bit status + // + if (CBitChanged) { ++ UINTN StartPfn = OrigPhysicalAddress >> EFI_PAGE_SHIFT; ++ UINTN EndPfn = (OrigPhysicalAddress + OrigLength + ++ ((1 << EFI_PAGE_SHIFT) - 1)) >> EFI_PAGE_SHIFT; ++ + Status = SetMemoryEncDecHypercall3 ( + OrigPhysicalAddress, +- EFI_SIZE_TO_PAGES (OrigLength), ++ (EndPfn - StartPfn), + (Mode == SetCBit) ? TRUE : FALSE + ); + } +-- +2.17.1 + diff --git a/0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch b/0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch new file mode 100644 index 0000000..5da0f2b --- /dev/null +++ b/0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch @@ -0,0 +1,36 @@ +From 901330a9161de852bf99ad7b2c629bae00af2b7a Mon Sep 17 00:00:00 2001 +From: hanliyang +Date: Sun, 19 Jun 2022 18:12:35 +0800 +Subject: [PATCH 46/46] anolis: OvmfPkg/BaseMemEncryptLib: Return SUCCESS if + not support SEV live migration + +Add this change to avoid trigger 'ASSERT_EFI_ERROR (Status = Unsupported)' +when QEMU doesn't support SEV live migration. + +Change-Id: I48066d6cf1b4357c984496bcb6450be4d35b7e16 +--- + OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c +index a6246d4..e50231c 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c +@@ -169,10 +169,12 @@ SetMemoryEncDecHypercall3 ( + UINTN Error; + UINTN EncryptState; + +- Ret = RETURN_UNSUPPORTED; ++ // ++ // Return success if not support migration. ++ // ++ Ret = RETURN_SUCCESS; + + if (MemEncryptSevLiveMigrationIsEnabled ()) { +- Ret = RETURN_SUCCESS; + // + // The encryption bit is set/clear on the smallest page size, hence + // use the 4k page size in MAP_GPA_RANGE hypercall below. +-- +2.17.1 + diff --git a/edk2.spec b/edk2.spec index fca9d85..8092072 100644 --- a/edk2.spec +++ b/edk2.spec @@ -1,3 +1,4 @@ +%define anolis_release .0.1 ExclusiveArch: x86_64 aarch64 %define GITDATE 20220126 @@ -7,7 +8,7 @@ ExclusiveArch: x86_64 aarch64 Name: edk2 Version: %{GITDATE}git%{GITCOMMIT} -Release: 13%{?dist} +Release: 13%{anolis_release}%{?dist} Summary: UEFI firmware for 64-bit virtual machines Group: Applications/Emulators License: BSD-2-Clause-Patent and OpenSSL and MIT @@ -261,6 +262,26 @@ Patch83: edk2-EmbeddedPkg-Hob-Integer-Overflow-in-CreateHob.patch # For RHEL-21158 - CVE-2022-36765 edk2: integer overflow in CreateHob() could lead to HOB OOB R/W [rhel-8] Patch84: edk2-StandaloneMmPkg-Hob-Integer-Overflow-in-CreateHob.patch +# Support hygon csv3 feature +Patch1000: 0029-anolis-UefiCpuPkg-Add-StandardSignatureIsHygonGenuin.patch +Patch1001: 0030-anolis-UefiCpuPkg-LocalApicLib-Exclude-second-SendIp.patch +Patch1002: 0031-anolis-OvmfPkg-Add-CSV-secure-call-library-on-Hygon-.patch +Patch1003: 0032-anolis-OvmfPkg-Tcg-Add-CsvLib-for-TpmMmioSevDecryptP.patch +Patch1004: 0033-anolis-OvmfPkg-ResetVector-Support-CSV-in-ResetVecto.patch +Patch1005: 0034-anolis-OvmfPkg-PlatformPei-Initialize-CSV-VM-s-memor.patch +Patch1006: 0035-anolis-OvmfPkg-BaseMemcryptSevLib-update-page-status.patch +Patch1007: 0036-anolis-OvmfPkg-Add-CsvDxe-driver.patch +Patch1008: 0037-anolis-OvmfPkg-IoMmuDxe-Add-CsvIoMmu-protocol.patch +Patch1009: 0038-anolis-OvmfPkg-Reserve-a-CPUID-table-page-for-CSV-gu.patch +# Support SEV live migration +Patch1010: 0039-OvmfPkg-BaseMemEncryptLib-Detect-SEV-live-migration-.patch +Patch1011: 0040-OvmfPkg-BaseMemEncryptLib-Hypercall-API-for-page-enc.patch +Patch1012: 0041-OvmfPkg-BaseMemEncryptLib-Invoke-page-encryption-sta.patch +Patch1013: 0042-OvmfPkg-VmgExitLib-Encryption-state-change-hypercall.patch +Patch1014: 0043-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch +Patch1015: 0044-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch +Patch1016: 0045-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch +Patch1017: 0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch # python3-devel and libuuid-devel are required for building tools. # python3-devel is also needed for varstore template generation and @@ -706,6 +727,10 @@ true %endif %changelog +* Tue May 28 2024 Jiang Xin - 20220126gitbb1bba3d77-13.0.1 +- Support hygon CSV3 feature +- Support SEV live migration + * Thu Mar 14 2024 Miroslav Rezanina - 20220126gitbb1bba3d77-13 - edk2-EmbeddedPkg-Hob-Integer-Overflow-in-CreateHob.patch [RHEL-21158] - edk2-StandaloneMmPkg-Hob-Integer-Overflow-in-CreateHob.patch [RHEL-21158] -- Gitee From 2e560e5a9806c8d1fbea843506d0bf02f9269908 Mon Sep 17 00:00:00 2001 From: Xin Jiang Date: Fri, 12 Jan 2024 10:57:05 +0800 Subject: [PATCH 3/4] anolis: OvmfPkg/BaseMemEncryptLib: Save memory encrypt status in reserved memory The MMIO routine of VC handler will get memory encrypt status to validate MMIO address. MemEncryptSevGetEncryptionMask() will enable interrupt while interrupt must be disabled during VC. During DXE stage, VC routine as below: CcExitHandleVc->MemEncryptSevGetAddressRangeState-> MemEncryptSevGetEncryptionMask->PcdGet64(PcdPteMemoryEncryptionAddressOrMask) Unfortunately, PcdGet64() will enable interrupt in VC context. Signed-off-by: Xin Jiang --- ...aseMemEncryptLib-Save-memory-encrypt.patch | 144 ++++++++++++++++++ edk2.spec | 4 + 2 files changed, 148 insertions(+) create mode 100644 0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch diff --git a/0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch b/0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch new file mode 100644 index 0000000..00380bc --- /dev/null +++ b/0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch @@ -0,0 +1,144 @@ +From 644748015685d9a13e43d7e689f1e7379adcc959 Mon Sep 17 00:00:00 2001 +From: Xin Jiang +Date: Fri, 12 Jan 2024 10:39:28 +0800 +Subject: [PATCH] anolis: OvmfPkg/BaseMemEncryptLib: Save memory encrypt status + in reserved memory + +The MMIO routine of VC handler will get memory encrypt status to +validate MMIO address. MemEncryptSevGetEncryptionMask() will enable +interrupt while interrupt must be disabled during VC. + +During DXE stage, VC routine as below: +CcExitHandleVc->MemEncryptSevGetAddressRangeState-> +MemEncryptSevGetEncryptionMask->PcdGet64(PcdPteMemoryEncryptionAddressOrMask) + +Unfortunately, PcdGet64() will enable interrupt in VC context. + +Change-Id: I89aedeac4a90ec79f9acb35daf638b7fb507f24c +Signed-off-by: Xin Jiang +--- + .../BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf | 4 ++++ + .../BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c | 10 ++-------- + OvmfPkg/OvmfPkg.dec | 4 ++++ + OvmfPkg/OvmfPkgX64.fdf | 5 ++++- + OvmfPkg/PlatformPei/AmdSev.c | 2 ++ + OvmfPkg/PlatformPei/Csv.c | 6 ++++++ + OvmfPkg/PlatformPei/PlatformPei.inf | 2 ++ + 7 files changed, 24 insertions(+), 9 deletions(-) + +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +index 8ea8d3a..55e75ef 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf +@@ -57,3 +57,7 @@ + + [Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ++ ++[FixedPcd] ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize +diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c +index df73a83..44d9ad1 100644 +--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c ++++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c +@@ -25,9 +25,6 @@ STATIC BOOLEAN mSevStatusChecked = FALSE; + STATIC BOOLEAN mSevLiveMigrationStatus = FALSE; + STATIC BOOLEAN mSevLiveMigrationStatusChecked = FALSE; + +-STATIC UINT64 mSevEncryptionMask = 0; +-STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE; +- + /** + Reads and sets the status of SEV features. + +@@ -177,10 +174,7 @@ MemEncryptSevGetEncryptionMask ( + VOID + ) + { +- if (!mSevEncryptionMaskSaved) { +- mSevEncryptionMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask); +- mSevEncryptionMaskSaved = TRUE; +- } ++ UINT64 *MemEncryptStatus = (UINT64 *)(UINT64)FixedPcdGet32 (PcdMemEncrpytStatusBase); + +- return mSevEncryptionMask; ++ return *MemEncryptStatus; + } +diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec +index b6f88e0..2c09ad4 100644 +--- a/OvmfPkg/OvmfPkg.dec ++++ b/OvmfPkg/OvmfPkg.dec +@@ -364,6 +364,10 @@ + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|0|UINT32|0x60 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize|0|UINT32|0x61 + ++ ## the base address of memory encryption status.^M ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase|0|UINT32|0x62 ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize|0|UINT32|0x63 ++ + [PcdsDynamic, PcdsDynamicEx] + gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 +diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf +index 04efa62..0cc12b8 100644 +--- a/OvmfPkg/OvmfPkgX64.fdf ++++ b/OvmfPkg/OvmfPkgX64.fdf +@@ -94,7 +94,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallBase|gUefiOvmfPkgTokenSpaceGui + 0x00F000|0x001000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize + +-0x010000|0x010000 ++0x010000|0x001000 ++gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase|gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize ++ ++0x011000|0x00F000 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + + 0x020000|0x0E0000 +diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c +index 1d38056..33fc83a 100644 +--- a/OvmfPkg/PlatformPei/AmdSev.c ++++ b/OvmfPkg/PlatformPei/AmdSev.c +@@ -167,6 +167,8 @@ AmdSevInitialize ( + PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask); + ASSERT_RETURN_ERROR (PcdStatus); + ++ *(UINT64 *)(UINT64)FixedPcdGet32 (PcdMemEncrpytStatusBase) = EncryptionMask; ++ + DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask)); + + // +diff --git a/OvmfPkg/PlatformPei/Csv.c b/OvmfPkg/PlatformPei/Csv.c +index f7c87ac..f8293ab 100644 +--- a/OvmfPkg/PlatformPei/Csv.c ++++ b/OvmfPkg/PlatformPei/Csv.c +@@ -32,6 +32,12 @@ CsvInitializeMemInfo ( + UINT64 LowerMemorySize; + UINT64 UpperMemorySize; + ++ BuildMemoryAllocationHob ( ++ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdMemEncrpytStatusBase), ++ (UINT64)(UINTN) FixedPcdGet32 (PcdMemEncrpytStatusSize), ++ EfiReservedMemoryType ++ ); ++ + if (!CsvIsEnabled ()) { + return ; + } +diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf +index bed4dcf..7bf667c 100644 +--- a/OvmfPkg/PlatformPei/PlatformPei.inf ++++ b/OvmfPkg/PlatformPei/PlatformPei.inf +@@ -125,6 +125,8 @@ + gUefiOvmfPkgTokenSpaceGuid.PcdCsvDefaultSecureCallSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCsvCpuidSize ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusBase ++ gUefiOvmfPkgTokenSpaceGuid.PcdMemEncrpytStatusSize + + [FeaturePcd] + gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable +-- +2.17.1 + diff --git a/edk2.spec b/edk2.spec index 8092072..fe37f6a 100644 --- a/edk2.spec +++ b/edk2.spec @@ -282,6 +282,8 @@ Patch1014: 0043-OvmfPkg-PlatformPei-Mark-SEC-GHCB-page-as-unencrypte.patch Patch1015: 0044-OvmfPkg-AmdSevDxe-Add-support-for-SEV-live-migration.patch Patch1016: 0045-anolis-OvmfPkg-BaseMemcryptSevLib-Correct-the-calcul.patch Patch1017: 0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch +# Fix the isue that interrupt is enabled in MMIO VC handler +Patch1018: 0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch # python3-devel and libuuid-devel are required for building tools. # python3-devel is also needed for varstore template generation and @@ -730,6 +732,8 @@ true * Tue May 28 2024 Jiang Xin - 20220126gitbb1bba3d77-13.0.1 - Support hygon CSV3 feature - Support SEV live migration +- 0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch +- Fix the isue that interrupt is enabled in MMIO VC handler * Thu Mar 14 2024 Miroslav Rezanina - 20220126gitbb1bba3d77-13 - edk2-EmbeddedPkg-Hob-Integer-Overflow-in-CreateHob.patch [RHEL-21158] -- Gitee From cd124bb190109ca088a349ece9d32d86ed49736b Mon Sep 17 00:00:00 2001 From: fangbaoshun Date: Wed, 24 Jan 2024 13:49:51 +0800 Subject: [PATCH 4/4] Commit 079a582 ("OvmfPkg/AmdSev/SecretPei: Mark SEV launch secret area as reserved") marked the launch secret area itself (1 page) as reserved so the guest OS can use it during the lifetime of the OS. However, the address and size of the secret area held in the CONFIDENTIAL_COMPUTING_SECRET_LOCATION struct are declared as STATIC in OVMF (in AmdSev/SecretDxe); therefore there's no guarantee that it will not be written over by OS data. Fix this by allocating the memory for the CONFIDENTIAL_COMPUTING_SECRET_LOCATION struct with the EfiACPIReclaimMemory memory type to ensure the guest OS will not reuse this memory. Fixes: 079a582 ("OvmfPkg/AmdSev/SecretPei: Mark SEV launch secret ...") Signed-off-by: fangbaoshun --- ...ecretDxe-Allocate-secret-location-as.patch | 73 +++++++++++++++++++ edk2.spec | 4 + 2 files changed, 77 insertions(+) create mode 100644 0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch diff --git a/0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch b/0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch new file mode 100644 index 0000000..e80d369 --- /dev/null +++ b/0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch @@ -0,0 +1,73 @@ +From 02916fa2f7b92b060bbdc70b2083d0fcf6139624 Mon Sep 17 00:00:00 2001 +From: Dov Murik +Date: Thu, 15 Dec 2022 13:11:51 +0000 +Subject: [PATCH] OvmfPkg/AmdSev/SecretDxe: Allocate secret location as + EfiACPIReclaimMemory + +BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4186 + +Commit 079a58276b98 ("OvmfPkg/AmdSev/SecretPei: Mark SEV launch secret +area as reserved") marked the launch secret area itself (1 page) as +reserved so the guest OS can use it during the lifetime of the OS. +However, the address and size of the secret area held in the +CONFIDENTIAL_COMPUTING_SECRET_LOCATION struct are declared as STATIC in +OVMF (in AmdSev/SecretDxe); therefore there's no guarantee that it will +not be written over by OS data. + +Fix this by allocating the memory for the +CONFIDENTIAL_COMPUTING_SECRET_LOCATION struct with the +EfiACPIReclaimMemory memory type to ensure the guest OS will not reuse +this memory. + +Fixes: 079a58276b98 ("OvmfPkg/AmdSev/SecretPei: Mark SEV launch secret ...") +Signed-off-by: Dov Murik +Reviewed-by: Tom Lendacky +Reviewed-by: Ard Biesheuvel +--- + OvmfPkg/AmdSev/SecretDxe/SecretDxe.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c +index 934ad20..c851176 100644 +--- a/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c ++++ b/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c +@@ -8,11 +8,6 @@ + #include + #include + +-STATIC CONFIDENTIAL_COMPUTING_SECRET_LOCATION mSecretDxeTable = { +- FixedPcdGet32 (PcdSevLaunchSecretBase), +- FixedPcdGet32 (PcdSevLaunchSecretSize), +-}; +- + EFI_STATUS + EFIAPI + InitializeSecretDxe( +@@ -20,8 +15,23 @@ InitializeSecretDxe( + IN EFI_SYSTEM_TABLE *SystemTable + ) + { ++ EFI_STATUS Status; ++ CONFIDENTIAL_COMPUTING_SECRET_LOCATION *SecretDxeTable; ++ ++ Status = gBS->AllocatePool ( ++ EfiACPIReclaimMemory, ++ sizeof (CONFIDENTIAL_COMPUTING_SECRET_LOCATION), ++ (VOID **)&SecretDxeTable ++ ); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } ++ ++ SecretDxeTable->Base = FixedPcdGet32 (PcdSevLaunchSecretBase); ++ SecretDxeTable->Size = FixedPcdGet32 (PcdSevLaunchSecretSize); ++ + return gBS->InstallConfigurationTable ( + &gConfidentialComputingSecretGuid, +- &mSecretDxeTable ++ SecretDxeTable + ); + } +-- +2.41.0 + diff --git a/edk2.spec b/edk2.spec index fe37f6a..49eedd0 100644 --- a/edk2.spec +++ b/edk2.spec @@ -285,6 +285,8 @@ Patch1017: 0046-anolis-OvmfPkg-BaseMemEncryptLib-Return-SUCCESS-if-n.patch # Fix the isue that interrupt is enabled in MMIO VC handler Patch1018: 0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch +Patch1019: 0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch + # python3-devel and libuuid-devel are required for building tools. # python3-devel is also needed for varstore template generation and # verification with "ovmf-vars-generator". @@ -734,6 +736,8 @@ true - Support SEV live migration - 0047-anolis-OvmfPkg-BaseMemEncryptLib-Save-memory-encrypt.patch - Fix the isue that interrupt is enabled in MMIO VC handler +- 0048-OvmfPkg-AmdSev-SecretDxe-Allocate-secret-location-as.patch (fangbaoshun@hygon.cn) +- Resolves: bz#8033 * Thu Mar 14 2024 Miroslav Rezanina - 20220126gitbb1bba3d77-13 - edk2-EmbeddedPkg-Hob-Integer-Overflow-in-CreateHob.patch [RHEL-21158] -- Gitee