commit c6ea5129475bb076f308eb2f3ae91609bb634b87 Author: MSVSphere Packaging Team Date: Fri Mar 29 15:31:26 2024 +0300 import edk2-20220126gitbb1bba3d77-12.el8 diff --git a/.edk2.metadata b/.edk2.metadata new file mode 100644 index 0000000..334c41f --- /dev/null +++ b/.edk2.metadata @@ -0,0 +1,2 @@ +ae830c7278f985cb25e90f4687b46c8b22316bef SOURCES/edk2-bb1bba3d77.tar.xz +85388ae6525650667302c6b553894430197d9e0d SOURCES/openssl-rhel-cf317b2bb227899cb2e761b9163210f62cab1b1e.tar.xz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..440a2b8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/edk2-bb1bba3d77.tar.xz +SOURCES/openssl-rhel-cf317b2bb227899cb2e761b9163210f62cab1b1e.tar.xz diff --git a/SOURCES/0008-BaseTools-do-not-build-BrotliCompress-RH-only.patch b/SOURCES/0008-BaseTools-do-not-build-BrotliCompress-RH-only.patch new file mode 100644 index 0000000..fcfa987 --- /dev/null +++ b/SOURCES/0008-BaseTools-do-not-build-BrotliCompress-RH-only.patch @@ -0,0 +1,43 @@ +From 0790c9c4f796fdce8ba6618359b78e1d0b331c95 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 4 Jun 2020 13:34:12 +0200 +Subject: BaseTools: do not build BrotliCompress (RH only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- no change + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- New patch. + +BrotliCompress is not used for building ArmVirtPkg or OvmfPkg platforms. +It depends on one of the upstream Brotli git submodules that we removed +earlier in this rebase series. (See patch "remove upstream edk2's Brotli +submodules (RH only"). + +Do not attempt to build BrotliCompress. + +Signed-off-by: Laszlo Ersek +(cherry picked from commit db8ccca337e2c5722c1d408d2541cf653d3371a2) +--- + BaseTools/Source/C/GNUmakefile | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/BaseTools/Source/C/GNUmakefile b/BaseTools/Source/C/GNUmakefile +index 8c191e0c38..3eae824a1c 100644 +--- a/BaseTools/Source/C/GNUmakefile ++++ b/BaseTools/Source/C/GNUmakefile +@@ -48,7 +48,6 @@ all: makerootdir subdirs + LIBRARIES = Common + VFRAUTOGEN = VfrCompile/VfrLexer.h + APPLICATIONS = \ +- BrotliCompress \ + VfrCompile \ + EfiRom \ + GenFfs \ +-- +2.27.0 + diff --git a/SOURCES/0009-MdeModulePkg-remove-package-private-Brotli-include-p.patch b/SOURCES/0009-MdeModulePkg-remove-package-private-Brotli-include-p.patch new file mode 100644 index 0000000..a8ef274 --- /dev/null +++ b/SOURCES/0009-MdeModulePkg-remove-package-private-Brotli-include-p.patch @@ -0,0 +1,49 @@ +From df9e25b7e6179a7764d44f915de95af5f850a020 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 4 Jun 2020 13:39:08 +0200 +Subject: MdeModulePkg: remove package-private Brotli include path (RH only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- no change + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- New patch. + +Originating from upstream commit 58802e02c41b +("MdeModulePkg/BrotliCustomDecompressLib: Make brotli a submodule", +2020-04-16), "MdeModulePkg/MdeModulePkg.dec" contains a package-internal +include path into a Brotli submodule. + +The edk2 build system requires such include paths to resolve successfully, +regardless of the firmware platform being built. Because +BrotliCustomDecompressLib is not consumed by any OvmfPkg or ArmVirtPkg +platforms, and we've removed the submodule earlier in this patch set, +remove the include path too. + +Signed-off-by: Laszlo Ersek +(cherry picked from commit e05e0de713c4a2b8adb6ff9809611f222bfe50ed) +--- + MdeModulePkg/MdeModulePkg.dec | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec +index 463e889e9a..9d69fb86ed 100644 +--- a/MdeModulePkg/MdeModulePkg.dec ++++ b/MdeModulePkg/MdeModulePkg.dec +@@ -24,9 +24,6 @@ + [Includes] + Include + +-[Includes.Common.Private] +- Library/BrotliCustomDecompressLib/brotli/c/include +- + [LibraryClasses] + ## @libraryclass Defines a set of methods to reset whole system. + ResetSystemLib|Include/Library/ResetSystemLib.h +-- +2.27.0 + diff --git a/SOURCES/0010-OvmfPkg-increase-max-debug-message-length-to-512-RHE.patch b/SOURCES/0010-OvmfPkg-increase-max-debug-message-length-to-512-RHE.patch new file mode 100644 index 0000000..4107e96 --- /dev/null +++ b/SOURCES/0010-OvmfPkg-increase-max-debug-message-length-to-512-RHE.patch @@ -0,0 +1,82 @@ +From 1a1bdd69fad22bbf48e3906bb73b33ede6632102 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 20 Feb 2014 22:54:45 +0100 +Subject: OvmfPkg: increase max debug message length to 512 (RHEL only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- no change + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- no change + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- trivial context difference due to upstream commit 2fe5f2f52918 + ("OvmfPkg/PlatformDebugLibIoPort: Add new APIs", 2019-04-02), resolved + by git-cherry-pick automatically + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- no changes + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- no changes + +Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase: + +- no changes + +Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase: + +- no changes + +Upstream prefers short debug messages (sometimes even limited to 80 +characters), but any line length under 512 characters is just unsuitable +for effective debugging. (For example, config strings in HII routing, +logged by the platform driver "OvmfPkg/PlatformDxe" on DEBUG_VERBOSE +level, can be several hundred characters long.) 512 is an empirically good +value. + +Signed-off-by: Laszlo Ersek +(cherry picked from commit bfe568d18dba15602604f155982e3b73add63dfb) +(cherry picked from commit 29435a32ec9428720c74c454ce9817662e601fb6) +(cherry picked from commit 58e1d1ebb78bfdaf05f4c6e8abf8d4908dfa038a) +(cherry picked from commit 1df2c822c996ad767f2f45570ab2686458f7604a) +(cherry picked from commit 22c9b4e971c70c69b4adf8eb93133824ccb6426a) +(cherry picked from commit a1260c9122c95bcbef1efc5eebe11902767813c2) +(cherry picked from commit e949bab1268f83f0f5815a96cd1cb9dd3b21bfb5) +(cherry picked from commit a95cff0b9573bf23699551beb4786383f697ff1e) +--- + OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c +index dffb20822d..0577c43c3d 100644 +--- a/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c ++++ b/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c +@@ -21,7 +21,7 @@ + // + // Define the maximum debug and assert message length that this library supports + // +-#define MAX_DEBUG_MESSAGE_LENGTH 0x100 ++#define MAX_DEBUG_MESSAGE_LENGTH 0x200 + + // + // VA_LIST can not initialize to NULL for all compiler, so we use this to +-- +2.27.0 + diff --git a/SOURCES/0011-MdeModulePkg-TerminalDxe-add-other-text-resolutions-.patch b/SOURCES/0011-MdeModulePkg-TerminalDxe-add-other-text-resolutions-.patch new file mode 100644 index 0000000..1ff85cd --- /dev/null +++ b/SOURCES/0011-MdeModulePkg-TerminalDxe-add-other-text-resolutions-.patch @@ -0,0 +1,168 @@ +From 8ea4ac38206664e1d833085a0b7d4e0736870c2b Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Tue, 25 Feb 2014 18:40:35 +0100 +Subject: MdeModulePkg: TerminalDxe: add other text resolutions (RHEL only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- no change + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- no changes + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- no changes + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- no change + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- update commit message as requested in + + +Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase: + +- no changes + +Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase: + +- adapt commit 0bc77c63de03 (code and commit message) to upstream commit + 390b95a49c14 ("MdeModulePkg/TerminalDxe: Refine + InitializeTerminalConsoleTextMode", 2017-01-10). + +When the console output is multiplexed to several devices by +ConSplitterDxe, then ConSplitterDxe builds an intersection of text modes +supported by all console output devices. + +Two notable output devices are provided by: +(1) MdeModulePkg/Universal/Console/GraphicsConsoleDxe, +(2) MdeModulePkg/Universal/Console/TerminalDxe. + +GraphicsConsoleDxe supports four modes at most -- see +InitializeGraphicsConsoleTextMode() and "mGraphicsConsoleModeData": + +(1a) 80x25 (required by the UEFI spec as mode 0), +(1b) 80x50 (not necessarily supported, but if it is, then the UEFI spec + requires the driver to provide it as mode 1), +(1c) 100x31 (corresponding to graphics resolution 800x600, which the UEFI + spec requires from all plug-in graphics devices), +(1d) "full screen" resolution, derived form the underlying GOP's + horizontal and vertical resolutions with division by EFI_GLYPH_WIDTH + (8) and EFI_GLYPH_HEIGHT (19), respectively. + +The automatic "full screen resolution" makes GraphicsConsoleDxe's +character console very flexible. However, TerminalDxe (which runs on +serial ports) only provides the following fixed resolutions -- see +InitializeTerminalConsoleTextMode() and "mTerminalConsoleModeData": + +(2a) 80x25 (required by the UEFI spec as mode 0), +(2b) 80x50 (since the character resolution of a serial device cannot be + interrogated easily, this is added unconditionally as mode 1), +(2c) 100x31 (since the character resolution of a serial device cannot be + interrogated easily, this is added unconditionally as mode 2). + +When ConSplitterDxe combines (1) and (2), multiplexing console output to +both video output and serial terminal, the list of commonly supported text +modes (ie. the "intersection") comprises: + +(3a) 80x25, unconditionally, from (1a) and (2a), +(3b) 80x50, if the graphics console provides at least 640x950 pixel + resolution, from (1b) and (2b) +(3c) 100x31, if the graphics device is a plug-in one (because in that case + 800x600 is a mandated pixel resolution), from (1c) and (2c). + +Unfortunately, the "full screen resolution" (1d) of the GOP-based text +console is not available in general. + +Mitigate this problem by extending "mTerminalConsoleModeData" with a +handful of text resolutions that are derived from widespread maximal pixel +resolutions. This way TerminalDxe won't cause ConSplitterDxe to filter out +the most frequent (1d) values from the intersection, and eg. the MODE +command in the UEFI shell will offer the "best" (ie. full screen) +resolution too. + +Upstreaming efforts for this patch have been discontinued; it was clear +from the off-list thread that consensus was impossible to reach. + +Signed-off-by: Laszlo Ersek +(cherry picked from commit 99dc3720ac86059f60156197328cc433603c536e) +(cherry picked from commit d2066c1748f885043026c51dec1bc8d6d406ae8f) +(cherry picked from commit 1facdd58e946c584a3dc1e5be8f2f837b5a7c621) +(cherry picked from commit 28faeb5f94b4866b9da16cf2a1e4e0fc09a26e37) +(cherry picked from commit 4e4e15b80a5b2103eadd495ef4a830d46dd4ed51) +(cherry picked from commit 12cb13a1da913912bd9148ce8f2353a75be77f18) +(cherry picked from commit 82b9edc5fef3a07227a45059bbe821af7b9abd69) +--- + .../Universal/Console/TerminalDxe/Terminal.c | 41 +++++++++++++++++-- + 1 file changed, 38 insertions(+), 3 deletions(-) + +diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c +index a98b690c8b..ded5513c74 100644 +--- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c ++++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c +@@ -115,9 +115,44 @@ TERMINAL_DEV mTerminalDevTemplate = { + }; + + TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = { +- {80, 25}, +- {80, 50}, +- {100, 31}, ++ { 80, 25 }, // from graphics resolution 640 x 480 ++ { 80, 50 }, // from graphics resolution 640 x 960 ++ { 100, 25 }, // from graphics resolution 800 x 480 ++ { 100, 31 }, // from graphics resolution 800 x 600 ++ { 104, 32 }, // from graphics resolution 832 x 624 ++ { 120, 33 }, // from graphics resolution 960 x 640 ++ { 128, 31 }, // from graphics resolution 1024 x 600 ++ { 128, 40 }, // from graphics resolution 1024 x 768 ++ { 144, 45 }, // from graphics resolution 1152 x 864 ++ { 144, 45 }, // from graphics resolution 1152 x 870 ++ { 160, 37 }, // from graphics resolution 1280 x 720 ++ { 160, 40 }, // from graphics resolution 1280 x 760 ++ { 160, 40 }, // from graphics resolution 1280 x 768 ++ { 160, 42 }, // from graphics resolution 1280 x 800 ++ { 160, 50 }, // from graphics resolution 1280 x 960 ++ { 160, 53 }, // from graphics resolution 1280 x 1024 ++ { 170, 40 }, // from graphics resolution 1360 x 768 ++ { 170, 40 }, // from graphics resolution 1366 x 768 ++ { 175, 55 }, // from graphics resolution 1400 x 1050 ++ { 180, 47 }, // from graphics resolution 1440 x 900 ++ { 200, 47 }, // from graphics resolution 1600 x 900 ++ { 200, 63 }, // from graphics resolution 1600 x 1200 ++ { 210, 55 }, // from graphics resolution 1680 x 1050 ++ { 240, 56 }, // from graphics resolution 1920 x 1080 ++ { 240, 63 }, // from graphics resolution 1920 x 1200 ++ { 240, 75 }, // from graphics resolution 1920 x 1440 ++ { 250, 105 }, // from graphics resolution 2000 x 2000 ++ { 256, 80 }, // from graphics resolution 2048 x 1536 ++ { 256, 107 }, // from graphics resolution 2048 x 2048 ++ { 320, 75 }, // from graphics resolution 2560 x 1440 ++ { 320, 84 }, // from graphics resolution 2560 x 1600 ++ { 320, 107 }, // from graphics resolution 2560 x 2048 ++ { 350, 110 }, // from graphics resolution 2800 x 2100 ++ { 400, 126 }, // from graphics resolution 3200 x 2400 ++ { 480, 113 }, // from graphics resolution 3840 x 2160 ++ { 512, 113 }, // from graphics resolution 4096 x 2160 ++ { 960, 227 }, // from graphics resolution 7680 x 4320 ++ { 1024, 227 }, // from graphics resolution 8192 x 4320 + // + // New modes can be added here. + // +-- +2.27.0 + diff --git a/SOURCES/0012-MdeModulePkg-TerminalDxe-set-xterm-resolution-on-mod.patch b/SOURCES/0012-MdeModulePkg-TerminalDxe-set-xterm-resolution-on-mod.patch new file mode 100644 index 0000000..0e74204 --- /dev/null +++ b/SOURCES/0012-MdeModulePkg-TerminalDxe-set-xterm-resolution-on-mod.patch @@ -0,0 +1,181 @@ +From fbfd113142f594c4f257b5a044a6e17ef7f66505 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Tue, 25 Feb 2014 22:40:01 +0100 +Subject: MdeModulePkg: TerminalDxe: set xterm resolution on mode change (RH + only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- Resolve harmless conflict in "MdeModulePkg/MdeModulePkg.dec", + originating from new upstream commits + - 45bc28172fbf ("MdeModulePkg.dec: Change PCDs for status code.", + 2020-06-18), + - 0785c619a58a ("MdeModulePkg/Bus/Pci/PciBusDxe: Support PCIe Resizable + BAR Capability", 2021-01-04), + - ef23012e5439 ("MdeModulePkg: Change default value of + PcdPcieResizableBarSupport to FALSE", 2021-01-14). + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- Resolve trivial conflict in "MdeModulePkg/MdeModulePkg.dec", arising + from upstream commit 166830d8f7ca ("MdeModulePkg/dec: add + PcdTcgPfpMeasurementRevision PCD", 2020-01-06). + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- Conflict in "MdeModulePkg/MdeModulePkg.dec" due to upstream commits + - 1103ba946aee ("MdeModulePkg: Add Capsule On Disk related definition.", + 2019-06-26), + - 1c7b3eb84631 ("MdeModulePkg/DxeIpl: Introduce PCD + PcdUse5LevelPageTable", 2019-08-09), + with easy manual resolution. + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- no change + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- no change + +Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase: + +- Refresh downstream-only commit 2909e025db68 against "MdeModulePkg.dec" + context change from upstream commits e043f7895b83 ("MdeModulePkg: Add + PCD PcdPteMemoryEncryptionAddressOrMask", 2017-02-27) and 76081dfcc5b2 + ("MdeModulePkg: Add PROMPT&HELP string of pcd to UNI file", 2017-03-03). + +Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase: + +- refresh commit 519b9751573e against various context changes + +The + + CSI Ps ; Ps ; Ps t + +escape sequence serves for window manipulation. We can use the + + CSI 8 ; ; t + +sequence to adapt eg. the xterm window size to the selected console mode. + +Reference: +Contributed-under: TianoCore Contribution Agreement 1.0 +Signed-off-by: Laszlo Ersek +(cherry picked from commit 2909e025db6878723b49644a8a0cf160d07e6444) +(cherry picked from commit b9c5c901f25e48d68eef6e78a4abca00e153f574) +(cherry picked from commit b7f6115b745de8cbc5214b6ede33c9a8558beb90) +(cherry picked from commit 67415982afdc77922aa37496c981adeb4351acdb) +(cherry picked from commit cfccb98d13e955beb0b93b4a75a973f30c273ffc) +(cherry picked from commit a11602f5e2ef930be5b693ddfd0c789a1bd4c60c) +(cherry picked from commit bc2266f20de5db1636e09a07e4a72c8dbf505f5a) +--- + MdeModulePkg/MdeModulePkg.dec | 4 +++ + .../Console/TerminalDxe/TerminalConOut.c | 30 +++++++++++++++++++ + .../Console/TerminalDxe/TerminalDxe.inf | 2 ++ + 3 files changed, 36 insertions(+) + +diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec +index 9d69fb86ed..08d59dfb3e 100644 +--- a/MdeModulePkg/MdeModulePkg.dec ++++ b/MdeModulePkg/MdeModulePkg.dec +@@ -2076,6 +2076,10 @@ + # @Prompt Enable PCIe Resizable BAR Capability support. + gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarSupport|FALSE|BOOLEAN|0x10000024 + ++ ## Controls whether TerminalDxe outputs an XTerm resize sequence on terminal ++ # mode change. ++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm|FALSE|BOOLEAN|0x00010080 ++ + [PcdsPatchableInModule] + ## Specify memory size with page number for PEI code when + # Loading Module at Fixed Address feature is enabled. +diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c +index aae470e956..26156857aa 100644 +--- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c ++++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c +@@ -7,6 +7,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ + ++#include ++ + #include "Terminal.h" + + // +@@ -80,6 +82,16 @@ CHAR16 mSetCursorPositionString[] = { ESC, '[', '0', '0', ';', '0', '0', 'H', 0 + CHAR16 mCursorForwardString[] = { ESC, '[', '0', '0', 'C', 0 }; + CHAR16 mCursorBackwardString[] = { ESC, '[', '0', '0', 'D', 0 }; + ++// ++// Note that this is an ASCII format string, taking two INT32 arguments: ++// rows, columns. ++// ++// A %d (INT32) format specification can expand to at most 11 characters. ++// ++CHAR8 mResizeTextAreaFormatString[] = "\x1B[8;%d;%dt"; ++#define RESIZE_SEQ_SIZE (sizeof mResizeTextAreaFormatString + 2 * (11 - 2)) ++ ++ + // + // Body of the ConOut functions + // +@@ -506,6 +518,24 @@ TerminalConOutSetMode ( + return EFI_DEVICE_ERROR; + } + ++ if (PcdGetBool (PcdResizeXterm)) { ++ CHAR16 ResizeSequence[RESIZE_SEQ_SIZE]; ++ ++ UnicodeSPrintAsciiFormat ( ++ ResizeSequence, ++ sizeof ResizeSequence, ++ mResizeTextAreaFormatString, ++ (INT32) TerminalDevice->TerminalConsoleModeData[ModeNumber].Rows, ++ (INT32) TerminalDevice->TerminalConsoleModeData[ModeNumber].Columns ++ ); ++ TerminalDevice->OutputEscChar = TRUE; ++ Status = This->OutputString (This, ResizeSequence); ++ TerminalDevice->OutputEscChar = FALSE; ++ if (EFI_ERROR (Status)) { ++ return EFI_DEVICE_ERROR; ++ } ++ } ++ + This->Mode->Mode = (INT32) ModeNumber; + + Status = This->ClearScreen (This); +diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +index b2a8aeba85..eff6253465 100644 +--- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf ++++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +@@ -55,6 +55,7 @@ + DebugLib + PcdLib + BaseLib ++ PrintLib + + [Guids] + ## SOMETIMES_PRODUCES ## Variable:L"ConInDev" +@@ -87,6 +88,7 @@ + [Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm ## CONSUMES + + # [Event] + # # Relative timer event set by UnicodeToEfiKey(), used to be one 2 seconds input timeout. +-- +2.27.0 + diff --git a/SOURCES/0013-OvmfPkg-take-PcdResizeXterm-from-the-QEMU-command-li.patch b/SOURCES/0013-OvmfPkg-take-PcdResizeXterm-from-the-QEMU-command-li.patch new file mode 100644 index 0000000..ae76f7c --- /dev/null +++ b/SOURCES/0013-OvmfPkg-take-PcdResizeXterm-from-the-QEMU-command-li.patch @@ -0,0 +1,152 @@ +From 9ea7b3f689bf7d21b869adb829139be7eb91bb33 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 14 Oct 2015 15:59:06 +0200 +Subject: OvmfPkg: take PcdResizeXterm from the QEMU command line (RH only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- Extend the DSC change to the new OvmfPkg/AmdSev platform, which has been + introduced upstream in commit 30d277ed7a82 ("OvmfPkg/Amdsev: Base commit + to build encrypted boot specific OVMF", 2020-12-14), for TianoCore#3077. + + We've always patched all those DSC/FDF files in OvmfPkg down-stream that + made sense at least in theory on QEMU. (For example, we've always + patched "OvmfPkgIa32.dsc" and "OvmfPkgIa32.fdf", even though we never + build or ship the pure IA32 firmware platform.) Follow suit with + "AmdSevX64.dsc". + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- Resolve contextual conflict in the DSC files, from upstream commit + b0ed7ebdebd1 ("OvmfPkg: set fixed FlashNvStorage base addresses with -D + SMM_REQUIRE", 2020-03-12). + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- no change + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- no change + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- no change + +Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase: + +- refresh downstream-only commit 8abc2a6ddad2 against context differences + in the DSC files from upstream commit 5e167d7e784c + ("OvmfPkg/PlatformPei: don't allocate reserved mem varstore if + SMM_REQUIRE", 2017-03-12). + +Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase: + +- no changes + +Contributed-under: TianoCore Contribution Agreement 1.0 +Signed-off-by: Laszlo Ersek +(cherry picked from commit 6fa0c4d67c0bb8bde2ddd6db41c19eb0c40b2721) +(cherry picked from commit 8abc2a6ddad25af7e88dc0cf57d55dfb75fbf92d) +(cherry picked from commit b311932d3841c017a0f0fec553edcac365cc2038) +(cherry picked from commit 61914fb81cf624c9028d015533b400b2794e52d3) +(cherry picked from commit 2ebf3cc2ae99275d63bb6efd3c22dec76251a853) +(cherry picked from commit f9b73437b9b231773c1a20e0c516168817a930a2) +(cherry picked from commit 2cc462ee963d0be119bc97bfc9c70d292a40516f) +(cherry picked from commit 51e0de961029af84b5bdbfddcc9762b1819d500f) +--- + OvmfPkg/AmdSev/AmdSevX64.dsc | 1 + + OvmfPkg/OvmfPkgIa32.dsc | 1 + + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + + OvmfPkg/OvmfPkgX64.dsc | 1 + + OvmfPkg/PlatformPei/Platform.c | 1 + + OvmfPkg/PlatformPei/PlatformPei.inf | 2 ++ + 6 files changed, 7 insertions(+) + +diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc +index 5ee5445116..6ea3621225 100644 +--- a/OvmfPkg/AmdSev/AmdSevX64.dsc ++++ b/OvmfPkg/AmdSev/AmdSevX64.dsc +@@ -534,6 +534,7 @@ + [PcdsDynamicDefault] + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0 + ++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0 +diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc +index 6a5be97c05..4cacf0ea94 100644 +--- a/OvmfPkg/OvmfPkgIa32.dsc ++++ b/OvmfPkg/OvmfPkgIa32.dsc +@@ -594,6 +594,7 @@ + # ($(SMM_REQUIRE) == FALSE) + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0 + ++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm|FALSE + !if $(SMM_REQUIRE) == FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0 +diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc +index 71227d1b70..6225f8e095 100644 +--- a/OvmfPkg/OvmfPkgIa32X64.dsc ++++ b/OvmfPkg/OvmfPkgIa32X64.dsc +@@ -600,6 +600,7 @@ + # ($(SMM_REQUIRE) == FALSE) + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0 + ++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm|FALSE + !if $(SMM_REQUIRE) == FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0 +diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc +index 52f7598cf1..b66fc67563 100644 +--- a/OvmfPkg/OvmfPkgX64.dsc ++++ b/OvmfPkg/OvmfPkgX64.dsc +@@ -600,6 +600,7 @@ + # ($(SMM_REQUIRE) == FALSE) + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0 + ++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm|FALSE + !if $(SMM_REQUIRE) == FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0 +diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c +index df2d9ad015..d0e2c08de9 100644 +--- a/OvmfPkg/PlatformPei/Platform.c ++++ b/OvmfPkg/PlatformPei/Platform.c +@@ -752,6 +752,7 @@ InitializePlatform ( + MemTypeInfoInitialization (); + MemMapInitialization (); + NoexecDxeInitialization (); ++ UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdResizeXterm); + } + + InstallClearCacheCallback (); +diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf +index 67eb7aa716..7d26b43680 100644 +--- a/OvmfPkg/PlatformPei/PlatformPei.inf ++++ b/OvmfPkg/PlatformPei/PlatformPei.inf +@@ -93,6 +93,8 @@ + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved ++ gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration ++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack +-- +2.27.0 + diff --git a/SOURCES/0014-ArmVirtPkg-take-PcdResizeXterm-from-the-QEMU-command.patch b/SOURCES/0014-ArmVirtPkg-take-PcdResizeXterm-from-the-QEMU-command.patch new file mode 100644 index 0000000..31d88dc --- /dev/null +++ b/SOURCES/0014-ArmVirtPkg-take-PcdResizeXterm-from-the-QEMU-command.patch @@ -0,0 +1,216 @@ +From b846a65eeb926a483cff3e35242097eb6d21ceab Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Sun, 26 Jul 2015 08:02:50 +0000 +Subject: ArmVirtPkg: take PcdResizeXterm from the QEMU command line (RH only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- no change + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- Resolve leading context divergence in "ArmVirtPkg/ArmVirtQemu.dsc", + arising from upstream commits: + + - 82662a3b5f56 ("ArmVirtPkg/PlatformPeiLib: discover the TPM base + address from the DT", 2020-03-04) + + - ddd34a818315 ("ArmVirtPkg/ArmVirtQemu: enable TPM2 support in the PEI + phase", 2020-03-04) + + - cdc3fa54184a ("ArmVirtPkg: control PXEv4 / PXEv6 boot support from the + QEMU command line", 2020-04-28) + +- Rework the downstream patch quite a bit, paralleling the upstream work + done for in commit + range 64ab457d1f21..cdc3fa54184a: + + - Refresh copyright year in TerminalPcdProducerLib.{inf,c}. Also replace + open-coded BSDL with "SPDX-License-Identifier: BSD-2-Clause-Patent". + + - Simplify LIBRARY_CLASS: this lib instance is meant to be consumed only + via NULL class resolution (basically: as a plugin), so use NULL for + LIBRARY_CLASS, not "TerminalPcdProducerLib|DXE_DRIVER". + + - Sort the [Packages] section alphabetically in the INF file. + + - Replace the open-coded GetNamedFwCfgBoolean() function with a call to + QemuFwCfgParseBool(), from QemuFwCfgSimpleParserLib. + + - Add the SOMETIMES_PRODUCES usage comment in the [Pcd] section of the + INF file. + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- no change + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- no change + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- no change + +Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase: + +- Refresh downstream-only commit d4564d39dfdb against context changes in + "ArmVirtPkg/ArmVirtQemu.dsc" from upstream commit 7e5f1b673870 + ("ArmVirtPkg/PlatformHasAcpiDtDxe: allow guest level ACPI disable + override", 2017-03-29). + +Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase: + +- Adapt commit 6b97969096a3 to the fact that upstream has deprecated such + setter functions for dynamic PCDs that don't return a status code (such + as PcdSetBool()). Employ PcdSetBoolS(), and assert that it succeeds -- + there's really no circumstance in this case when it could fail. + +Contributed-under: TianoCore Contribution Agreement 1.0 +Signed-off-by: Laszlo Ersek +(cherry picked from commit d4564d39dfdbf74e762af43314005a2c026cb262) +(cherry picked from commit c9081ebe3bcd28e5cce4bf58bd8d4fca12f9af7c) +(cherry picked from commit 8e92730c8e1cdb642b3b3e680e643ff774a90c65) +(cherry picked from commit 9448b6b46267d8d807fac0c648e693171bb34806) +(cherry picked from commit 232fcf06f6b3048b7c2ebd6931f23186b3852f04) +(cherry picked from commit 8338545260fbb423f796d5196faaaf8ff6e1ed99) +(cherry picked from commit a5f7a57bf390f1f340ff1d1f1884a73716817ef1) +--- + ArmVirtPkg/ArmVirtQemu.dsc | 7 +++- + .../TerminalPcdProducerLib.c | 34 +++++++++++++++++++ + .../TerminalPcdProducerLib.inf | 33 ++++++++++++++++++ + OvmfPkg/PlatformPei/PlatformPei.inf | 1 - + 4 files changed, 73 insertions(+), 2 deletions(-) + create mode 100644 ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.c + create mode 100644 ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.inf + +diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc +index 891e065311..e0476ede4f 100644 +--- a/ArmVirtPkg/ArmVirtQemu.dsc ++++ b/ArmVirtPkg/ArmVirtQemu.dsc +@@ -282,6 +282,8 @@ + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask|0 + !endif + ++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm|FALSE ++ + [PcdsDynamicHii] + gArmVirtTokenSpaceGuid.PcdForceNoAcpi|L"ForceNoAcpi"|gArmVirtVariableGuid|0x0|FALSE|NV,BS + +@@ -384,7 +386,10 @@ + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf +- MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf ++ MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf { ++ ++ NULL|ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.inf ++ } + MdeModulePkg/Universal/SerialDxe/SerialDxe.inf + + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf +diff --git a/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.c b/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.c +new file mode 100644 +index 0000000000..bfd3a6a535 +--- /dev/null ++++ b/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.c +@@ -0,0 +1,34 @@ ++/** @file ++* Plugin library for setting up dynamic PCDs for TerminalDxe, from fw_cfg ++* ++* Copyright (C) 2015-2020, Red Hat, Inc. ++* Copyright (c) 2014, Linaro Ltd. All rights reserved.
++* ++* SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#include ++#include ++#include ++ ++#define UPDATE_BOOLEAN_PCD_FROM_FW_CFG(TokenName) \ ++ do { \ ++ BOOLEAN Setting; \ ++ RETURN_STATUS PcdStatus; \ ++ \ ++ if (!RETURN_ERROR (QemuFwCfgParseBool ( \ ++ "opt/org.tianocore.edk2.aavmf/" #TokenName, &Setting))) { \ ++ PcdStatus = PcdSetBoolS (TokenName, Setting); \ ++ ASSERT_RETURN_ERROR (PcdStatus); \ ++ } \ ++ } while (0) ++ ++RETURN_STATUS ++EFIAPI ++TerminalPcdProducerLibConstructor ( ++ VOID ++ ) ++{ ++ UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdResizeXterm); ++ return RETURN_SUCCESS; ++} +diff --git a/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.inf b/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.inf +new file mode 100644 +index 0000000000..a51dbd1670 +--- /dev/null ++++ b/ArmVirtPkg/Library/TerminalPcdProducerLib/TerminalPcdProducerLib.inf +@@ -0,0 +1,33 @@ ++## @file ++# Plugin library for setting up dynamic PCDs for TerminalDxe, from fw_cfg ++# ++# Copyright (C) 2015-2020, Red Hat, Inc. ++# Copyright (c) 2014, Linaro Ltd. All rights reserved.
++# ++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++ ++[Defines] ++ INF_VERSION = 0x00010005 ++ BASE_NAME = TerminalPcdProducerLib ++ FILE_GUID = 4a0c5ed7-8c42-4c01-8f4c-7bf258316a96 ++ MODULE_TYPE = BASE ++ VERSION_STRING = 1.0 ++ LIBRARY_CLASS = NULL ++ CONSTRUCTOR = TerminalPcdProducerLibConstructor ++ ++[Sources] ++ TerminalPcdProducerLib.c ++ ++[Packages] ++ MdeModulePkg/MdeModulePkg.dec ++ MdePkg/MdePkg.dec ++ OvmfPkg/OvmfPkg.dec ++ ++[LibraryClasses] ++ DebugLib ++ PcdLib ++ QemuFwCfgSimpleParserLib ++ ++[Pcd] ++ gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm ## SOMETIMES_PRODUCES +diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf +index 7d26b43680..69eb3edad3 100644 +--- a/OvmfPkg/PlatformPei/PlatformPei.inf ++++ b/OvmfPkg/PlatformPei/PlatformPei.inf +@@ -93,7 +93,6 @@ + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved +- gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration + gEfiMdeModulePkgTokenSpaceGuid.PcdResizeXterm + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable +-- +2.27.0 + diff --git a/SOURCES/0015-OvmfPkg-allow-exclusion-of-the-shell-from-the-firmwa.patch b/SOURCES/0015-OvmfPkg-allow-exclusion-of-the-shell-from-the-firmwa.patch new file mode 100644 index 0000000..03a185b --- /dev/null +++ b/SOURCES/0015-OvmfPkg-allow-exclusion-of-the-shell-from-the-firmwa.patch @@ -0,0 +1,172 @@ +From e8e12cb7d3a47e5823cf2cb12c9bfe5901d3b100 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Tue, 4 Nov 2014 23:02:53 +0100 +Subject: OvmfPkg: allow exclusion of the shell from the firmware image (RH + only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- No manual / explicit code change is necessary, because the newly + inherited OvmfPkg/AmdSev platform already has its own BUILD_SHELL + build-time macro (feature test flag), with default value FALSE -- from + upstream commit b261a30c900a ("OvmfPkg/AmdSev: add Grub Firmware Volume + Package", 2020-12-14). + +- Contextual differences from new upstream commits 2d8ca4f90eae ("OvmfPkg: + enable HttpDynamicCommand", 2020-10-01) and 5ab6a0e1c8e9 ("OvmfPkg: + introduce VirtioFsDxe", 2020-12-21) have been auto-resolved by + git-cherry-pick. + +- Remove obsolete commit message tags related to downstream patch + management: Message-id, Patchwork-id, O-Subject, Acked-by + (RHBZ#1846481). + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- context difference from upstream commit ec41733cfd10 ("OvmfPkg: add the + 'initrd' dynamic shell command", 2020-03-04) correctly auto-resolved + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- no change + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- update the patch against the following upstream commits: + - 4b888334d234 ("OvmfPkg: Remove EdkShellBinPkg in FDF", 2018-11-19) + - 277a3958d93a ("OvmfPkg: Don't include TftpDynamicCommand in XCODE5 + tool chain", 2018-11-27) + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- no change + +Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase: + +- no changes + +Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase: + +- no changes + +Bugzilla: 1147592 + +When '-D EXCLUDE_SHELL_FROM_FD' is passed to 'build', exclude the shell +binary from the firmware image. + +Peter Jones advised us that firmware vendors for physical systems disable +the memory-mapped, firmware image-contained UEFI shell in +SecureBoot-enabled builds. The reason being that the memory-mapped shell +can always load, it may have direct access to various hardware in the +system, and it can run UEFI shell scripts (which cannot be signed at all). + +Intended use of the new build option: + +- In-tree builds: don't pass '-D EXCLUDE_SHELL_FROM_FD'. The resultant + firmware image will contain a shell binary, independently of SecureBoot + enablement, which is flexible for interactive development. (Ie. no + change for in-tree builds.) + +- RPM builds: pass both '-D SECURE_BOOT_ENABLE' and + '-D EXCLUDE_SHELL_FROM_FD'. The resultant RPM will provide: + + - OVMF_CODE.fd: SecureBoot-enabled firmware, without builtin UEFI shell, + + - OVMF_VARS.fd: variable store template matching OVMF_CODE.fd, + + - UefiShell.iso: a bootable ISO image with the shell on it as default + boot loader. The shell binary will load when SecureBoot is turned off, + and won't load when SecureBoot is turned on (because it is not + signed). + + UefiShell.iso is the reason we're not excluding the shell from the DSC + files as well, only the FDF files -- when '-D EXCLUDE_SHELL_FROM_FD' + is specified, the shell binary needs to be built the same, only it + will be included in UefiShell.iso. + +Signed-off-by: Laszlo Ersek +(cherry picked from commit 9c391def70366cabae08e6008814299c3372fafd) +(cherry picked from commit d9dd9ee42937b2611fe37183cc9ec7f62d946933) +(cherry picked from commit 23df46ebbe7b09451d3a05034acd4d3a25e7177b) +(cherry picked from commit f0303f71d576c51b01c4ff961b429d0e0e707245) +(cherry picked from commit bbd64eb8658e9a33eab4227d9f4e51ad78d9f687) +(cherry picked from commit 8628ef1b8d675ebec39d83834abbe3c8c8c42cf4) +(cherry picked from commit 229c88dc3ded9baeaca8b87767dc5c41c05afd6e) +(cherry picked from commit c2812d7189dee06c780f05a5880eb421c359a687) +--- + OvmfPkg/OvmfPkgIa32.fdf | 2 ++ + OvmfPkg/OvmfPkgIa32X64.fdf | 2 ++ + OvmfPkg/OvmfPkgX64.fdf | 2 ++ + 3 files changed, 6 insertions(+) + +diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf +index 775ea2d710..00ea14adf0 100644 +--- a/OvmfPkg/OvmfPkgIa32.fdf ++++ b/OvmfPkg/OvmfPkgIa32.fdf +@@ -290,12 +290,14 @@ INF FatPkg/EnhancedFatDxe/Fat.inf + INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf + INF OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf + ++!ifndef $(EXCLUDE_SHELL_FROM_FD) + !if $(TOOL_CHAIN_TAG) != "XCODE5" + INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf + INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf + INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf + !endif + INF ShellPkg/Application/Shell/Shell.inf ++!endif + + INF MdeModulePkg/Logo/LogoDxe.inf + +diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf +index 9d8695922f..e33a40c44e 100644 +--- a/OvmfPkg/OvmfPkgIa32X64.fdf ++++ b/OvmfPkg/OvmfPkgIa32X64.fdf +@@ -294,12 +294,14 @@ INF FatPkg/EnhancedFatDxe/Fat.inf + INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf + INF OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf + ++!ifndef $(EXCLUDE_SHELL_FROM_FD) + !if $(TOOL_CHAIN_TAG) != "XCODE5" + INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf + INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf + INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf + !endif + INF ShellPkg/Application/Shell/Shell.inf ++!endif + + INF MdeModulePkg/Logo/LogoDxe.inf + +diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf +index b6cc3cabdd..85b4b23857 100644 +--- a/OvmfPkg/OvmfPkgX64.fdf ++++ b/OvmfPkg/OvmfPkgX64.fdf +@@ -310,12 +310,14 @@ INF FatPkg/EnhancedFatDxe/Fat.inf + INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf + INF OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf + ++!ifndef $(EXCLUDE_SHELL_FROM_FD) + !if $(TOOL_CHAIN_TAG) != "XCODE5" + INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf + INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf + INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf + !endif + INF ShellPkg/Application/Shell/Shell.inf ++!endif + + INF MdeModulePkg/Logo/LogoDxe.inf + +-- +2.27.0 + diff --git a/SOURCES/0016-ArmPlatformPkg-introduce-fixed-PCD-for-early-hello-m.patch b/SOURCES/0016-ArmPlatformPkg-introduce-fixed-PCD-for-early-hello-m.patch new file mode 100644 index 0000000..2019fb9 --- /dev/null +++ b/SOURCES/0016-ArmPlatformPkg-introduce-fixed-PCD-for-early-hello-m.patch @@ -0,0 +1,93 @@ +From eba5ecf4b2611d593a978ccac804314ab7848754 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 14 Oct 2015 13:49:43 +0200 +Subject: ArmPlatformPkg: introduce fixed PCD for early hello message (RH only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- no change + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- no change + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- no change + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- no change + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- no changes + +Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase: + +- no changes + +Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase: + +- no changes + +Drew has proposed that ARM|AARCH64 platform firmware (especially virtual +machine firmware) print a reasonably early, simple hello message to the +serial port, regardless of debug mask settings. This should inform +interactive users, and provide some rough help in localizing boot +problems, even with restrictive debug masks. + +If a platform doesn't want this feature, it should stick with the default +empty string. + +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1270279 +Downstream only: +. + +Suggested-by: Drew Jones +Contributed-under: TianoCore Contribution Agreement 1.0 +Signed-off-by: Laszlo Ersek +(cherry picked from commit 7ce97b06421434c82095f01a1753a8c9c546cc30) +(cherry picked from commit 20b1f1cbd0590aa71c6d99d35e23cf08e0707750) +(cherry picked from commit 6734b88cf7abcaf42632e3d2fc469b2169dd2f16) +(cherry picked from commit ef77da632559e9baa1c69869e4cbea377068ef27) +(cherry picked from commit 58755c51d3252312d80cbcb97928d71199c2f5e1) +(cherry picked from commit c3f07e323e76856f1b42ea7b8c598ba3201c28a2) +(cherry picked from commit 9f756c1ad83cc81f7d892cd036d59a2b567b02dc) +(cherry picked from commit c75aea7a738ac7fb944c0695a4bfffc3985afaa9) +--- + ArmPlatformPkg/ArmPlatformPkg.dec | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/ArmPlatformPkg/ArmPlatformPkg.dec b/ArmPlatformPkg/ArmPlatformPkg.dec +index 3a25ddcdc8..b2b58553c7 100644 +--- a/ArmPlatformPkg/ArmPlatformPkg.dec ++++ b/ArmPlatformPkg/ArmPlatformPkg.dec +@@ -121,6 +121,13 @@ + ## If set, this will swap settings for HDLCD RED_SELECT and BLUE_SELECT registers + gArmPlatformTokenSpaceGuid.PcdArmHdLcdSwapBlueRedSelect|FALSE|BOOLEAN|0x00000045 + ++ # ++ # Early hello message (ASCII string), printed to the serial port. ++ # If set to the empty string, nothing is printed. ++ # Otherwise, a trailing CRLF should be specified explicitly. ++ # ++ gArmPlatformTokenSpaceGuid.PcdEarlyHelloMessage|""|VOID*|0x00000100 ++ + [PcdsFixedAtBuild.common,PcdsDynamic.common] + ## PL031 RealTimeClock + gArmPlatformTokenSpaceGuid.PcdPL031RtcBase|0x0|UINT32|0x00000024 +-- +2.27.0 + diff --git a/SOURCES/0017-ArmPlatformPkg-PrePeiCore-write-early-hello-message-.patch b/SOURCES/0017-ArmPlatformPkg-PrePeiCore-write-early-hello-message-.patch new file mode 100644 index 0000000..258c56d --- /dev/null +++ b/SOURCES/0017-ArmPlatformPkg-PrePeiCore-write-early-hello-message-.patch @@ -0,0 +1,145 @@ +From 8be1d7253ba8a7d30bb54835ef1fc866aa62e216 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 14 Oct 2015 13:59:20 +0200 +Subject: ArmPlatformPkg: PrePeiCore: write early hello message to the serial + port (RH) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- no change + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- no change + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- no change + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- no change + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- adapt to upstream commit 7e2a8dfe8a9a ("ArmPlatformPkg/PrePeiCore: seed + temporary stack before entering PEI core", 2017-11-09) -- conflict + resolution in "ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf" + +Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase: + +- no changes + +Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase: + +- no changes + +The FixedPcdGetSize() macro expands to an integer constant, therefore an +optimizing compiler can eliminate the new code, if the platform DSC +doesn't override the empty string (size=1) default of +PcdEarlyHelloMessage. + +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1270279 +Downstream only: +. + +Contributed-under: TianoCore Contribution Agreement 1.0 +Signed-off-by: Laszlo Ersek +(cherry picked from commit b16c4c505ce0e27305235533eac9236aa66f132e) +(cherry picked from commit 742e5bf6d5ce5a1e73879d6e5c0dd00feda7a9ac) +(cherry picked from commit 93d69eb9393cf05af90676253875c59c1bec67fd) +(cherry picked from commit 638594083b191f84f5d9333eb6147a31570f5a5a) +(cherry picked from commit f4b7aae411d88b2b83f85d20ef06a4032a57e7de) +(cherry picked from commit bb71490fdda3b38fa9f071d281b863f9b64363bf) +(cherry picked from commit 8d5a8827aabc67cb2a046697e1a750ca8d9cc453) +(cherry picked from commit 49fe5596cd79c94d903c4d506c563d642ccd69aa) +--- + ArmPlatformPkg/PrePeiCore/MainMPCore.c | 5 +++++ + ArmPlatformPkg/PrePeiCore/MainUniCore.c | 5 +++++ + ArmPlatformPkg/PrePeiCore/PrePeiCore.h | 1 + + ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf | 2 ++ + ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf | 2 ++ + 5 files changed, 15 insertions(+) + +diff --git a/ArmPlatformPkg/PrePeiCore/MainMPCore.c b/ArmPlatformPkg/PrePeiCore/MainMPCore.c +index 859f1adf20..cf9e65bb7c 100644 +--- a/ArmPlatformPkg/PrePeiCore/MainMPCore.c ++++ b/ArmPlatformPkg/PrePeiCore/MainMPCore.c +@@ -111,6 +111,11 @@ PrimaryMain ( + UINTN TemporaryRamBase; + UINTN TemporaryRamSize; + ++ if (FixedPcdGetSize (PcdEarlyHelloMessage) > 1) { ++ SerialPortWrite (FixedPcdGetPtr (PcdEarlyHelloMessage), ++ FixedPcdGetSize (PcdEarlyHelloMessage) - 1); ++ } ++ + CreatePpiList (&PpiListSize, &PpiList); + + // Enable the GIC Distributor +diff --git a/ArmPlatformPkg/PrePeiCore/MainUniCore.c b/ArmPlatformPkg/PrePeiCore/MainUniCore.c +index 220f9b5680..158cc34c77 100644 +--- a/ArmPlatformPkg/PrePeiCore/MainUniCore.c ++++ b/ArmPlatformPkg/PrePeiCore/MainUniCore.c +@@ -29,6 +29,11 @@ PrimaryMain ( + UINTN TemporaryRamBase; + UINTN TemporaryRamSize; + ++ if (FixedPcdGetSize (PcdEarlyHelloMessage) > 1) { ++ SerialPortWrite (FixedPcdGetPtr (PcdEarlyHelloMessage), ++ FixedPcdGetSize (PcdEarlyHelloMessage) - 1); ++ } ++ + CreatePpiList (&PpiListSize, &PpiList); + + // Adjust the Temporary Ram as the new Ppi List (Common + Platform Ppi Lists) is created at +diff --git a/ArmPlatformPkg/PrePeiCore/PrePeiCore.h b/ArmPlatformPkg/PrePeiCore/PrePeiCore.h +index 7b155a8a61..e9e283f9ec 100644 +--- a/ArmPlatformPkg/PrePeiCore/PrePeiCore.h ++++ b/ArmPlatformPkg/PrePeiCore/PrePeiCore.h +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + #include +diff --git a/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf b/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf +index fb01dd1a11..a6681c1032 100644 +--- a/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf ++++ b/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf +@@ -69,6 +69,8 @@ + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize + ++ gArmPlatformTokenSpaceGuid.PcdEarlyHelloMessage ++ + gArmTokenSpaceGuid.PcdGicDistributorBase + gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase + gArmTokenSpaceGuid.PcdGicSgiIntId +diff --git a/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf b/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf +index e9eb092d3a..c98dc82f0c 100644 +--- a/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf ++++ b/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf +@@ -67,4 +67,6 @@ + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize + ++ gArmPlatformTokenSpaceGuid.PcdEarlyHelloMessage ++ + gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack +-- +2.27.0 + diff --git a/SOURCES/0018-ArmVirtPkg-set-early-hello-message-RH-only.patch b/SOURCES/0018-ArmVirtPkg-set-early-hello-message-RH-only.patch new file mode 100644 index 0000000..23137c2 --- /dev/null +++ b/SOURCES/0018-ArmVirtPkg-set-early-hello-message-RH-only.patch @@ -0,0 +1,82 @@ +From 12873d08db00e113ef28eb4552f478cd4ffb3393 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 14 Oct 2015 14:07:17 +0200 +Subject: ArmVirtPkg: set early hello message (RH only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- no change + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- context difference from upstream commit f5cb3767038e + ("ArmVirtPkg/ArmVirtQemu: add ResetSystem PEIM for upcoming TPM2 + support", 2020-03-04) automatically resolved correctly + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- no change + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- resolve context conflict with upstream commit eaa1e98ae31d ("ArmVirtPkg: + don't set PcdCoreCount", 2019-02-13) + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- no changes + +Notes about the 20170228-c325e41585e3 -> 20171011-92d07e48907f rebase: + +- no changes + +Notes about the 20160608b-988715a -> 20170228-c325e41585e3 rebase: + +- no changes + +Print a friendly banner on QEMU, regardless of debug mask settings. + +RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1270279 +Downstream only: +. + +Contributed-under: TianoCore Contribution Agreement 1.0 +Signed-off-by: Laszlo Ersek +(cherry picked from commit 5d4a15b9019728b2d96322bc679099da49916925) +(cherry picked from commit 179df76dbb0d199bd905236e98775b4059c6502a) +(cherry picked from commit ce3f59d0710c24c162d5222bbf5cd7e36180c80c) +(cherry picked from commit c201a8e6ae28d75f7ba581828b533c3b26fa7f18) +(cherry picked from commit 2d4db6ec70e004cd9ac147615d17033bee5d3b18) +(cherry picked from commit fb2032bbea7e02c426855cf86a323556d493fd8a) +(cherry picked from commit ba73b99d5cb38f87c1a8f0936d515eaaefa3f04b) +(cherry picked from commit 72550e12ae469012a505bf5b98a6543a754028d3) +--- + ArmVirtPkg/ArmVirtQemu.dsc | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc +index e0476ede4f..ec0edf6e7b 100644 +--- a/ArmVirtPkg/ArmVirtQemu.dsc ++++ b/ArmVirtPkg/ArmVirtQemu.dsc +@@ -134,6 +134,7 @@ + gArmVirtTokenSpaceGuid.PcdTpm2SupportEnabled|$(TPM2_ENABLE) + + [PcdsFixedAtBuild.common] ++ gArmPlatformTokenSpaceGuid.PcdEarlyHelloMessage|"UEFI firmware starting.\r\n" + !if $(ARCH) == AARCH64 + gArmTokenSpaceGuid.PcdVFPEnabled|1 + !endif +-- +2.27.0 + diff --git a/SOURCES/0019-OvmfPkg-enable-DEBUG_VERBOSE-RHEL-only.patch b/SOURCES/0019-OvmfPkg-enable-DEBUG_VERBOSE-RHEL-only.patch new file mode 100644 index 0000000..070ecc4 --- /dev/null +++ b/SOURCES/0019-OvmfPkg-enable-DEBUG_VERBOSE-RHEL-only.patch @@ -0,0 +1,121 @@ +From 02687f83845b9ae8455655e117f0b7cdaa18ba5c Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 21 Nov 2017 00:57:45 +0100 +Subject: OvmfPkg: enable DEBUG_VERBOSE (RHEL only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- Extend the DSC change to the new OvmfPkg/AmdSev platform, which has been + introduced upstream in commit 30d277ed7a82 ("OvmfPkg/Amdsev: Base commit + to build encrypted boot specific OVMF", 2020-12-14), for TianoCore#3077. + +- Remove obsolete commit message tags related to downstream patch + management: Message-id, Patchwork-id, O-Subject, Acked-by, From + (RHBZ#1846481). + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- context difference from upstream commit 46bb81200742 ("OvmfPkg: Make + SOURCE_DEBUG_ENABLE actually need to be set to TRUE", 2019-10-22) + resolved automatically + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- no change + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- no change + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- no changes + +Bugzilla: 1488247 + +Set the DEBUG_VERBOSE bit (0x00400000) in the log mask. We want detailed +debug messages, and code in OvmfPkg logs many messages on the +DEBUG_VERBOSE level. + +Signed-off-by: Laszlo Ersek +Signed-off-by: Paolo Bonzini +(this patch was previously applied as commit 78d3ed73172b5738e32d2b0bc03f7984b9584117) +(cherry picked from commit 7aeeaabc9871f657e65d2b99d81011b4964a1ce9) +(cherry picked from commit a0617a6be1a80966099ddceb010f89202a79ee76) +(cherry picked from commit 759bd3f591e2db699bdef4c7ea4e97c908e7f027) +(cherry picked from commit 7e6d5dc4078c64be6d55d8fc3317c59a91507a50) +(cherry picked from commit 3cb92f9ba18ac79911bd5258ff4f949cc617ae89) +(cherry picked from commit 5ecc18badaabe774d9d0806b027ab63a30c6a2d7) +--- + OvmfPkg/AmdSev/AmdSevX64.dsc | 2 +- + OvmfPkg/OvmfPkgIa32.dsc | 2 +- + OvmfPkg/OvmfPkgIa32X64.dsc | 2 +- + OvmfPkg/OvmfPkgX64.dsc | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc +index 6ea3621225..366fa79f62 100644 +--- a/OvmfPkg/AmdSev/AmdSevX64.dsc ++++ b/OvmfPkg/AmdSev/AmdSevX64.dsc +@@ -486,7 +486,7 @@ + # DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may + # // significantly impact boot performance + # DEBUG_ERROR 0x80000000 // Error +- gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8040004F + + !if $(SOURCE_DEBUG_ENABLE) == TRUE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 +diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc +index 4cacf0ea94..2aacf1a5ff 100644 +--- a/OvmfPkg/OvmfPkgIa32.dsc ++++ b/OvmfPkg/OvmfPkgIa32.dsc +@@ -534,7 +534,7 @@ + # DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may + # // significantly impact boot performance + # DEBUG_ERROR 0x80000000 // Error +- gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8040004F + + !if $(SOURCE_DEBUG_ENABLE) == TRUE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 +diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc +index 6225f8e095..2613c83adb 100644 +--- a/OvmfPkg/OvmfPkgIa32X64.dsc ++++ b/OvmfPkg/OvmfPkgIa32X64.dsc +@@ -538,7 +538,7 @@ + # DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may + # // significantly impact boot performance + # DEBUG_ERROR 0x80000000 // Error +- gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8040004F + + !if $(SOURCE_DEBUG_ENABLE) == TRUE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 +diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc +index b66fc67563..d7d34eeef2 100644 +--- a/OvmfPkg/OvmfPkgX64.dsc ++++ b/OvmfPkg/OvmfPkgX64.dsc +@@ -540,7 +540,7 @@ + # DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may + # // significantly impact boot performance + # DEBUG_ERROR 0x80000000 // Error +- gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8040004F + + !if $(SOURCE_DEBUG_ENABLE) == TRUE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 +-- +2.27.0 + diff --git a/SOURCES/0020-OvmfPkg-silence-DEBUG_VERBOSE-0x00400000-in-QemuVide.patch b/SOURCES/0020-OvmfPkg-silence-DEBUG_VERBOSE-0x00400000-in-QemuVide.patch new file mode 100644 index 0000000..3ec8a64 --- /dev/null +++ b/SOURCES/0020-OvmfPkg-silence-DEBUG_VERBOSE-0x00400000-in-QemuVide.patch @@ -0,0 +1,173 @@ +From a5dd9e06c570b2c003a2b6aea681f0d93bfbfdc4 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 21 Nov 2017 00:57:46 +0100 +Subject: OvmfPkg: silence DEBUG_VERBOSE (0x00400000) in + QemuVideoDxe/QemuRamfbDxe (RH) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- Extend the DSC change to the new OvmfPkg/AmdSev platform, which has been + introduced upstream in commit 30d277ed7a82 ("OvmfPkg/Amdsev: Base commit + to build encrypted boot specific OVMF", 2020-12-14), for TianoCore#3077. + +- Remove obsolete commit message tags related to downstream patch + management: Message-id, Patchwork-id, O-Subject, Acked-by, From + (RHBZ#1846481). + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- no change + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- Due to upstream commit 4b04d9d73604 ("OvmfPkg: Don't build in + QemuVideoDxe when we have CSM", 2019-06-26), the contexts of + "QemuVideoDxe.inf" / "QemuRamfbDxe.inf" have changed in the DSC files. + Resolve the conflict manually. + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- Upstream commit 1d25ff51af5c ("OvmfPkg: add QemuRamfbDxe", 2018-06-14) + introduced another GOP driver that consumes FrameBufferBltLib, and + thereby produces a large number of (mostly useless) debug messages at + the DEBUG_VERBOSE level. Extend the patch to suppress those messages in + both QemuVideoDxe and QemuRamfbDxe; update the subject accordingly. + QemuRamfbDxe itself doesn't log anything at the VERBOSE level (see also + the original commit message at the bottom of this downstream patch). + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- no changes + +Bugzilla: 1488247 + +In commit 5b2291f9567a ("OvmfPkg: QemuVideoDxe uses +MdeModulePkg/FrameBufferLib"), QemuVideoDxe was rebased to +FrameBufferBltLib. + +The FrameBufferBltLib instance added in commit b1ca386074bd +("MdeModulePkg: Add FrameBufferBltLib library instance") logs many +messages on the VERBOSE level; for example, a normal boot with OVMF can +produce 500+ "VideoFill" messages, dependent on the progress bar, when the +VERBOSE bit is set in PcdDebugPrintErrorLevel. + +QemuVideoDxe itself doesn't log anything at the VERBOSE level, so we lose +none of its messages this way. + +Signed-off-by: Laszlo Ersek +Signed-off-by: Paolo Bonzini +(this patch was previously applied as commit 9b0d031dee7e823f6717bab73e422fbc6f0a6c52) +(cherry picked from commit 9122d5f2e8d8d289064d1e1700cb61964d9931f3) +(cherry picked from commit 7eb3be1d4ccafc26c11fe5afb95cc12b250ce6f0) +(cherry picked from commit bd650684712fb840dbcda5d6eaee065bd9e91fa1) +(cherry picked from commit b06b87f8ffd4fed4ef7eacb13689a9b6d111f850) +(cherry picked from commit c8c3f893e7c3710afe45c46839e97954871536e4) +(cherry picked from commit 1355849ad97c1e4a5c430597a377165a5cc118f7) +--- + OvmfPkg/AmdSev/AmdSevX64.dsc | 10 ++++++++-- + OvmfPkg/OvmfPkgIa32.dsc | 10 ++++++++-- + OvmfPkg/OvmfPkgIa32X64.dsc | 10 ++++++++-- + OvmfPkg/OvmfPkgX64.dsc | 10 ++++++++-- + 4 files changed, 32 insertions(+), 8 deletions(-) + +diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc +index 366fa79f62..a289d8a573 100644 +--- a/OvmfPkg/AmdSev/AmdSevX64.dsc ++++ b/OvmfPkg/AmdSev/AmdSevX64.dsc +@@ -750,8 +750,14 @@ + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + +- OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf +- OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf ++ OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } ++ OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } + OvmfPkg/VirtioGpuDxe/VirtioGpu.inf + + # +diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc +index 2aacf1a5ff..1a5cfa4c6d 100644 +--- a/OvmfPkg/OvmfPkgIa32.dsc ++++ b/OvmfPkg/OvmfPkgIa32.dsc +@@ -846,9 +846,15 @@ + MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + + !ifndef $(CSM_ENABLE) +- OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf ++ OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } + !endif +- OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf ++ OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } + OvmfPkg/VirtioGpuDxe/VirtioGpu.inf + + # +diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc +index 2613c83adb..11002ffd95 100644 +--- a/OvmfPkg/OvmfPkgIa32X64.dsc ++++ b/OvmfPkg/OvmfPkgIa32X64.dsc +@@ -860,9 +860,15 @@ + MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + + !ifndef $(CSM_ENABLE) +- OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf ++ OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } + !endif +- OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf ++ OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } + OvmfPkg/VirtioGpuDxe/VirtioGpu.inf + + # +diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc +index d7d34eeef2..f176aa4061 100644 +--- a/OvmfPkg/OvmfPkgX64.dsc ++++ b/OvmfPkg/OvmfPkgX64.dsc +@@ -858,9 +858,15 @@ + MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + + !ifndef $(CSM_ENABLE) +- OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf ++ OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } + !endif +- OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf ++ OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } + OvmfPkg/VirtioGpuDxe/VirtioGpu.inf + + # +-- +2.27.0 + diff --git a/SOURCES/0021-ArmVirtPkg-silence-DEBUG_VERBOSE-0x00400000-in-QemuR.patch b/SOURCES/0021-ArmVirtPkg-silence-DEBUG_VERBOSE-0x00400000-in-QemuR.patch new file mode 100644 index 0000000..7160188 --- /dev/null +++ b/SOURCES/0021-ArmVirtPkg-silence-DEBUG_VERBOSE-0x00400000-in-QemuR.patch @@ -0,0 +1,97 @@ +From ccc2c9c85f43662f942bf5c303f4a1a9f964c36d Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 27 Jan 2016 03:05:18 +0100 +Subject: ArmVirtPkg: silence DEBUG_VERBOSE (0x00400000) in QemuRamfbDxe (RH + only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- no change + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- no change + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- The previous version of this patch (downstream commit 76b4ac28e975) + caused a regression (RHBZ#1714446), which was fixed up in downstream + commit 5a216abaa737 ("ArmVirtPkg: silence DEBUG_VERBOSE masking + ~0x00400000 in QemuRamfbDxe (RH only)", 2019-08-05). + + Squash the fixup into the original patch. Fuse the commit messages. + (Acked-by tags are not preserved, lest we confuse ourselves while + reviewing this rebase.) + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- new patch, due to upstream commit c64688f36a8b ("ArmVirtPkg: add + QemuRamfbDxe", 2018-06-14) + +QemuRamfbDxe uses FrameBufferLib. The FrameBufferBltLib instance added in +commit b1ca386074bd ("MdeModulePkg: Add FrameBufferBltLib library +instance") logs many messages on the VERBOSE level; for example, a normal +boot with ArmVirtQemu[Kernel] can produce 500+ "VideoFill" messages, +dependent on the progress bar, when the VERBOSE bit is set in +PcdDebugPrintErrorLevel. + +Clear the VERBOSE bit without touching other bits -- those other bits +differ between the "silent" and "verbose" builds, so we can't set them as +constants. + +QemuRamfbDxe itself doesn't log anything at the VERBOSE level, so we lose +none of its messages, with the VERBOSE bit clear. + +Signed-off-by: Laszlo Ersek +(cherry picked from commit 76b4ac28e975bd63c25db903a1d42c47b38cc756) +Reported-by: Andrew Jones +Suggested-by: Laszlo Ersek +Signed-off-by: Philippe Mathieu-Daude +(cherry picked from commit 5a216abaa737195327235e37563b18a6bf2a74dc) +Signed-off-by: Laszlo Ersek +(cherry picked from commit e5b8152bced2364a1ded0926dbba4d65e23e3f84) +(cherry picked from commit e7f57f154439c1c18ea5030b01f8d7bc492698b2) +--- + ArmVirtPkg/ArmVirtQemu.dsc | 5 ++++- + ArmVirtPkg/ArmVirtQemuKernel.dsc | 5 ++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc +index ec0edf6e7b..e6fad9f066 100644 +--- a/ArmVirtPkg/ArmVirtQemu.dsc ++++ b/ArmVirtPkg/ArmVirtQemu.dsc +@@ -509,7 +509,10 @@ + # + # Video support + # +- OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf ++ OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|($(DEBUG_PRINT_ERROR_LEVEL)) & 0xFFBFFFFF ++ } + OvmfPkg/VirtioGpuDxe/VirtioGpu.inf + OvmfPkg/PlatformDxe/Platform.inf + +diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc +index a8bb83b288..656c9d99a3 100644 +--- a/ArmVirtPkg/ArmVirtQemuKernel.dsc ++++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc +@@ -438,7 +438,10 @@ + # + # Video support + # +- OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf ++ OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|($(DEBUG_PRINT_ERROR_LEVEL)) & 0xFFBFFFFF ++ } + OvmfPkg/VirtioGpuDxe/VirtioGpu.inf + OvmfPkg/PlatformDxe/Platform.inf + +-- +2.27.0 + diff --git a/SOURCES/0022-OvmfPkg-QemuRamfbDxe-Do-not-report-DXE-failure-on-Aa.patch b/SOURCES/0022-OvmfPkg-QemuRamfbDxe-Do-not-report-DXE-failure-on-Aa.patch new file mode 100644 index 0000000..9cf8fe5 --- /dev/null +++ b/SOURCES/0022-OvmfPkg-QemuRamfbDxe-Do-not-report-DXE-failure-on-Aa.patch @@ -0,0 +1,95 @@ +From b3147a5ce92a149532ef1ec47cdf14082a56654d Mon Sep 17 00:00:00 2001 +From: Philippe Mathieu-Daude +Date: Thu, 1 Aug 2019 20:43:48 +0200 +Subject: OvmfPkg: QemuRamfbDxe: Do not report DXE failure on Aarch64 silent + builds (RH only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- no change + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- no change + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- We have to carry this downstream-only patch -- committed originally as + aaaedc1e2cfd -- indefinitely. + +- To avoid confusion, remove the tags from the commit message that had + been added by the downstream maintainer scripts, such as: Message-id, + Patchwork-id, O-Subject, Acked-by. These remain available on the + original downstream commit. The Bugzilla line is preserved, as it + doesn't relate to a specific posting, but to the problem. + +Bugzilla: 1714446 + +To suppress an error message on the silent build when ramfb is +not configured, change QemuRamfbDxe to return EFI_SUCCESS even +when it fails. +Some memory is wasted (driver stays resident without +any good use), but it is mostly harmless, as the memory +is released by the OS after ExitBootServices(). + +Suggested-by: Laszlo Ersek +Signed-off-by: Philippe Mathieu-Daude +(cherry picked from commit aaaedc1e2cfd55ef003fb1b5a37c73a196b26dc7) +Signed-off-by: Laszlo Ersek +(cherry picked from commit aa2b66b18a62d652bdbefae7b5732297294306ca) +(cherry picked from commit deb3451034326b75fd760aba47a5171493ff055e) +--- + OvmfPkg/QemuRamfbDxe/QemuRamfb.c | 14 ++++++++++++++ + OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf | 1 + + 2 files changed, 15 insertions(+) + +diff --git a/OvmfPkg/QemuRamfbDxe/QemuRamfb.c b/OvmfPkg/QemuRamfbDxe/QemuRamfb.c +index 0d49d8bbab..dbf9bcbe16 100644 +--- a/OvmfPkg/QemuRamfbDxe/QemuRamfb.c ++++ b/OvmfPkg/QemuRamfbDxe/QemuRamfb.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -242,6 +243,19 @@ InitializeQemuRamfb ( + + Status = QemuFwCfgFindFile ("etc/ramfb", &mRamfbFwCfgItem, &FwCfgSize); + if (EFI_ERROR (Status)) { ++#if defined (MDE_CPU_AARCH64) ++ // ++ // RHBZ#1714446 ++ // If no ramfb device was configured, this platform DXE driver should ++ // returns EFI_NOT_FOUND, so the DXE Core can unload it. However, even ++ // using a silent build, an error message is issued to the guest console. ++ // Since this confuse users, return success and stay resident. The wasted ++ // guest RAM still gets freed later after ExitBootServices(). ++ // ++ if (GetDebugPrintErrorLevel () == DEBUG_ERROR) { ++ return EFI_SUCCESS; ++ } ++#endif + return EFI_NOT_FOUND; + } + if (FwCfgSize != sizeof (RAMFB_CONFIG)) { +diff --git a/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf b/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf +index e3890b8c20..6ffee5acb2 100644 +--- a/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf ++++ b/OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf +@@ -29,6 +29,7 @@ + BaseLib + BaseMemoryLib + DebugLib ++ DebugPrintErrorLevelLib + DevicePathLib + FrameBufferBltLib + MemoryAllocationLib +-- +2.27.0 + diff --git a/SOURCES/0023-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-NvmExpre.patch b/SOURCES/0023-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-NvmExpre.patch new file mode 100644 index 0000000..fd57bb6 --- /dev/null +++ b/SOURCES/0023-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-NvmExpre.patch @@ -0,0 +1,131 @@ +From a663867a4a99b97d0e1c5fdfed0389312fecd767 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 21 Nov 2017 00:57:47 +0100 +Subject: OvmfPkg: silence EFI_D_VERBOSE (0x00400000) in NvmExpressDxe (RH + only) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- Extend the DSC change to the new OvmfPkg/AmdSev platform, which has been + introduced upstream in commit 30d277ed7a82 ("OvmfPkg/Amdsev: Base commit + to build encrypted boot specific OVMF", 2020-12-14), for TianoCore#3077. + +- Remove obsolete commit message tags related to downstream patch + management: Message-id, Patchwork-id, O-Subject, Acked-by, From + (RHBZ#1846481). + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- no change + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- no change + +Notes about the RHEL-8.0/20180508-ee3198e672e2 -> +RHEL-8.1/20190308-89910a39dcfd rebase: + +- no change + +Notes about the RHEL-7.6/ovmf-20180508-2.gitee3198e672e2.el7 -> +RHEL-8.0/20180508-ee3198e672e2 rebase: + +- reorder the rebase changelog in the commit message so that it reads like + a blog: place more recent entries near the top +- no changes to the patch body + +Notes about the 20171011-92d07e48907f -> 20180508-ee3198e672e2 rebase: + +- no changes + +Bugzilla: 1488247 + +NvmExpressDxe logs all BlockIo read & write calls on the EFI_D_VERBOSE +level. + +Signed-off-by: Laszlo Ersek +Signed-off-by: Paolo Bonzini +(this patch was previously applied as commit 5f432837b9c60c2929b13dda1a1b488d5c3a6d2f) +(cherry picked from commit 33e00146eb878588ad1395d7b1ae38f401729da4) +(cherry picked from commit bd10cabcfcb1bc9a32b05062f4ee3792e27bc2d8) +(cherry picked from commit 5a27af700f49e00608f232f618dedd7bf5e9b3e6) +(cherry picked from commit 58bba429b9ec7b78109940ef945d0dc93f3cd958) +(cherry picked from commit b8d0ebded8c2cf5b266c807519e2d8ccfd66fee6) +(cherry picked from commit ed89844b47f46cfe911f1bf2bda40e537a908502) +--- + OvmfPkg/AmdSev/AmdSevX64.dsc | 5 ++++- + OvmfPkg/OvmfPkgIa32.dsc | 5 ++++- + OvmfPkg/OvmfPkgIa32X64.dsc | 5 ++++- + OvmfPkg/OvmfPkgX64.dsc | 5 ++++- + 4 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc +index a289d8a573..ccdf9b8ce0 100644 +--- a/OvmfPkg/AmdSev/AmdSevX64.dsc ++++ b/OvmfPkg/AmdSev/AmdSevX64.dsc +@@ -744,7 +744,10 @@ + OvmfPkg/SataControllerDxe/SataControllerDxe.inf + MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +- MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf ++ MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc +index 1a5cfa4c6d..a0666930d6 100644 +--- a/OvmfPkg/OvmfPkgIa32.dsc ++++ b/OvmfPkg/OvmfPkgIa32.dsc +@@ -839,7 +839,10 @@ + OvmfPkg/SataControllerDxe/SataControllerDxe.inf + MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +- MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf ++ MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc +index 11002ffd95..5efeb42bf3 100644 +--- a/OvmfPkg/OvmfPkgIa32X64.dsc ++++ b/OvmfPkg/OvmfPkgIa32X64.dsc +@@ -853,7 +853,10 @@ + OvmfPkg/SataControllerDxe/SataControllerDxe.inf + MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +- MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf ++ MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc +index f176aa4061..10fb7d7069 100644 +--- a/OvmfPkg/OvmfPkgX64.dsc ++++ b/OvmfPkg/OvmfPkgX64.dsc +@@ -851,7 +851,10 @@ + OvmfPkg/SataControllerDxe/SataControllerDxe.inf + MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +- MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf ++ MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf { ++ ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F ++ } + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +-- +2.27.0 + diff --git a/SOURCES/0024-CryptoPkg-OpensslLib-list-RHEL8-specific-OpenSSL-fil.patch b/SOURCES/0024-CryptoPkg-OpensslLib-list-RHEL8-specific-OpenSSL-fil.patch new file mode 100644 index 0000000..8546eb5 --- /dev/null +++ b/SOURCES/0024-CryptoPkg-OpensslLib-list-RHEL8-specific-OpenSSL-fil.patch @@ -0,0 +1,179 @@ +From e0b349962f12a500afa449900a81440a96ca21f4 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Sat, 16 Nov 2019 17:11:27 +0100 +Subject: CryptoPkg/OpensslLib: list RHEL8-specific OpenSSL files in the INFs + (RH) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1938257 + +- Recreate the patch based on downstream commits: + + - 56c4bb81b311 ("CryptoPkg/OpensslLib: list RHEL8-specific OpenSSL files + in the INFs (RH)", 2020-06-05), + - e81751a1c303 ("CryptoPkg/OpensslLib: Upgrade OpenSSL to 1.1.1g", + 2020-11-23), + - 3e3fe5e62079 ("redhat: bump OpenSSL dist-git submodule to 1.1.1g+ / + RHEL-8.4", 2020-11-23). + + (1) At e81751a1c303, downstream edk2 was in sync with upstream edk2 + consuming OpenSSL 1.1.1g (upstream edk2 commit 8c30327debb2 + ("CryptoPkg/OpensslLib: Upgrade OpenSSL to 1.1.1g", 2020-07-25)). + + Since commit 8c30327debb2, upstream edk2 modified the OpensslLib INF + files, namely + + - CryptoPkg/Library/OpensslLib/OpensslLib.inf + - CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf + + in the following commits only: + + - be01087e0780 ("CryptoPkg/Library: Remove the redundant build + option", 2020-08-12), which did not affect the source file list at + all, + + - b5701a4c7a0f ("CryptoPkg: OpensslLib: Use RngLib to generate + entropy in rand_pool", 2020-09-18), which replaced some of the + *edk2-specific* "rand_pool_noise" source files with an RngLib + dependency. + + This means that the list of required, actual OpenSSL source files + has not changed in upstream edk2 since our downstream edk2 commit + e81751a1c303. + + (2) At commit 3e3fe5e62079 (the direct child of e81751a1c303), + downstream edk2's OpenSSL dependency was satisfied with RHEL-8 + OpenSSL at dist-git commit bdd048e929dc ("Two fixes that will be + shipped in RHEL-8.3.0.z", 2020-10-23). + + Since commit bdd048e929dc, RHEL-8 OpenSSL dist-git advanced + (fast-forwarded) to commit a75722161d20 ("Update to version 1.1.1k", + 2021-05-25), which is the current head of the rhel-8.5.0 branch. + (See also .) + + At both dist-git bdd048e929dc and dist-git a75722161d20, I built the + respective RHEL-8 OpenSSL *source* RPM, and prepped the respective + source tree, with "rpmbuild -bp". Subsequently I compared the + prepped source trees recursively. + + - The following files disappeared: + + - 29 backup files created by "patch", + + - the assembly generator perl script called + "ecp_nistz256-avx2.pl", which is not used during the build. + + - The following new files appeared: + + - 18 files directly or indirectly under the "test" subdirectory, + which are not used during the build, + + - 5 backup files created by "patch", + + - 2 DCL scripts used when building OpenSSL on OpenVMS. + + This means that the total list of RHEL-8 OpenSSL source files has + not changed in RHEL-8 OpenSSL dist-git since our downstream edk2 + commit 3e3fe5e62079. + + As a result, copy the "RHEL8-specific OpenSSL file list" sections + verbatim from the INF files, at downstream commit e81751a1c303. (I used + the "git checkout -p e81751a1c303 -- Library/OpensslLib/OpensslLib.inf + CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf" command.) + +Notes about the RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] -> +RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] rebase: + +- "OpensslLib.inf": + + - Automatic leading context refresh against upstream commit c72ca4666886 + ("CryptoPkg/OpensslLib: Add "sort" keyword to header file parsing + loop", 2020-03-10). + + - Manual trailing context refresh against upstream commit b49a6c8f80d9 + ("CryptoPkg/OpensslLib: improve INF file consistency", 2019-12-02). + +- "OpensslLibCrypto.inf": + + - Automatic leading context refresh against upstream commits + 8906f076de35 ("CryptoPkg/OpensslLib: Add missing header files in INF + file", 2019-08-16) and 9f4fbd56d430 ("CryptoPkg/OpensslLib: Update + process_files.pl to generate .h files", 2019-10-30). + +Notes about the RHEL-8.1/20190308-89910a39dcfd [edk2-stable201903] -> +RHEL-8.2/20190904-37eef91017ad [edk2-stable201908] rebase: + +- new patch + +The downstream changes in RHEL8's OpenSSL package, for example in +"openssl-1.1.1-evp-kdf.patch", introduce new files, and even move some +preexistent code into those new files. In order to avoid undefined +references in link editing, we have to list the new files. + +Note: "process_files.pl" is not re-run at this time manually, because + +(a) "process_files.pl" would pollute the file list (and some of the + auto-generated header files) with RHEL8-specific FIPS artifacts, which + are explicitly unwanted in edk2, + +(b) The RHEL OpenSSL maintainer, Tomas Mraz, identified this specific set + of files in , + and will help with future changes too. + +Signed-off-by: Laszlo Ersek +(cherry picked from commit 57bd3f146590df8757865d8f2cdd1db3cf3f4d40) +(cherry picked from commit 56c4bb81b311dfcee6a34c81d3e4feeda7f88995) +--- + CryptoPkg/Library/OpensslLib/OpensslLib.inf | 11 +++++++++++ + CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf | 11 +++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/CryptoPkg/Library/OpensslLib/OpensslLib.inf b/CryptoPkg/Library/OpensslLib/OpensslLib.inf +index d84bde056a..19913a4ac6 100644 +--- a/CryptoPkg/Library/OpensslLib/OpensslLib.inf ++++ b/CryptoPkg/Library/OpensslLib/OpensslLib.inf +@@ -570,6 +570,17 @@ + $(OPENSSL_PATH)/ssl/statem/statem.h + $(OPENSSL_PATH)/ssl/statem/statem_local.h + # Autogenerated files list ends here ++# RHEL8-specific OpenSSL file list starts here ++ $(OPENSSL_PATH)/crypto/evp/kdf_lib.c ++ $(OPENSSL_PATH)/crypto/evp/pkey_kdf.c ++ $(OPENSSL_PATH)/crypto/kdf/kbkdf.c ++ $(OPENSSL_PATH)/crypto/kdf/kdf_local.h ++ $(OPENSSL_PATH)/crypto/kdf/kdf_util.c ++ $(OPENSSL_PATH)/crypto/kdf/krb5kdf.c ++ $(OPENSSL_PATH)/crypto/kdf/pbkdf2.c ++ $(OPENSSL_PATH)/crypto/kdf/sshkdf.c ++ $(OPENSSL_PATH)/crypto/kdf/sskdf.c ++# RHEL8-specific OpenSSL file list ends here + buildinf.h + ossl_store.c + rand_pool.c +diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf +index cdeed0d073..5057857e8d 100644 +--- a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf ++++ b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf +@@ -519,6 +519,17 @@ + $(OPENSSL_PATH)/crypto/x509v3/standard_exts.h + $(OPENSSL_PATH)/crypto/x509v3/v3_admis.h + # Autogenerated files list ends here ++# RHEL8-specific OpenSSL file list starts here ++ $(OPENSSL_PATH)/crypto/evp/kdf_lib.c ++ $(OPENSSL_PATH)/crypto/evp/pkey_kdf.c ++ $(OPENSSL_PATH)/crypto/kdf/kbkdf.c ++ $(OPENSSL_PATH)/crypto/kdf/kdf_local.h ++ $(OPENSSL_PATH)/crypto/kdf/kdf_util.c ++ $(OPENSSL_PATH)/crypto/kdf/krb5kdf.c ++ $(OPENSSL_PATH)/crypto/kdf/pbkdf2.c ++ $(OPENSSL_PATH)/crypto/kdf/sshkdf.c ++ $(OPENSSL_PATH)/crypto/kdf/sskdf.c ++# RHEL8-specific OpenSSL file list ends here + buildinf.h + ossl_store.c + rand_pool.c +-- +2.27.0 + diff --git a/SOURCES/0025-OvmfPkg-QemuKernelLoaderFsDxe-suppress-error-on-no-k.patch b/SOURCES/0025-OvmfPkg-QemuKernelLoaderFsDxe-suppress-error-on-no-k.patch new file mode 100644 index 0000000..1ee9e11 --- /dev/null +++ b/SOURCES/0025-OvmfPkg-QemuKernelLoaderFsDxe-suppress-error-on-no-k.patch @@ -0,0 +1,83 @@ +From d9416e3015cadb3214d5ca409e57fd2352ae1961 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 24 Jun 2020 11:31:36 +0200 +Subject: OvmfPkg/QemuKernelLoaderFsDxe: suppress error on no "-kernel" in + silent aa64 build (RH) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- Remove obsolete commit message tags related to downstream patch + management: Message-id, Patchwork-id, O-Subject, Acked-by, From, + RH-Acked-by, RH-Author (RHBZ#1846481). + +Bugzilla: 1844682 + +If the "-kernel" QEMU option is not used, then QemuKernelLoaderFsDxe +should return EFI_NOT_FOUND, so that the DXE Core can unload it. However, +the associated error message, logged by the DXE Core to the serial +console, is not desired in the silent edk2-aarch64 build, given that the +absence of "-kernel" is nothing out of the ordinary. Therefore, return +success and stay resident. The wasted guest RAM still gets freed after +ExitBootServices(). + +(Inspired by RHEL-8.1.0 commit aaaedc1e2cfd.) + +Signed-off-by: Laszlo Ersek +Signed-off-by: Miroslav Rezanina +(cherry picked from commit 9adcdf493ebbd11efb74e2905ab5f6c8996e096d) +--- + .../QemuKernelLoaderFsDxe.c | 17 +++++++++++++++++ + .../QemuKernelLoaderFsDxe.inf | 1 + + 2 files changed, 18 insertions(+) + +diff --git a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c +index 6832d563bc..08ed67f5ff 100644 +--- a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c ++++ b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1054,6 +1055,22 @@ QemuKernelLoaderFsDxeEntrypoint ( + + if (KernelBlob->Data == NULL) { + Status = EFI_NOT_FOUND; ++#if defined (MDE_CPU_AARCH64) ++ // ++ // RHBZ#1844682 ++ // ++ // If the "-kernel" QEMU option is not being used, this platform DXE driver ++ // should return EFI_NOT_FOUND, so that the DXE Core can unload it. ++ // However, the associated error message, logged by the DXE Core to the ++ // serial console, is not desired in the silent edk2-aarch64 build, given ++ // that the absence of "-kernel" is nothing out of the ordinary. Therefore, ++ // return success and stay resident. The wasted guest RAM still gets freed ++ // after ExitBootServices(). ++ // ++ if (GetDebugPrintErrorLevel () == DEBUG_ERROR) { ++ Status = EFI_SUCCESS; ++ } ++#endif + goto FreeBlobs; + } + +diff --git a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf +index 7b35adb8e0..e0331c6e2c 100644 +--- a/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf ++++ b/OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf +@@ -28,6 +28,7 @@ + BaseLib + BaseMemoryLib + DebugLib ++ DebugPrintErrorLevelLib + DevicePathLib + MemoryAllocationLib + QemuFwCfgLib +-- +2.27.0 + diff --git a/SOURCES/0026-SecurityPkg-Tcg2Dxe-suppress-error-on-no-swtpm-in-si.patch b/SOURCES/0026-SecurityPkg-Tcg2Dxe-suppress-error-on-no-swtpm-in-si.patch new file mode 100644 index 0000000..1db7c47 --- /dev/null +++ b/SOURCES/0026-SecurityPkg-Tcg2Dxe-suppress-error-on-no-swtpm-in-si.patch @@ -0,0 +1,82 @@ +From fd19e4e33d52e843e6e35adde2c1e266497e8a7b Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 24 Jun 2020 11:40:09 +0200 +Subject: SecurityPkg/Tcg2Dxe: suppress error on no swtpm in silent aa64 build + (RH) + +Notes about the RHEL-8.3/20200603-ca407c7246bf [edk2-stable202005] -> +RHEL-8.5/20210520-e1999b264f1f [edk2-stable202105] rebase: + +- Remove obsolete commit message tags related to downstream patch + management: Message-id, Patchwork-id, O-Subject, Acked-by, From, + RH-Acked-by, RH-Author (RHBZ#1846481). + +Bugzilla: 1844682 + +If swtpm / vTPM2 is not being used, Tcg2Dxe should return EFI_UNSUPPORTED, +so that the DXE Core can unload it. However, the associated error message, +logged by the DXE Core to the serial console, is not desired in the silent +edk2-aarch64 build, given that the absence of swtpm / vTPM2 is nothing out +of the ordinary. Therefore, return success and stay resident. The wasted +guest RAM still gets freed after ExitBootServices(). + +(Inspired by RHEL-8.1.0 commit aaaedc1e2cfd.) + +Signed-off-by: Laszlo Ersek +Signed-off-by: Miroslav Rezanina +(cherry picked from commit cbce29f7749477e271f9764fed82de94724af5df) +--- + SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c | 17 +++++++++++++++++ + SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf | 1 + + 2 files changed, 18 insertions(+) + +diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c +index 6d17616c1c..f1a97d4b2d 100644 +--- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c ++++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c +@@ -28,6 +28,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + #include + + #include ++#include + #include + #include + #include +@@ -2642,6 +2643,22 @@ DriverEntry ( + if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) || + CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){ + DEBUG ((DEBUG_INFO, "No TPM2 instance required!\n")); ++#if defined (MDE_CPU_AARCH64) ++ // ++ // RHBZ#1844682 ++ // ++ // If swtpm / vTPM2 is not being used, this driver should return ++ // EFI_UNSUPPORTED, so that the DXE Core can unload it. However, the ++ // associated error message, logged by the DXE Core to the serial console, ++ // is not desired in the silent edk2-aarch64 build, given that the absence ++ // of swtpm / vTPM2 is nothing out of the ordinary. Therefore, return ++ // success and stay resident. The wasted guest RAM still gets freed after ++ // ExitBootServices(). ++ // ++ if (GetDebugPrintErrorLevel () == DEBUG_ERROR) { ++ return EFI_SUCCESS; ++ } ++#endif + return EFI_UNSUPPORTED; + } + +diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf +index 7dc7a2683d..3bc8833931 100644 +--- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf ++++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf +@@ -55,6 +55,7 @@ + UefiRuntimeServicesTableLib + BaseMemoryLib + DebugLib ++ DebugPrintErrorLevelLib + Tpm2CommandLib + PrintLib + UefiLib +-- +2.27.0 + diff --git a/SOURCES/LICENSE.qosb b/SOURCES/LICENSE.qosb new file mode 100644 index 0000000..9849381 --- /dev/null +++ b/SOURCES/LICENSE.qosb @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Patrick Uiterwijk + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/SOURCES/RedHatSecureBootPkKek1.pem b/SOURCES/RedHatSecureBootPkKek1.pem new file mode 100644 index 0000000..d302362 --- /dev/null +++ b/SOURCES/RedHatSecureBootPkKek1.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDoDCCAoigAwIBAgIJAP71iOjzlsDxMA0GCSqGSIb3DQEBCwUAMFExKzApBgNV +BAMTIlJlZCBIYXQgU2VjdXJlIEJvb3QgKFBLL0tFSyBrZXkgMSkxIjAgBgkqhkiG +9w0BCQEWE3NlY2FsZXJ0QHJlZGhhdC5jb20wHhcNMTQxMDMxMTExNTM3WhcNMzcx +MDI1MTExNTM3WjBRMSswKQYDVQQDEyJSZWQgSGF0IFNlY3VyZSBCb290IChQSy9L +RUsga2V5IDEpMSIwIAYJKoZIhvcNAQkBFhNzZWNhbGVydEByZWRoYXQuY29tMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkB+Ee42865cmgm2Iq4rJjGhw ++d9LB7I3gwsCyGdoMJ7j8PCZSrhZV8ZB9jiL/mZMSek3N5IumAEeWxRQ5qiNJQ31 +huarMMtAFuqNixaGcEM38s7Akd9xFI6ZDom2TG0kHozkL08l0LoG+MboGRh2cx2B +bajYBc86yHsoyDajFg0pjJmaaNyrwE2Nv1q7K6k5SwSXHPk2u8U6hgSur9SCe+Cr +3kkFaPz2rmgabJBNVxk8ZGYD9sdSm/eUz5NqoWjJqs+Za7yqXgjnORz3+A+6Bn7x +y+h23f4i2q06Xls06rPJ4E0EKX64YLkF77XZF1hWFmC5MDLwNkrD8nmNEkBw8wID +AQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVy +YXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUPOlg4/8ZoQp7o0L0jUIutNWccuww +HwYDVR0jBBgwFoAUPOlg4/8ZoQp7o0L0jUIutNWccuwwDQYJKoZIhvcNAQELBQAD +ggEBAFxNkoi0gl8drYsR7N8GpnqlK583VQyNbgUArbcMQYlpz9ZlBptReNKtx7+c +3AVzf+ceORO06rYwfUB1q5xDC9+wwhu/MOD0/sDbYiGY9sWv3jtPSQrmHvmGsD8N +1tRGN9tUdF7/EcJgxnBYxRxv7LLYbm/DvDOHOKTzRGScNDsolCZ4J58WF+g7aQol +qXM2fp43XOzoP9uR+RKzPc7n3RXDrowFIGGbld6br/qxXBzll+fDNBGF9YonJqRw +NuwM9oM9kPc28/nzFdSQYr5TtK/TSa/v9HPoe3bkRCo3uoGkmQw6MSRxoOTktxrL +R+SqIs/vdWGA40O3SFdzET14m2k= +-----END CERTIFICATE----- diff --git a/SOURCES/edk2-Apply-uncrustify-changes-to-.c-.h-files-in-the-Netwo.patch b/SOURCES/edk2-Apply-uncrustify-changes-to-.c-.h-files-in-the-Netwo.patch new file mode 100644 index 0000000..0ef1750 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-ArmVirtPkg-ArmVirtQemu-migrate-to-OVMF-s-VirtNorFlas.patch b/SOURCES/edk2-ArmVirtPkg-ArmVirtQemu-migrate-to-OVMF-s-VirtNorFlas.patch new file mode 100644 index 0000000..43848d5 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-MdePkg-Introduce-CcMeasurementProtocol-for-CC-Guest-.patch b/SOURCES/edk2-MdePkg-Introduce-CcMeasurementProtocol-for-CC-Guest-.patch new file mode 100644 index 0000000..df008db --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch b/SOURCES/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch new file mode 100644 index 0000000..b984c70 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch b/SOURCES/edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch new file mode 100644 index 0000000..2c0ae8b --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Apply-uncrustify-changes-p2.patch b/SOURCES/edk2-NetworkPkg-Apply-uncrustify-changes-p2.patch new file mode 100644 index 0000000..d51d127 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Apply-uncrustify-changes.patch b/SOURCES/edk2-NetworkPkg-Apply-uncrustify-changes.patch new file mode 100644 index 0000000..2bf3ddf --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch b/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch new file mode 100644 index 0000000..e37b524 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch b/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch new file mode 100644 index 0000000..a928fa2 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch b/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch new file mode 100644 index 0000000..dcf5bb7 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch b/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch new file mode 100644 index 0000000..ea1b84f --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch b/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch new file mode 100644 index 0000000..f4ee0d4 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch b/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch new file mode 100644 index 0000000..e7e40c1 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch b/SOURCES/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch new file mode 100644 index 0000000..b87ded2 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch b/SOURCES/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch new file mode 100644 index 0000000..35eaa36 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch b/SOURCES/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch new file mode 100644 index 0000000..a7b6eb8 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch b/SOURCES/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch new file mode 100644 index 0000000..1add20a --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch b/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch new file mode 100644 index 0000000..8e6f603 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch b/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch new file mode 100644 index 0000000..aac0738 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch b/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch new file mode 100644 index 0000000..beaa36f --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch b/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch new file mode 100644 index 0000000..8380050 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-AmdSev-SecretPei-Mark-SEV-launch-secret-area.patch b/SOURCES/edk2-OvmfPkg-AmdSev-SecretPei-Mark-SEV-launch-secret-area.patch new file mode 100644 index 0000000..94d6eb6 --- /dev/null +++ b/SOURCES/edk2-OvmfPkg-AmdSev-SecretPei-Mark-SEV-launch-secret-area.patch @@ -0,0 +1,50 @@ +From e4a64ad230ff2906ec56d41b2a8dd7a0bb39a399 Mon Sep 17 00:00:00 2001 +From: Dov Murik +Date: Tue, 4 Jan 2022 15:16:40 +0800 +Subject: [PATCH] OvmfPkg/AmdSev/SecretPei: Mark SEV launch secret area as + reserved + +RH-Author: Pawel Polawski +RH-MergeRequest: 11: OvmfPkg/AmdSev/SecretPei: Mark SEV launch secret area as reserved +RH-Commit: [1/1] a14d34eb204387aae3446770a0e5fb95a9283ae3 (elkoniu/edk2) +RH-Bugzilla: 2041754 +RH-Acked-by: Oliver Steffen + +Mark the SEV launch secret MEMFD area as reserved, which will allow the +guest OS to use it during the lifetime of the OS, without creating +copies of the sensitive content. + +Cc: Ard Biesheuvel +Cc: Jordan Justen +Cc: Gerd Hoffmann +Cc: Brijesh Singh +Cc: Erdem Aktas +Cc: James Bottomley +Cc: Jiewen Yao +Cc: Min Xu +Cc: Tom Lendacky +Cc: Tobin Feldman-Fitzthum +Signed-off-by: Dov Murik +Acked-by: Gerd Hoffmann +Acked-by: Jiewen Yao +Reviewed-by: Brijesh Singh +--- + OvmfPkg/AmdSev/SecretPei/SecretPei.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/OvmfPkg/AmdSev/SecretPei/SecretPei.c b/OvmfPkg/AmdSev/SecretPei/SecretPei.c +index db94c26b54..6bf1a55dea 100644 +--- a/OvmfPkg/AmdSev/SecretPei/SecretPei.c ++++ b/OvmfPkg/AmdSev/SecretPei/SecretPei.c +@@ -19,7 +19,7 @@ InitializeSecretPei ( + BuildMemoryAllocationHob ( + PcdGet32 (PcdSevLaunchSecretBase), + ALIGN_VALUE (PcdGet32 (PcdSevLaunchSecretSize), EFI_PAGE_SIZE), +- EfiBootServicesData ++ EfiReservedMemoryType + ); + + return EFI_SUCCESS; +-- +2.27.0 + diff --git a/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-ValidateFvHeader-unwritten-s.patch new file mode 100644 index 0000000..adf5b38 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-add-a-loop-for-NorFlashWrite.patch new file mode 100644 index 0000000..4fc7c3e --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-add-casts-to-UINTN-and-UINT3.patch new file mode 100644 index 0000000..2494899 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-allow-larger-writes-without-.patch new file mode 100644 index 0000000..f30a257 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-avoid-array-mode-switch-afte.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-avoid-array-mode-switch-afte.patch new file mode 100644 index 0000000..fc64a93 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-avoid-switching-between-mode.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-avoid-switching-between-mode.patch new file mode 100644 index 0000000..783b96f --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-clarify-block-write-logic-fi.patch new file mode 100644 index 0000000..0ac5c14 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-clone-ArmPlatformPkg-s-NOR-f.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-clone-ArmPlatformPkg-s-NOR-f.patch new file mode 100644 index 0000000..41975ab --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-drop-block-I-O-protocol-impl.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-drop-block-I-O-protocol-impl.patch new file mode 100644 index 0000000..e8c0128 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-map-flash-memory-as-uncachea.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-map-flash-memory-as-uncachea.patch new file mode 100644 index 0000000..8eff08e --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-move-DoErase-code-block-into.patch new file mode 100644 index 0000000..da9eafb --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-remove-CheckBlockLocked-feat.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-remove-CheckBlockLocked-feat.patch new file mode 100644 index 0000000..2fdee8e --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-remove-disk-I-O-protocol-imp.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-remove-disk-I-O-protocol-imp.patch new file mode 100644 index 0000000..9319925 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variable2.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variable2.patch new file mode 100644 index 0000000..106b9db --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variables.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-sanity-check-variables.patch new file mode 100644 index 0000000..f94ca10 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariable2.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariable2.patch new file mode 100644 index 0000000..a735619 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariableG.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-stop-accepting-gEfiVariableG.patch new file mode 100644 index 0000000..a3b6933 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-use-EFI_MEMORY_WC-and-drop-A.patch b/SOURCES/edk2-OvmfPkg-VirtNorFlashDxe-use-EFI_MEMORY_WC-and-drop-A.patch new file mode 100644 index 0000000..a61f223 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-OvmfPkg-clone-NorFlashPlatformLib-into-VirtNorFlashP.patch b/SOURCES/edk2-OvmfPkg-clone-NorFlashPlatformLib-into-VirtNorFlashP.patch new file mode 100644 index 0000000..178b1e7 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-Adding-CVE-2022-36763-to-SecurityFixes.y.patch b/SOURCES/edk2-SecurityPkg-Adding-CVE-2022-36763-to-SecurityFixes.y.patch new file mode 100644 index 0000000..f2f31b7 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-Change-OPTIONAL-keyword-usage-style.patch b/SOURCES/edk2-SecurityPkg-Change-OPTIONAL-keyword-usage-style.patch new file mode 100644 index 0000000..bc3723f --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-Change-use-of-EFI_D_-to-DEBUG_.patch b/SOURCES/edk2-SecurityPkg-Change-use-of-EFI_D_-to-DEBUG_.patch new file mode 100644 index 0000000..1d2659d --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-DxeImageVerificationLib-Check-result-of-.patch b/SOURCES/edk2-SecurityPkg-DxeImageVerificationLib-Check-result-of-.patch new file mode 100644 index 0000000..e2d7ed3 --- /dev/null +++ b/SOURCES/edk2-SecurityPkg-DxeImageVerificationLib-Check-result-of-.patch @@ -0,0 +1,109 @@ +From bb0f29580825e60a5dc5c67e260dd20258eb71b0 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 29 Mar 2023 11:52:52 -0400 +Subject: [PATCH] SecurityPkg/DxeImageVerificationLib: Check result of + GetEfiGlobalVariable2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +RH-MergeRequest: 22: SecurityPkg/DxeImageVerificationLib: Check result of GetEfiGlobalVariable2 +RH-Bugzilla: 1861743 +RH-Acked-by: Gerd Hoffmann +RH-Commit: [1/1] 70e1ae5e2c7c148fc23160acdd360c044df5f4ff + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1861743 +Upstream: Merged +CVE: CVE-2019-14560 + +commit 494127613b36e870250649b02cd4ce5f1969d9bd +Author: Gerd Hoffmann +Date: Fri Mar 3 18:35:53 2023 +0800 + + SecurityPkg/DxeImageVerificationLib: Check result of GetEfiGlobalVariable2 + + Call gRT->GetVariable() directly to read the SecureBoot variable. It is + one byte in size so we can easily place it on the stack instead of + having GetEfiGlobalVariable2() allocate it for us, which avoids a few + possible error cases. + + Skip secure boot checks if (and only if): + + (a) the SecureBoot variable is not present (EFI_NOT_FOUND) according to + the return value, or + (b) the SecureBoot variable was read successfully and is set to + SECURE_BOOT_MODE_DISABLE. + + Previously the code skipped the secure boot checks on *any* + gRT->GetVariable() error (GetEfiGlobalVariable2 sets the variable + value to NULL in that case) and also on memory allocation failures. + + Fixes: CVE-2019-14560 + Signed-off-by: Gerd Hoffmann + Suggested-by: Marvin Häuser + Reviewed-by: Min Xu + Reviewed-by: Jiewen Yao + +Signed-off-by: Jon Maloy +--- + .../DxeImageVerificationLib.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +index c48861cd64..1252927664 100644 +--- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c ++++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +@@ -1650,7 +1650,8 @@ DxeImageVerificationHandler ( + EFI_IMAGE_EXECUTION_ACTION Action; + WIN_CERTIFICATE *WinCertificate; + UINT32 Policy; +- UINT8 *SecureBoot; ++ UINT8 SecureBoot; ++ UINTN SecureBootSize; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + UINT32 NumberOfRvaAndSizes; + WIN_CERTIFICATE_EFI_PKCS *PkcsCertData; +@@ -1665,6 +1666,8 @@ DxeImageVerificationHandler ( + RETURN_STATUS PeCoffStatus; + EFI_STATUS HashStatus; + EFI_STATUS DbStatus; ++ EFI_STATUS VarStatus; ++ UINT32 VarAttr; + BOOLEAN IsFound; + + SignatureList = NULL; +@@ -1720,22 +1723,25 @@ DxeImageVerificationHandler ( + CpuDeadLoop (); + } + +- GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL); ++ SecureBootSize = sizeof (SecureBoot); ++ VarStatus = gRT->GetVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, &VarAttr, &SecureBootSize, &SecureBoot); + // + // Skip verification if SecureBoot variable doesn't exist. + // +- if (SecureBoot == NULL) { ++ if (VarStatus == EFI_NOT_FOUND) { + return EFI_SUCCESS; + } + + // + // Skip verification if SecureBoot is disabled but not AuditMode + // +- if (*SecureBoot == SECURE_BOOT_MODE_DISABLE) { +- FreePool (SecureBoot); ++ if ((VarStatus == EFI_SUCCESS) && ++ (VarAttr == (EFI_VARIABLE_BOOTSERVICE_ACCESS | ++ EFI_VARIABLE_RUNTIME_ACCESS)) && ++ (SecureBoot == SECURE_BOOT_MODE_DISABLE)) ++ { + return EFI_SUCCESS; + } +- FreePool (SecureBoot); + + // + // Read the Dos header. +-- +2.39.1 + diff --git a/SOURCES/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SEC-PATCH-4118-2.patch b/SOURCES/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SEC-PATCH-4118-2.patch new file mode 100644 index 0000000..464b257 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch b/SOURCES/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-411.patch new file mode 100644 index 0000000..372ad1f --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-418.patch b/SOURCES/edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-418.patch new file mode 100644 index 0000000..f01c9a1 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-DxeTpmMeasureBootLib-SEC-PATCH-4117-2.patch b/SOURCES/edk2-SecurityPkg-DxeTpmMeasureBootLib-SEC-PATCH-4117-2.patch new file mode 100644 index 0000000..b9629c0 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4117.patch b/SOURCES/edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4117.patch new file mode 100644 index 0000000..499abda --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4118.patch b/SOURCES/edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4118.patch new file mode 100644 index 0000000..8586c39 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpm2.patch b/SOURCES/edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpm2.patch new file mode 100644 index 0000000..2ee9f81 --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpmM.patch b/SOURCES/edk2-SecurityPkg-Support-CcMeasurementProtocol-in-DxeTpmM.patch new file mode 100644 index 0000000..9764d7f --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-SecurityPkg-Updating-SecurityFixes.yaml-after-symbol.patch b/SOURCES/edk2-SecurityPkg-Updating-SecurityFixes.yaml-after-symbol.patch new file mode 100644 index 0000000..ce0441b --- /dev/null +++ b/SOURCES/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/SOURCES/edk2-UefiCpuPkg-MpInitLib-fix-apic-mode-for-cpu-hotplug.patch b/SOURCES/edk2-UefiCpuPkg-MpInitLib-fix-apic-mode-for-cpu-hotplug.patch new file mode 100644 index 0000000..2739061 --- /dev/null +++ b/SOURCES/edk2-UefiCpuPkg-MpInitLib-fix-apic-mode-for-cpu-hotplug.patch @@ -0,0 +1,49 @@ +From c32f4994552ea5835cf00ce06f2f7d88c71249e5 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 28 Feb 2023 15:47:00 +0100 +Subject: [PATCH] UefiCpuPkg/MpInitLib: fix apic mode for cpu hotplug + +RH-Author: Miroslav Rezanina +RH-MergeRequest: 29: UefiCpuPkg/MpInitLib: fix apic mode for cpu hotplug +RH-Bugzilla: 2150267 +RH-Acked-by: Oliver Steffen +RH-Acked-by: Jon Maloy +RH-Commit: [1/1] e7e332ac0e6edf207b1b9692f2e1aed4a1fe7c0c + +In case the number of CPUs can in increase beyond 255 +due to CPU hotplug choose x2apic mode. + +Signed-off-by: Gerd Hoffmann +--- + UefiCpuPkg/Library/MpInitLib/MpLib.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c +index b9a06747ed..177d15ab5b 100644 +--- a/UefiCpuPkg/Library/MpInitLib/MpLib.c ++++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c +@@ -495,7 +495,9 @@ CollectProcessorCount ( + // + // Enable x2APIC mode if + // 1. Number of CPU is greater than 255; or +- // 2. There are any logical processors reporting an Initial APIC ID of 255 or greater. ++ // 2. The platform exposed the exact *boot* CPU count to us in advance, and ++ // more than 255 logical processors are possible later, with hotplug; or ++ // 3. There are any logical processors reporting an Initial APIC ID of 255 or greater. + // + X2Apic = FALSE; + if (CpuMpData->CpuCount > 255) { +@@ -503,6 +505,10 @@ CollectProcessorCount ( + // If there are more than 255 processor found, force to enable X2APIC + // + X2Apic = TRUE; ++ } else if ((PcdGet32 (PcdCpuBootLogicalProcessorNumber) > 0) && ++ (PcdGet32 (PcdCpuMaxLogicalProcessorNumber) > 255)) ++ { ++ X2Apic = TRUE; + } else { + CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; + for (Index = 0; Index < CpuMpData->CpuCount; Index++) { +-- +2.37.3 + diff --git a/SOURCES/edk2-aarch64-verbose.json b/SOURCES/edk2-aarch64-verbose.json new file mode 100644 index 0000000..ceec878 --- /dev/null +++ b/SOURCES/edk2-aarch64-verbose.json @@ -0,0 +1,31 @@ +{ + "description": "UEFI firmware for ARM64 virtual machines, verbose logs", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "executable": { + "filename": "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/edk2/aarch64/vars-template-pflash.raw", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "aarch64", + "machines": [ + "virt-*" + ] + } + ], + "features": [ + "verbose-static" + ], + "tags": [ + + ] +} diff --git a/SOURCES/edk2-aarch64.json b/SOURCES/edk2-aarch64.json new file mode 100644 index 0000000..c5a73cb --- /dev/null +++ b/SOURCES/edk2-aarch64.json @@ -0,0 +1,31 @@ +{ + "description": "UEFI firmware for ARM64 virtual machines", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "executable": { + "filename": "/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.raw", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/edk2/aarch64/vars-template-pflash.raw", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "aarch64", + "machines": [ + "virt-*" + ] + } + ], + "features": [ + + ], + "tags": [ + + ] +} diff --git a/SOURCES/edk2-ovmf-cc.json b/SOURCES/edk2-ovmf-cc.json new file mode 100644 index 0000000..64c38d0 --- /dev/null +++ b/SOURCES/edk2-ovmf-cc.json @@ -0,0 +1,34 @@ +{ + "description": "OVMF with SEV-ES support", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "executable": { + "filename": "/usr/share/edk2/ovmf/OVMF_CODE.cc.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/edk2/ovmf/OVMF_VARS.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-q35-rhel8.6.0", + "pc-q35-rhel8.5.0" + ] + } + ], + "features": [ + "amd-sev", + "amd-sev-es", + "verbose-dynamic" + ], + "tags": [ + + ] +} diff --git a/SOURCES/edk2-ovmf-sb.json b/SOURCES/edk2-ovmf-sb.json new file mode 100644 index 0000000..a0203e8 --- /dev/null +++ b/SOURCES/edk2-ovmf-sb.json @@ -0,0 +1,36 @@ +{ + "description": "OVMF with SB+SMM, SB enabled, MS certs enrolled", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "executable": { + "filename": "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "amd-sev", + "enrolled-keys", + "requires-smm", + "secure-boot", + "verbose-dynamic" + ], + "tags": [ + + ] +} diff --git a/SOURCES/edk2-ovmf.json b/SOURCES/edk2-ovmf.json new file mode 100644 index 0000000..74d00e3 --- /dev/null +++ b/SOURCES/edk2-ovmf.json @@ -0,0 +1,35 @@ +{ + "description": "OVMF with SB+SMM, empty varstore", + "interface-types": [ + "uefi" + ], + "mapping": { + "device": "flash", + "executable": { + "filename": "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd", + "format": "raw" + }, + "nvram-template": { + "filename": "/usr/share/edk2/ovmf/OVMF_VARS.fd", + "format": "raw" + } + }, + "targets": [ + { + "architecture": "x86_64", + "machines": [ + "pc-q35-*" + ] + } + ], + "features": [ + "acpi-s3", + "amd-sev", + "requires-smm", + "secure-boot", + "verbose-dynamic" + ], + "tags": [ + + ] +} diff --git a/SOURCES/edk2-rh-openssl-add-crypto-bn-rsa_sup_mul.c-to-file-list.patch b/SOURCES/edk2-rh-openssl-add-crypto-bn-rsa_sup_mul.c-to-file-list.patch new file mode 100644 index 0000000..f0ee17f --- /dev/null +++ b/SOURCES/edk2-rh-openssl-add-crypto-bn-rsa_sup_mul.c-to-file-list.patch @@ -0,0 +1,42 @@ +From ec7ff1612b2f5b0075545dc705b7c2610ec83748 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Fri, 10 Feb 2023 11:43:06 +0100 +Subject: [PATCH 2/2] rh openssl: add crypto/bn/rsa_sup_mul.c to file list + +RH-Author: Gerd Hoffmann +RH-MergeRequest: 21: openssl update +RH-Bugzilla: 2164531 2164543 2164558 2164581 +RH-Acked-by: Miroslav Rezanina +RH-Commit: [2/2] 61acf48e337f04b34c4f309241775b204ae2e54f (kraxel/rhel-edk-2) +--- + CryptoPkg/Library/OpensslLib/OpensslLib.inf | 1 + + CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/CryptoPkg/Library/OpensslLib/OpensslLib.inf b/CryptoPkg/Library/OpensslLib/OpensslLib.inf +index 19913a4ac6..4eaa8a756d 100644 +--- a/CryptoPkg/Library/OpensslLib/OpensslLib.inf ++++ b/CryptoPkg/Library/OpensslLib/OpensslLib.inf +@@ -571,6 +571,7 @@ + $(OPENSSL_PATH)/ssl/statem/statem_local.h + # Autogenerated files list ends here + # RHEL8-specific OpenSSL file list starts here ++ $(OPENSSL_PATH)/crypto/bn/rsa_sup_mul.c + $(OPENSSL_PATH)/crypto/evp/kdf_lib.c + $(OPENSSL_PATH)/crypto/evp/pkey_kdf.c + $(OPENSSL_PATH)/crypto/kdf/kbkdf.c +diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf +index 5057857e8d..eec4771f2c 100644 +--- a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf ++++ b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf +@@ -520,6 +520,7 @@ + $(OPENSSL_PATH)/crypto/x509v3/v3_admis.h + # Autogenerated files list ends here + # RHEL8-specific OpenSSL file list starts here ++ $(OPENSSL_PATH)/crypto/bn/rsa_sup_mul.c + $(OPENSSL_PATH)/crypto/evp/kdf_lib.c + $(OPENSSL_PATH)/crypto/evp/pkey_kdf.c + $(OPENSSL_PATH)/crypto/kdf/kbkdf.c +-- +2.37.3 + diff --git a/SOURCES/ovmf-vars-generator b/SOURCES/ovmf-vars-generator new file mode 100755 index 0000000..111e438 --- /dev/null +++ b/SOURCES/ovmf-vars-generator @@ -0,0 +1,295 @@ +#!/bin/python3 +# Copyright (C) 2017 Red Hat +# Authors: +# - Patrick Uiterwijk +# - Kashyap Chamarthy +# +# Licensed under MIT License, for full text see LICENSE +# +# Purpose: Launch a QEMU guest and enroll ithe UEFI keys into an OVMF +# variables ("VARS") file. Then boot a Linux kernel with QEMU. +# Finally, perform a check to verify if Secure Boot +# is enabled. + +from __future__ import print_function + +import argparse +import os +import logging +import tempfile +import shutil +import string +import subprocess + + +def strip_special(line): + return ''.join([c for c in str(line) if c in string.printable]) + + +def generate_qemu_cmd(args, readonly, *extra_args): + if args.disable_smm: + machinetype = 'pc' + else: + machinetype = 'q35,smm=on' + machinetype += ',accel=%s' % ('kvm' if args.enable_kvm else 'tcg') + + if args.oem_string is None: + oemstrings = [] + else: + oemstring_values = [ + ",value=" + s.replace(",", ",,") for s in args.oem_string ] + oemstrings = [ + '-smbios', + "type=11" + ''.join(oemstring_values) ] + + return [ + args.qemu_binary, + '-machine', machinetype, + '-display', 'none', + '-no-user-config', + '-nodefaults', + '-m', '768', + '-smp', '2,sockets=2,cores=1,threads=1', + '-chardev', 'pty,id=charserial1', + '-device', 'isa-serial,chardev=charserial1,id=serial1', + '-global', 'driver=cfi.pflash01,property=secure,value=%s' % ( + 'off' if args.disable_smm else 'on'), + '-drive', + 'file=%s,if=pflash,format=raw,unit=0,readonly=on' % ( + args.ovmf_binary), + '-drive', + 'file=%s,if=pflash,format=raw,unit=1,readonly=%s' % ( + args.out_temp, 'on' if readonly else 'off'), + '-serial', 'stdio'] + oemstrings + list(extra_args) + + +def download(url, target, suffix, no_download): + istemp = False + if target and os.path.exists(target): + return target, istemp + if not target: + temped = tempfile.mkstemp(prefix='qosb.', suffix='.%s' % suffix) + os.close(temped[0]) + target = temped[1] + istemp = True + if no_download: + raise Exception('%s did not exist, but downloading was disabled' % + target) + import requests + logging.debug('Downloading %s to %s', url, target) + r = requests.get(url, stream=True) + with open(target, 'wb') as f: + for chunk in r.iter_content(chunk_size=1024): + if chunk: + f.write(chunk) + return target, istemp + + +def enroll_keys(args): + shutil.copy(args.ovmf_template_vars, args.out_temp) + + logging.info('Starting enrollment') + + cmd = generate_qemu_cmd( + args, + False, + '-drive', + 'file=%s,format=raw,if=none,media=cdrom,id=drive-cd1,' + 'readonly=on' % args.uefi_shell_iso, + '-device', + 'ide-cd,drive=drive-cd1,id=cd1,' + 'bootindex=1') + p = subprocess.Popen(cmd, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + logging.info('Performing enrollment') + # Wait until the UEFI shell starts (first line is printed) + read = p.stdout.readline() + if b'char device redirected' in read: + read = p.stdout.readline() + # Skip passed QEMU warnings, like the following one we see in Ubuntu: + # qemu-system-x86_64: warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5] + while b'qemu-system-x86_64: warning:' in read: + read = p.stdout.readline() + if args.print_output: + print(strip_special(read), end='') + print() + # Send the escape char to enter the UEFI shell early + p.stdin.write(b'\x1b') + p.stdin.flush() + # And then run the following three commands from the UEFI shell: + # change into the first file system device; install the default + # keys and certificates, and reboot + p.stdin.write(b'fs0:\r\n') + p.stdin.write(b'EnrollDefaultKeys.efi\r\n') + p.stdin.write(b'reset -s\r\n') + p.stdin.flush() + while True: + read = p.stdout.readline() + if args.print_output: + print('OUT: %s' % strip_special(read), end='') + print() + if b'info: success' in read: + break + p.wait() + if args.print_output: + print(strip_special(p.stdout.read()), end='') + logging.info('Finished enrollment') + + +def test_keys(args): + logging.info('Grabbing test kernel') + kernel, kerneltemp = download(args.kernel_url, args.kernel_path, + 'kernel', args.no_download) + + logging.info('Starting verification') + try: + cmd = generate_qemu_cmd( + args, + True, + '-append', 'console=tty0 console=ttyS0,115200n8', + '-kernel', kernel) + p = subprocess.Popen(cmd, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + logging.info('Performing verification') + while True: + read = p.stdout.readline() + if args.print_output: + print('OUT: %s' % strip_special(read), end='') + print() + if b'Secure boot disabled' in read: + raise Exception('Secure Boot was disabled') + elif b'Secure boot enabled' in read: + logging.info('Confirmed: Secure Boot is enabled') + break + elif b'Kernel is locked down from EFI secure boot' in read: + logging.info('Confirmed: Secure Boot is enabled') + break + p.kill() + if args.print_output: + print(strip_special(p.stdout.read()), end='') + logging.info('Finished verification') + finally: + if kerneltemp: + os.remove(kernel) + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument('output', help='Filename for output vars file') + parser.add_argument('--out-temp', help=argparse.SUPPRESS) + parser.add_argument('--force', help='Overwrite existing output file', + action='store_true') + parser.add_argument('--print-output', help='Print the QEMU guest output', + action='store_true') + parser.add_argument('--verbose', '-v', help='Increase verbosity', + action='count') + parser.add_argument('--quiet', '-q', help='Decrease verbosity', + action='count') + parser.add_argument('--qemu-binary', help='QEMU binary path', + default='/usr/bin/qemu-system-x86_64') + parser.add_argument('--enable-kvm', help='Enable KVM acceleration', + action='store_true') + parser.add_argument('--ovmf-binary', help='OVMF secureboot code file', + default='/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd') + parser.add_argument('--ovmf-template-vars', help='OVMF empty vars file', + default='/usr/share/edk2/ovmf/OVMF_VARS.fd') + parser.add_argument('--uefi-shell-iso', help='Path to uefi shell iso', + default='/usr/share/edk2/ovmf/UefiShell.iso') + parser.add_argument('--skip-enrollment', + help='Skip enrollment, only test', action='store_true') + parser.add_argument('--skip-testing', + help='Skip testing generated "VARS" file', + action='store_true') + parser.add_argument('--kernel-path', + help='Specify a consistent path for kernel') + parser.add_argument('--no-download', action='store_true', + help='Never download a kernel') + parser.add_argument('--fedora-version', + help='Fedora version to get kernel for checking', + default='27') + parser.add_argument('--kernel-url', help='Kernel URL', + default='https://download.fedoraproject.org/pub/fedora' + '/linux/releases/%(version)s/Everything/x86_64' + '/os/images/pxeboot/vmlinuz') + parser.add_argument('--disable-smm', + help=('Don\'t restrict varstore pflash writes to ' + 'guest code that executes in SMM. Use this ' + 'option only if your OVMF binary doesn\'t have ' + 'the edk2 SMM driver stack built into it ' + '(possibly because your QEMU binary lacks SMM ' + 'emulation). Note that without restricting ' + 'varstore pflash writes to guest code that ' + 'executes in SMM, a malicious guest kernel, ' + 'used for testing, could undermine Secure ' + 'Boot.'), + action='store_true') + parser.add_argument('--oem-string', + help=('Pass the argument to the guest as a string in ' + 'the SMBIOS Type 11 (OEM Strings) table. ' + 'Multiple occurrences of this option are ' + 'collected into a single SMBIOS Type 11 table. ' + 'A pure ASCII string argument is strongly ' + 'suggested.'), + action='append') + args = parser.parse_args() + args.kernel_url = args.kernel_url % {'version': args.fedora_version} + + validate_args(args) + return args + + +def validate_args(args): + if (os.path.exists(args.output) + and not args.force + and not args.skip_enrollment): + raise Exception('%s already exists' % args.output) + + if args.skip_enrollment and not os.path.exists(args.output): + raise Exception('%s does not yet exist' % args.output) + + verbosity = (args.verbose or 1) - (args.quiet or 0) + if verbosity >= 2: + logging.basicConfig(level=logging.DEBUG) + elif verbosity == 1: + logging.basicConfig(level=logging.INFO) + elif verbosity < 0: + logging.basicConfig(level=logging.ERROR) + else: + logging.basicConfig(level=logging.WARN) + + if args.skip_enrollment: + args.out_temp = args.output + else: + temped = tempfile.mkstemp(prefix='qosb.', suffix='.vars') + os.close(temped[0]) + args.out_temp = temped[1] + logging.debug('Temp output: %s', args.out_temp) + + +def move_to_dest(args): + shutil.copy(args.out_temp, args.output) + os.remove(args.out_temp) + + +def main(): + args = parse_args() + if not args.skip_enrollment: + enroll_keys(args) + if not args.skip_testing: + test_keys(args) + if not args.skip_enrollment: + move_to_dest(args) + if args.skip_testing: + logging.info('Created %s' % args.output) + else: + logging.info('Created and verified %s' % args.output) + else: + logging.info('Verified %s', args.output) + + +if __name__ == '__main__': + main() diff --git a/SOURCES/ovmf-whitepaper-c770f8c.txt b/SOURCES/ovmf-whitepaper-c770f8c.txt new file mode 100644 index 0000000..ba727b4 --- /dev/null +++ b/SOURCES/ovmf-whitepaper-c770f8c.txt @@ -0,0 +1,2422 @@ +Open Virtual Machine Firmware (OVMF) Status Report +July 2014 (with updates in August 2014 - January 2015) + +Author: Laszlo Ersek +Copyright (C) 2014-2015, Red Hat, Inc. +CC BY-SA 4.0 + +Abstract +-------- + +The Unified Extensible Firmware Interface (UEFI) is a specification that +defines a software interface between an operating system and platform firmware. +UEFI is designed to replace the Basic Input/Output System (BIOS) firmware +interface. + +Hardware platform vendors have been increasingly adopting the UEFI +Specification to govern their boot firmware developments. OVMF (Open Virtual +Machine Firmware), a sub-project of Intel's EFI Development Kit II (edk2), +enables UEFI support for Ia32 and X64 Virtual Machines. + +This paper reports on the status of the OVMF project, treats features and +limitations, gives end-user hints, and examines some areas in-depth. + +Keywords: ACPI, boot options, CSM, edk2, firmware, flash, fw_cfg, KVM, memory +map, non-volatile variables, OVMF, PCD, QEMU, reset vector, S3, Secure Boot, +Smbios, SMM, TianoCore, UEFI, VBE shim, Virtio + +Table of Contents +----------------- + +- Motivation +- Scope +- Example qemu invocation +- Installation of OVMF guests with virt-manager and virt-install +- Supported guest operating systems +- Compatibility Support Module (CSM) +- Phases of the boot process +- Project structure +- Platform Configuration Database (PCD) +- Firmware image structure +- S3 (suspend to RAM and resume) +- A comprehensive memory map of OVMF +- Known Secure Boot limitations +- Variable store and LockBox in SMRAM +- Select features + - X64-specific reset vector for OVMF + - Client library for QEMU's firmware configuration interface + - Guest ACPI tables + - Guest SMBIOS tables + - Platform-specific boot policy + - Virtio drivers + - Platform Driver + - Video driver +- Afterword + +Motivation +---------- + +OVMF extends the usual benefits of virtualization to UEFI. Reasons to use OVMF +include: + +- Legacy-free guests. A UEFI-based environment eliminates dependencies on + legacy address spaces and devices. This is especially beneficial when used + with physically assigned devices where the legacy operating mode is + troublesome to support, ex. assigned graphics cards operating in legacy-free, + non-VGA mode in the guest. + +- Future proof guests. The x86 market is steadily moving towards a legacy-free + platform and guest operating systems may eventually require a UEFI + environment. OVMF provides that next generation firmware support for such + applications. + +- GUID partition tables (GPTs). MBR partition tables represent partition + offsets and sizes with 32-bit integers, in units of 512 byte sectors. This + limits the addressable portion of the disk to 2 TB. GPT represents logical + block addresses with 64 bits. + +- Liberating boot loader binaries from residing in contested and poorly defined + space between the partition table and the partitions. + +- Support for booting off disks (eg. pass-through physical SCSI devices) with a + 4kB physical and logical sector size, i.e. which don't have 512-byte block + emulation. + +- Development and testing of Secure Boot-related features in guest operating + systems. Although OVMF's Secure Boot implementation is currently not secure + against malicious UEFI drivers, UEFI applications, and guest kernels, + trusted guest code that only uses standard UEFI interfaces will find a valid + Secure Boot environment under OVMF, with working key enrollment and signature + validation. This enables development and testing of portable, Secure + Boot-related guest code. + +- Presence of non-volatile UEFI variables. This furthers development and + testing of OS installers, UEFI boot loaders, and unique, dependent guest OS + features. For example, an efivars-backed pstore (persistent storage) + file system works under Linux. + +- Altogether, a near production-level UEFI environment for virtual machines + when Secure Boot is not required. + +Scope +----- + +UEFI and especially Secure Boot have been topics fraught with controversy and +political activism. This paper sidesteps these aspects and strives to focus on +use cases, hands-on information for end users, and technical details. + +Unless stated otherwise, the expression "X supports Y" means "X is technically +compatible with interfaces provided or required by Y". It does not imply +support as an activity performed by natural persons or companies. + +We discuss the status of OVMF at a state no earlier than edk2 SVN revision +16158. The paper concentrates on upstream projects and communities, but +occasionally it pans out about OVMF as it is planned to be shipped (as +Technical Preview) in Red Hat Enterprise Linux 7.1. Such digressions are marked +with the [RHEL] margin notation. + +Although other VMMs and accelerators are known to support (or plan to support) +OVMF to various degrees -- for example, VirtualBox, Xen, BHyVe --, we'll +emphasize OVMF on qemu/KVM, because QEMU and KVM have always been Red Hat's +focus wrt. OVMF. + +The recommended upstream QEMU version is 2.1+. The recommended host Linux +kernel (KVM) version is 3.10+. The recommended QEMU machine type is +"qemu-system-x86_64 -M pc-i440fx-2.1" or later. + +The term "TianoCore" is used interchangeably with "edk2" in this paper. + +Example qemu invocation +----------------------- + +The following commands give a quick foretaste of installing a UEFI operating +system on OVMF, relying only on upstream edk2 and qemu. + +- Clone and build OVMF: + + git clone https://github.com/tianocore/edk2.git + cd edk2 + nice OvmfPkg/build.sh -a X64 -n $(getconf _NPROCESSORS_ONLN) + + (Note that this ad-hoc build will not include the Secure Boot feature.) + +- The build output file, "OVMF.fd", includes not only the executable firmware + code, but the non-volatile variable store as well. For this reason, make a + VM-specific copy of the build output (the variable store should be private to + the virtual machine): + + cp Build/OvmfX64/DEBUG_GCC4?/FV/OVMF.fd fedora.flash + + (The variable store and the firmware executable are also available in the + build output as separate files: "OVMF_VARS.fd" and "OVMF_CODE.fd". This + enables central management and updates of the firmware executable, while each + virtual machine can retain its own variable store.) + +- Download a Fedora LiveCD: + + wget https://dl.fedoraproject.org/pub/fedora/linux/releases/20/Live/x86_64/Fedora-Live-Xfce-x86_64-20-1.iso + +- Create a virtual disk (qcow2 format, 20 GB in size): + + qemu-img create -f qcow2 fedora.img 20G + +- Create the following qemu wrapper script under the name "fedora.sh": + + # Basic virtual machine properties: a recent i440fx machine type, KVM + # acceleration, 2048 MB RAM, two VCPUs. + OPTS="-M pc-i440fx-2.1 -enable-kvm -m 2048 -smp 2" + + # The OVMF binary, including the non-volatile variable store, appears as a + # "normal" qemu drive on the host side, and it is exposed to the guest as a + # persistent flash device. + OPTS="$OPTS -drive if=pflash,format=raw,file=fedora.flash" + + # The hard disk is exposed to the guest as a virtio-block device. OVMF has a + # driver stack that supports such a disk. We specify this disk as first boot + # option. OVMF recognizes the boot order specification. + OPTS="$OPTS -drive id=disk0,if=none,format=qcow2,file=fedora.img" + OPTS="$OPTS -device virtio-blk-pci,drive=disk0,bootindex=0" + + # The Fedora installer disk appears as an IDE CD-ROM in the guest. This is + # the 2nd boot option. + OPTS="$OPTS -drive id=cd0,if=none,format=raw,readonly" + OPTS="$OPTS,file=Fedora-Live-Xfce-x86_64-20-1.iso" + OPTS="$OPTS -device ide-cd,bus=ide.1,drive=cd0,bootindex=1" + + # The following setting enables S3 (suspend to RAM). OVMF supports S3 + # suspend/resume. + OPTS="$OPTS -global PIIX4_PM.disable_s3=0" + + # OVMF emits a number of info / debug messages to the QEMU debug console, at + # ioport 0x402. We configure qemu so that the debug console is indeed + # available at that ioport. We redirect the host side of the debug console to + # a file. + OPTS="$OPTS -global isa-debugcon.iobase=0x402 -debugcon file:fedora.ovmf.log" + + # QEMU accepts various commands and queries from the user on the monitor + # interface. Connect the monitor with the qemu process's standard input and + # output. + OPTS="$OPTS -monitor stdio" + + # A USB tablet device in the guest allows for accurate pointer tracking + # between the host and the guest. + OPTS="$OPTS -device piix3-usb-uhci -device usb-tablet" + + # Provide the guest with a virtual network card (virtio-net). + # + # Normally, qemu provides the guest with a UEFI-conformant network driver + # from the iPXE project, in the form of a PCI expansion ROM. For this test, + # we disable the expansion ROM and allow OVMF's built-in virtio-net driver to + # take effect. + # + # On the host side, we use the SLIRP ("user") network backend, which has + # relatively low performance, but it doesn't require extra privileges from + # the user executing qemu. + OPTS="$OPTS -netdev id=net0,type=user" + OPTS="$OPTS -device virtio-net-pci,netdev=net0,romfile=" + + # A Spice QXL GPU is recommended as the primary VGA-compatible display + # device. It is a full-featured virtual video card, with great operating + # system driver support. OVMF supports it too. + OPTS="$OPTS -device qxl-vga" + + qemu-system-x86_64 $OPTS + +- Start the Fedora guest: + + sh fedora.sh + +- The above command can be used for both installation and later boots of the + Fedora guest. + +- In order to verify basic OVMF network connectivity: + + - Assuming that the non-privileged user running qemu belongs to group G + (where G is a numeric identifier), ensure as root on the host that the + group range in file "/proc/sys/net/ipv4/ping_group_range" includes G. + + - As the non-privileged user, boot the guest as usual. + + - On the TianoCore splash screen, press ESC. + + - Navigate to Boot Manager | EFI Internal Shell + + - In the UEFI Shell, issue the following commands: + + ifconfig -s eth0 dhcp + ping A.B.C.D + + where A.B.C.D is a public IPv4 address in dotted decimal notation that your + host can reach. + + - Type "quit" at the (qemu) monitor prompt. + +Installation of OVMF guests with virt-manager and virt-install +-------------------------------------------------------------- + +(1) Assuming OVMF has been installed on the host with the following files: + - /usr/share/OVMF/OVMF_CODE.fd + - /usr/share/OVMF/OVMF_VARS.fd + + locate the "nvram" stanza in "/etc/libvirt/qemu.conf", and edit it as + follows: + + nvram = [ "/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd" ] + +(2) Restart libvirtd with your Linux distribution's service management tool; + for example, + + systemctl restart libvirtd + +(3) In virt-manager, proceed with the guest installation as usual: + - select File | New Virtual Machine, + - advance to Step 5 of 5, + - in Step 5, check "Customize configuration before install", + - click Finish; + - in the customization dialog, select Overview | Firmware, and choose UEFI, + - click Apply and Begin Installation. + +(4) With virt-install: + + LDR="loader=/usr/share/OVMF/OVMF_CODE.fd,loader_ro=yes,loader_type=pflash" + virt-install \ + --name fedora20 \ + --memory 2048 \ + --vcpus 2 \ + --os-variant fedora20 \ + --boot hd,cdrom,$LDR \ + --disk size=20 \ + --disk path=Fedora-Live-Xfce-x86_64-20-1.iso,device=cdrom,bus=scsi + +(5) A popular, distribution-independent, bleeding-edge OVMF package is + available under , courtesy of Gerd Hoffmann. + + The "edk2.git-ovmf-x64" package provides the following files, among others: + - /usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd + - /usr/share/edk2.git/ovmf-x64/OVMF_VARS-pure-efi.fd + + When using this package, adapt steps (1) and (4) accordingly. + +(6) Additionally, the "edk2.git-ovmf-x64" package seeks to simplify the + enablement of Secure Boot in a virtual machine (strictly for development + and testing purposes). + + - Boot the virtual machine off the CD-ROM image called + "/usr/share/edk2.git/ovmf-x64/UefiShell.iso"; before or after installing + the main guest operating system. + + - When the UEFI shell appears, issue the following commands: + + EnrollDefaultKeys.efi + reset -s + + - The EnrollDefaultKeys.efi utility enrolls the following keys: + + - A static example X.509 certificate (CN=TestCommonName) as Platform Key + and first Key Exchange Key. + + The private key matching this certificate has been destroyed (but you + shouldn't trust this statement). + + - "Microsoft Corporation KEK CA 2011" as second Key Exchange Key + (SHA1: 31:59:0b:fd:89:c9:d7:4e:d0:87:df:ac:66:33:4b:39:31:25:4b:30). + + - "Microsoft Windows Production PCA 2011" as first DB entry + (SHA1: 58:0a:6f:4c:c4:e4:b6:69:b9:eb:dc:1b:2b:3e:08:7b:80:d0:67:8d). + + - "Microsoft Corporation UEFI CA 2011" as second DB entry + (SHA1: 46:de:f6:3b:5c:e6:1c:f8:ba:0d:e2:e6:63:9c:10:19:d0:ed:14:f3). + + These keys suffice to boot released versions of popular Linux + distributions (through the shim.efi utility), and Windows 8 and Windows + Server 2012 R2, in Secure Boot mode. + +Supported guest operating systems +--------------------------------- + +Upstream OVMF does not favor some guest operating systems over others for +political or ideological reasons. However, some operating systems are harder to +obtain and/or technically more difficult to support. The general expectation is +that recent UEFI OSes should just work. Please consult the "OvmfPkg/README" +file. + +The following guest OSes were tested with OVMF: +- Red Hat Enterprise Linux 6 +- Red Hat Enterprise Linux 7 +- Fedora 18 +- Fedora 19 +- Fedora 20 +- Windows Server 2008 R2 SP1 +- Windows Server 2012 +- Windows 8 + +Notes about Windows Server 2008 R2 (paraphrasing the "OvmfPkg/README" file): + +- QEMU should be started with one of the "-device qxl-vga" and "-device VGA" + options. + +- Only one video mode, 1024x768x32, is supported at OS runtime. + + Please refer to the section about QemuVideoDxe (OVMF's built-in video driver) + for more details on this limitation. + +- The qxl-vga video card is recommended ("-device qxl-vga"). After booting the + installed guest OS, select the video card in Device Manager, and upgrade the + video driver to the QXL XDDM one. + + The QXL XDDM driver can be downloaded from + , under Guest | Windows binaries. + + This driver enables additional graphics resolutions at OS runtime, and + provides S3 (suspend/resume) capability. + +Notes about Windows Server 2012 and Windows 8: + +- QEMU should be started with the "-device qxl-vga,revision=4" option (or a + later revision, if available). + +- The guest OS's builtin video driver inherits the video mode / frame buffer + from OVMF. There's no way to change the resolution at OS runtime. + + For this reason, a platform driver has been developed for OVMF, which allows + users to change the preferred video mode in the firmware. Please refer to the + section about PlatformDxe for details. + +- It is recommended to upgrade the guest OS's video driver to the QXL WDDM one, + via Device Manager. + + Binaries for the QXL WDDM driver can be found at + (pick a version greater than or + equal to 0.6), while the source code resides at + . + + This driver enables additional graphics resolutions at OS runtime, and + provides S3 (suspend/resume) capability. + +Compatibility Support Module (CSM) +---------------------------------- + +Collaboration between SeaBIOS and OVMF developers has enabled SeaBIOS to be +built as a Compatibility Support Module, and OVMF to embed and use it. + +Benefits of a SeaBIOS CSM include: + +- The ability to boot legacy (non-UEFI) operating systems, such as legacy Linux + systems, Windows 7, OpenBSD 5.2, FreeBSD 8/9, NetBSD, DragonflyBSD, Solaris + 10/11. + +- Legacy (non-UEFI-compliant) PCI expansion ROMs, such as a VGA BIOS, mapped by + QEMU in emulated devices' ROM BARs, are loaded and executed by OVMF. + + For example, this grants the Windows Server 2008 R2 SP1 guest's native, + legacy video driver access to all modes of all QEMU video cards. + +Building the CSM target of the SeaBIOS source tree is out of scope for this +report. Additionally, upstream OVMF does not enable the CSM by default. + +Interested users and developers should look for OVMF's "-D CSM_ENABLE" +build-time option, and check out the continuous +integration repository, which provides CSM-enabled OVMF builds. + +[RHEL] The "OVMF_CODE.fd" firmware image made available on the Red Hat + Enterprise Linux 7.1 host does not include a Compatibility Support + Module, for the following reasons: + + - Virtual machines running officially supported, legacy guest operating + systems should just use the standalone SeaBIOS firmware. Firmware + selection is flexible in virtualization, see eg. "Installation of OVMF + guests with virt-manager and virt-install" above. + + - The 16-bit thunking interface between OVMF and SeaBIOS is very complex + and presents a large debugging and support burden, based on past + experience. + + - Secure Boot is incompatible with CSM. + + - Inter-project dependencies should be minimized whenever possible. + + - Using the default QXL video card, the Windows 2008 R2 SP1 guest can be + installed with its built-in, legacy video driver. Said driver will + select the only available video mode, 1024x768x32. After installation, + the video driver can be upgraded to the full-featured QXL XDDM driver. + +Phases of the boot process +-------------------------- + +The PI and UEFI specifications, and Intel's UEFI and EDK II Learning and +Development materials provide ample information on PI and UEFI concepts. The +following is an absolutely minimal, rough glossary that is included only to +help readers new to PI and UEFI understand references in later, OVMF-specific +sections. We defer heavily to the official specifications and the training +materials, and frequently quote them below. + +A central concept to mention early is the GUID -- globally unique identifier. A +GUID is a 128-bit number, written as XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, +where each X stands for a hexadecimal nibble. GUIDs are used to name everything +in PI and in UEFI. Programmers introduce new GUIDs with the "uuidgen" utility, +and standards bodies standardize well-known services by positing their GUIDs. + +The boot process is roughly divided in the following phases: + +- Reset vector code. + +- SEC: Security phase. This phase is the root of firmware integrity. + +- PEI: Pre-EFI Initialization. This phase performs "minimal processor, chipset + and platform configuration for the purpose of discovering memory". Modules in + PEI collectively save their findings about the platform in a list of HOBs + (hand-off blocks). + + When developing PEI code, the Platform Initialization (PI) specification + should be consulted. + +- DXE: Driver eXecution Environment, pronounced as "Dixie". This "is the phase + where the bulk of the booting occurs: devices are enumerated and initialized, + UEFI services are supported, and protocols and drivers are implemented. Also, + the tables that create the UEFI interface are produced". + + On the PEI/DXE boundary, the HOBs produced by PEI are consumed. For example, + this is how the memory space map is configured initially. + +- BDS: Boot Device Selection. It is "responsible for determining how and where + you want to boot the operating system". + + When developing DXE and BDS code, it is mainly the UEFI specification that + should be consulted. When speaking about DXE, BDS is frequently considered to + be a part of it. + +The following concepts are tied to specific boot process phases: + +- PEIM: a PEI Module (pronounced "PIM"). A binary module running in the PEI + phase, consuming some PPIs and producing other PPIs, and producing HOBs. + +- PPI: PEIM-to-PEIM interface. A structure of function pointers and related + data members that establishes a PEI service, or an instance of a PEI service. + PPIs are identified by GUID. + + An example is EFI_PEI_S3_RESUME2_PPI (6D582DBC-DB85-4514-8FCC-5ADF6227B147). + +- DXE driver: a binary module running in the DXE and BDS phases, consuming some + protocols and producing other protocols. + +- Protocol: A structure of function pointers and related data members that + establishes a DXE service, or an instance of a DXE service. Protocols are + identified by GUID. + + An example is EFI_BLOCK_IO_PROTOCOL (964E5B21-6459-11D2-8E39-00A0C969723B). + +- Architectural protocols: a set of standard protocols that are foundational to + the working of a UEFI system. Each architectural protocol has at most one + instance. Architectural protocols are implemented by a subset of DXE drivers. + DXE drivers explicitly list the set of protocols (including architectural + protocols) that they need to work. UEFI drivers can only be loaded once all + architectural protocols have become available during the DXE phase. + + An example is EFI_VARIABLE_WRITE_ARCH_PROTOCOL + (6441F818-6362-4E44-B570-7DBA31DD2453). + +Project structure +----------------- + +The term "OVMF" usually denotes the project (community and development effort) +that provide and maintain the subject matter UEFI firmware for virtual +machines. However the term is also frequently applied to the firmware binary +proper that a virtual machine executes. + +OVMF emerges as a compilation of several modules from the edk2 source +repository. "edk2" stands for EFI Development Kit II; it is a "modern, +feature-rich, cross-platform firmware development environment for the UEFI and +PI specifications". + +The composition of OVMF is dictated by the following build control files: + + OvmfPkg/OvmfPkgIa32.dsc + OvmfPkg/OvmfPkgIa32.fdf + + OvmfPkg/OvmfPkgIa32X64.dsc + OvmfPkg/OvmfPkgIa32X64.fdf + + OvmfPkg/OvmfPkgX64.dsc + OvmfPkg/OvmfPkgX64.fdf + +The format of these files is described in the edk2 DSC and FDF specifications. +Roughly, the DSC file determines: +- library instance resolutions for library class requirements presented by the + modules to be compiled, +- the set of modules to compile. + +The FDF file roughly determines: +- what binary modules (compilation output files, precompiled binaries, graphics + image files, verbatim binary sections) to include in the firmware image, +- how to lay out the firmware image. + +The Ia32 flavor of these files builds a firmware where both PEI and DXE phases +are 32-bit. The Ia32X64 flavor builds a firmware where the PEI phase consists +of 32-bit modules, and the DXE phase is 64-bit. The X64 flavor builds a purely +64-bit firmware. + +The word size of the DXE phase must match the word size of the runtime OS -- a +32-bit DXE can't cooperate with a 64-bit OS, and a 64-bit DXE can't work a +32-bit OS. + +OVMF pulls together modules from across the edk2 tree. For example: + +- common drivers and libraries that are platform independent are usually + located under MdeModulePkg and MdePkg, + +- common but hardware-specific drivers and libraries that match QEMU's + pc-i440fx-* machine type are pulled in from IntelFrameworkModulePkg, + PcAtChipsetPkg and UefiCpuPkg, + +- the platform independent UEFI Shell is built from ShellPkg, + +- OvmfPkg includes drivers and libraries that are useful for virtual machines + and may or may not be specific to QEMU's pc-i440fx-* machine type. + +Platform Configuration Database (PCD) +------------------------------------- + +Like the "Phases of the boot process" section, this one introduces a concept in +very raw form. We defer to the PCD related edk2 specifications, and we won't +discuss implementation details here. Our purpose is only to offer the reader a +usable (albeit possibly inaccurate) definition, so that we can refer to PCDs +later on. + +Colloquially, when we say "PCD", we actually mean "PCD entry"; that is, an +entry stored in the Platform Configuration Database. + +The Platform Configuration Database is +- a firmware-wide +- name-value store +- of scalars and buffers +- where each entry may be + - build-time constant, or + - run-time dynamic, or + - theoretically, a middle option: patchable in the firmware file itself, + using a dedicated tool. (OVMF does not utilize externally patchable + entries.) + +A PCD entry is declared in the DEC file of the edk2 top-level Package directory +whose modules (drivers and libraries) are the primary consumers of the PCD +entry. (See for example OvmfPkg/OvmfPkg.dec). Basically, a PCD in a DEC file +exposes a simple customization point. + +Interest in a PCD entry is communicated to the build system by naming the PCD +entry in the INF file of the interested module (application, driver or +library). The module may read and -- dependent on the PCD entry's category -- +write the PCD entry. + +Let's investigate the characteristics of the Database and the PCD entries. + +- Firmware-wide: technically, all modules may access all entries they are + interested in, assuming they advertise their interest in their INF files. + With careful design, PCDs enable inter-driver propagation of (simple) system + configuration. PCDs are available in both PEI and DXE. + + (UEFI drivers meant to be portable (ie. from third party vendors) are not + supposed to use PCDs, since PCDs qualify internal to the specific edk2 + firmware in question.) + +- Name-value store of scalars and buffers: each PCD has a symbolic name, and a + fixed scalar type (UINT16, UINT32 etc), or VOID* for buffers. Each PCD entry + belongs to a namespace, where a namespace is (obviously) a GUID, defined in + the DEC file. + +- A DEC file can permit several categories for a PCD: + - build-time constant ("FixedAtBuild"), + - patchable in the firmware image ("PatchableInModule", unused in OVMF), + - runtime modifiable ("Dynamic"). + +The platform description file (DSC) of a top-level Package directory may choose +the exact category for a given PCD entry that its modules wish to use, and +assign a default (or constant) initial value to it. + +In addition, the edk2 build system too can initialize PCD entries to values +that it calculates while laying out the flash device image. Such PCD +assignments are described in the FDF control file. + +Firmware image structure +------------------------ + +(We assume the common X64 choice for both PEI and DXE, and the default DEBUG +build target.) + +The OvmfPkg/OvmfPkgX64.fdf file defines the following layout for the flash +device image "OVMF.fd": + + Description Compression type Size + ------------------------------ ---------------------- ------- + Non-volatile data storage open-coded binary data 128 KB + Variable store 56 KB + Event log 4 KB + Working block 4 KB + Spare area 64 KB + + FVMAIN_COMPACT uncompressed 1712 KB + FV Firmware File System file LZMA compressed + PEIFV uncompressed 896 KB + individual PEI modules uncompressed + DXEFV uncompressed 8192 KB + individual DXE modules uncompressed + + SECFV uncompressed 208 KB + SEC driver + reset vector code + +The top-level image consists of three regions (three firmware volumes): +- non-volatile data store (128 KB), +- main firmware volume (FVMAIN_COMPACT, 1712 KB), +- firmware volume containing the reset vector code and the SEC phase code (208 + KB). + +In total, the OVMF.fd file has size 128 KB + 1712 KB + 208 KB == 2 MB. + +(1) The firmware volume with non-volatile data store (128 KB) has the following + internal structure, in blocks of 4 KB: + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ L: event log + LIVE | varstore |L|W| W: working block + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + SPARE | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The first half of this firmware volume is "live", while the second half is + "spare". The spare half is important when the variable driver reclaims + unused storage and reorganizes the variable store. + + The live half dedicates 14 blocks (56 KB) to the variable store itself. On + top of those, one block is set aside for an event log, and one block is + used as the working block of the fault tolerant write protocol. Fault + tolerant writes are used to recover from an occasional (virtual) power loss + during variable updates. + + The blocks in this firmware volume are accessed, in stacking order from + least abstract to most abstract, by: + + - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL (provided by + OvmfPkg/QemuFlashFvbServicesRuntimeDxe), + + - EFI_FAULT_TOLERANT_WRITE_PROTOCOL (provided by + MdeModulePkg/Universal/FaultTolerantWriteDxe), + + - architectural protocols instrumental to the runtime UEFI variable + services: + - EFI_VARIABLE_ARCH_PROTOCOL, + - EFI_VARIABLE_WRITE_ARCH_PROTOCOL. + + In a non-secure boot build, the DXE driver providing these architectural + protocols is MdeModulePkg/Universal/Variable/RuntimeDxe. In a secure boot + build, where authenticated variables are available, the DXE driver + offering these protocols is SecurityPkg/VariableAuthenticated/RuntimeDxe. + +(2) The main firmware volume (FVMAIN_COMPACT, 1712 KB) embeds further firmware + volumes. The outermost layer is a Firmware File System (FFS), carrying a + single file. This file holds an LZMA-compressed section, which embeds two + firmware volumes: PEIFV (896 KB) with PEIMs, and DXEFV (8192 KB) with DXE + and UEFI drivers. + + This scheme enables us to build 896 KB worth of PEI drivers and 8192 KB + worth of DXE and UEFI drivers, compress them all with LZMA in one go, and + store the compressed result in 1712 KB, saving room in the flash device. + +(3) The SECFV firmware volume (208 KB) is not compressed. It carries the + "volume top file" with the reset vector code, to end at 4 GB in + guest-physical address space, and the SEC phase driver (OvmfPkg/Sec). + + The last 16 bytes of the volume top file (mapped directly under 4 GB) + contain a NOP slide and a jump instruction. This is where QEMU starts + executing the firmware, at address 0xFFFF_FFF0. The reset vector and the + SEC driver run from flash directly. + + The SEC driver locates FVMAIN_COMPACT in the flash, and decompresses the + main firmware image to RAM. The rest of OVMF (PEI, DXE, BDS phases) run + from RAM. + +As already mentioned, the OVMF.fd file is mapped by qemu's +"hw/block/pflash_cfi01.c" device just under 4 GB in guest-physical address +space, according to the command line option + + -drive if=pflash,format=raw,file=fedora.flash + +(refer to the Example qemu invocation). This is a "ROMD device", which can +switch out of "ROMD mode" and back into it. + +Namely, in the default ROMD mode, the guest-physical address range backed by +the flash device reads and executes as ROM (it does not trap from KVM to QEMU). +The first write access in this mode traps to QEMU, and flips the device out of +ROMD mode. + +In non-ROMD mode, the flash chip is programmed by storing CFI (Common Flash +Interface) command values at the flash-covered addresses; both reads and writes +trap to QEMU, and the flash contents are modified and synchronized to the +host-side file. A special CFI command flips the flash device back to ROMD mode. + +Qemu implements the above based on the KVM_CAP_READONLY_MEM / KVM_MEM_READONLY +KVM features, and OVMF puts it to use in its EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL +implementation, under "OvmfPkg/QemuFlashFvbServicesRuntimeDxe". + +IMPORTANT: Never pass OVMF.fd to qemu with the -bios option. That option maps +the firmware image as ROM into the guest's address space, and forces OVMF to +emulate non-volatile variables with a fallback driver that is bound to have +insufficient and confusing semantics. + +The 128 KB firmware volume with the variable store, discussed under (1), is +also built as a separate host-side file, named "OVMF_VARS.fd". The "rest" is +built into a third file, "OVMF_CODE.fd", which is only 1920 KB in size. The +variable store is mapped into its usual location, at 4 GB - 2 MB = 0xFFE0_0000, +through the following qemu options: + + -drive if=pflash,format=raw,readonly,file=OVMF_CODE.fd \ + -drive if=pflash,format=raw,file=fedora.varstore.fd + +This way qemu configures two flash chips consecutively, with start addresses +growing downwards, which is transparent to OVMF. + +[RHEL] Red Hat Enterprise Linux 7.1 ships a Secure Boot-enabled, X64, DEBUG + firmware only. Furthermore, only the split files ("OVMF_VARS.fd" and + "OVMF_CODE.fd") are available. + +S3 (suspend to RAM and resume) +------------------------------ + +As noted in Example qemu invocation, the + + -global PIIX4_PM.disable_s3=0 + +command line option tells qemu and OVMF if the user would like to enable S3 +support. (This is corresponds to the /domain/pm/suspend-to-mem/@enabled libvirt +domain XML attribute.) + +Implementing / orchestrating S3 was a considerable community effort in OVMF. A +detailed description exceeds the scope of this report; we only make a few +statements. + +(1) S3-related PPIs and protocols are well documented in the PI specification. + +(2) Edk2 contains most modules that are needed to implement S3 on a given + platform. One abstraction that is central to the porting / extending of the + S3-related modules to a new platform is the LockBox library interface, + which a specific platform can fill in by implementing its own LockBox + library instance. + + The LockBox library provides a privileged name-value store (to be addressed + by GUIDs). The privilege separation stretches between the firmware and the + operating system. That is, the S3-related machinery of the firmware saves + some items in the LockBox securely, under well-known GUIDs, before booting + the operating system. During resume (which is a form of warm reset), the + firmware is activated again, and retrieves items from the LockBox. Before + jumping to the OS's resume vector, the LockBox is secured again. + + We'll return to this later when we separately discuss SMRAM and SMM. + +(3) During resume, the DXE and later phases are never reached; only the reset + vector, and the SEC and PEI phases of the firmware run. The platform is + supposed to detect a resume in progress during PEI, and to store that fact + in the BootMode field of the Phase Handoff Information Table (PHIT) HOB. + OVMF keys this off the CMOS, see OvmfPkg/PlatformPei. + + At the end of PEI, the DXE IPL PEIM (Initial Program Load PEI Module, see + MdeModulePkg/Core/DxeIplPeim) examines the Boot Mode, and if it says "S3 + resume in progress", then the IPL branches to the PEIM that exports + EFI_PEI_S3_RESUME2_PPI (provided by UefiCpuPkg/Universal/Acpi/S3Resume2Pei) + rather than loading the DXE core. + + S3Resume2Pei executes the technical steps of the resumption, relying on the + contents of the LockBox. + +(4) During first boot (or after a normal platform reset), when DXE does run, + hardware drivers in the DXE phase are encouraged to "stash" their hardware + configuration steps (eg. accesses to PCI config space, I/O ports, memory + mapped addresses, and so on) in a centrally maintained, so called "S3 boot + script". Hardware accesses are represented with opcodes of a special binary + script language. + + This boot script is to be replayed during resume, by S3Resume2Pei. The + general goal is to bring back hardware devices -- which have been powered + off during suspend -- to their original after-first-boot state, and in + particular, to do so quickly. + + At the moment, OVMF saves only one opcode in the S3 resume boot script: an + INFORMATION opcode, with contents 0xDEADBEEF (in network byte order). The + consensus between Linux developers seems to be that boot firmware is only + responsible for restoring basic chipset state, which OVMF does during PEI + anyway, independently of S3 vs. normal reset. (One example is the power + management registers of the i440fx chipset.) Device and peripheral state is + the responsibility of the runtime operating system. + + Although an experimental OVMF S3 boot script was at one point captured for + the virtual Cirrus VGA card, such a boot script cannot follow eg. video + mode changes effected by the OS. Hence the operating system can never avoid + restoring device state, and most Linux display drivers (eg. stdvga, QXL) + already cover S3 resume fully. + + The XDDM and WDDM driver models used under Windows OSes seem to recognize + this notion of runtime OS responsibility as well. (See the list of OSes + supported by OVMF in a separate section.) + +(5) The S3 suspend/resume data flow in OVMF is included here tersely, for + interested developers. + + (a) BdsLibBootViaBootOption() + EFI_ACPI_S3_SAVE_PROTOCOL [AcpiS3SaveDxe] + - saves ACPI S3 Context to LockBox ---------------------+ + (including FACS address -- FACS ACPI table | + contains OS waking vector) | + | + - prepares boot script: | + EFI_S3_SAVE_STATE_PROTOCOL.Write() [S3SaveStateDxe] | + S3BootScriptLib [PiDxeS3BootScriptLib] | + - opcodes & arguments are saved in NVS. --+ | + | | + - issues a notification by installing | | + EFI_DXE_SMM_READY_TO_LOCK_PROTOCOL | | + | | + (b) EFI_S3_SAVE_STATE_PROTOCOL [S3SaveStateDxe] | | + S3BootScriptLib [PiDxeS3BootScriptLib] | | + - closes script with special opcode <---------+ | + - script is available in non-volatile memory | + via PcdS3BootScriptTablePrivateDataPtr --+ | + | | + BootScriptExecutorDxe | | + S3BootScriptLib [PiDxeS3BootScriptLib] | | + - Knows about boot script location by <----+ | + synchronizing with the other library | + instance via | + PcdS3BootScriptTablePrivateDataPtr. | + - Copies relocated image of itself to | + reserved memory. --------------------------------+ | + - Saved image contains pointer to boot script. ---|--+ | + | | | + Runtime: | | | + | | | + (c) OS is booted, writes OS waking vector to FACS, | | | + suspends machine | | | + | | | + S3 Resume (PEI): | | | + | | | + (d) PlatformPei sets S3 Boot Mode based on CMOS | | | + | | | + (e) DXE core is skipped and EFI_PEI_S3_RESUME2 is | | | + called as last step of PEI | | | + | | | + (f) S3Resume2Pei retrieves from LockBox: | | | + - ACPI S3 Context (path to FACS) <------------------|--|--+ + | | | + +------------------|--|--+ + - Boot Script Executor Image <----------------------+ | | + | | + (g) BootScriptExecutorDxe | | + S3BootScriptLib [PiDxeS3BootScriptLib] | | + - executes boot script <-----------------------------+ | + | + (h) OS waking vector available from ACPI S3 Context / FACS <--+ + is called + +A comprehensive memory map of OVMF +---------------------------------- + +The following section gives a detailed analysis of memory ranges below 4 GB +that OVMF statically uses. + +In the rightmost column, the PCD entry is identified by which the source refers +to the address or size in question. + +The flash-covered range has been discussed previously in "Firmware image +structure", therefore we include it only for completeness. Due to the fact that +this range is always backed by a memory mapped device (and never RAM), it is +unaffected by S3 (suspend to RAM and resume). + ++--------------------------+ 4194304 KB +| | +| SECFV | size: 208 KB +| | ++--------------------------+ 4194096 KB +| | +| FVMAIN_COMPACT | size: 1712 KB +| | ++--------------------------+ 4192384 KB +| | +| variable store | size: 64 KB PcdFlashNvStorageFtwSpareSize +| spare area | +| | ++--------------------------+ 4192320 KB PcdOvmfFlashNvStorageFtwSpareBase +| | +| FTW working block | size: 4 KB PcdFlashNvStorageFtwWorkingSize +| | ++--------------------------+ 4192316 KB PcdOvmfFlashNvStorageFtwWorkingBase +| | +| Event log of | size: 4 KB PcdOvmfFlashNvStorageEventLogSize +| non-volatile storage | +| | ++--------------------------+ 4192312 KB PcdOvmfFlashNvStorageEventLogBase +| | +| variable store | size: 56 KB PcdFlashNvStorageVariableSize +| | ++--------------------------+ 4192256 KB PcdOvmfFlashNvStorageVariableBase + +The flash-mapped image of OVMF.fd covers the entire structure above (2048 KB). + +When using the split files, the address 4192384 KB +(PcdOvmfFlashNvStorageFtwSpareBase + PcdFlashNvStorageFtwSpareSize) is the +boundary between the mapped images of OVMF_VARS.fd (56 KB + 4 KB + 4 KB + 64 KB += 128 KB) and OVMF_CODE.fd (1712 KB + 208 KB = 1920 KB). + +With regard to RAM that is statically used by OVMF, S3 (suspend to RAM and +resume) complicates matters. Many ranges have been introduced only to support +S3, hence for all ranges below, the following questions will be audited: + +(a) when and how a given range is initialized after first boot of the VM, +(b) how it is protected from memory allocations during DXE, +(c) how it is protected from the OS, +(d) how it is accessed on the S3 resume path, +(e) how it is accessed on the warm reset path. + +Importantly, the term "protected" is meant as protection against inadvertent +reallocations and overwrites by co-operating DXE and OS modules. It does not +imply security against malicious code. + ++--------------------------+ 17408 KB +| | +|DXEFV from FVMAIN_COMPACT | size: 8192 KB PcdOvmfDxeMemFvSize +| decompressed firmware | +| volume with DXE modules | +| | ++--------------------------+ 9216 KB PcdOvmfDxeMemFvBase +| | +|PEIFV from FVMAIN_COMPACT | size: 896 KB PcdOvmfPeiMemFvSize +| decompressed firmware | +| volume with PEI modules | +| | ++--------------------------+ 8320 KB PcdOvmfPeiMemFvBase +| | +| permanent PEI memory for | size: 32 KB PcdS3AcpiReservedMemorySize +| the S3 resume path | +| | ++--------------------------+ 8288 KB PcdS3AcpiReservedMemoryBase +| | +| temporary SEC/PEI heap | size: 32 KB PcdOvmfSecPeiTempRamSize +| and stack | +| | ++--------------------------+ 8256 KB PcdOvmfSecPeiTempRamBase +| | +| unused | size: 32 KB +| | ++--------------------------+ 8224 KB +| | +| SEC's table of | size: 4 KB PcdGuidedExtractHandlerTableSize +| GUIDed section handlers | +| | ++--------------------------+ 8220 KB PcdGuidedExtractHandlerTableAddress +| | +| LockBox storage | size: 4 KB PcdOvmfLockBoxStorageSize +| | ++--------------------------+ 8216 KB PcdOvmfLockBoxStorageBase +| | +| early page tables on X64 | size: 24 KB PcdOvmfSecPageTablesSize +| | ++--------------------------+ 8192 KB PcdOvmfSecPageTablesBase + +(1) Early page tables on X64: + + (a) when and how it is initialized after first boot of the VM + + The range is filled in during the SEC phase + [OvmfPkg/ResetVector/Ia32/PageTables64.asm]. The CR3 register is verified + against the base address in SecCoreStartupWithStack() + [OvmfPkg/Sec/SecMain.c]. + + (b) how it is protected from memory allocations during DXE + + If S3 was enabled on the QEMU command line (see "-global + PIIX4_PM.disable_s3=0" earlier), then InitializeRamRegions() + [OvmfPkg/PlatformPei/MemDetect.c] protects the range with an AcpiNVS memory + allocation HOB, in PEI. + + If S3 was disabled, then this range is not protected. DXE's own page tables + are first built while still in PEI (see HandOffToDxeCore() + [MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c]). Those tables are located + in permanent PEI memory. After CR3 is switched over to them (which occurs + before jumping to the DXE core entry point), we don't have to preserve the + initial tables. + + (c) how it is protected from the OS + + If S3 is enabled, then (1b) reserves it from the OS too. + + If S3 is disabled, then the range needs no protection. + + (d) how it is accessed on the S3 resume path + + It is rewritten same as in (1a), which is fine because (1c) reserved it. + + (e) how it is accessed on the warm reset path + + It is rewritten same as in (1a). + +(2) LockBox storage: + + (a) when and how it is initialized after first boot of the VM + + InitializeRamRegions() [OvmfPkg/PlatformPei/MemDetect.c] zeroes out the + area during PEI. This is correct but not strictly necessary, since on first + boot the area is zero-filled anyway. + + The LockBox signature of the area is filled in by the PEI module or DXE + driver that has been linked against OVMF's LockBoxLib and is run first. The + signature is written in LockBoxLibInitialize() + [OvmfPkg/Library/LockBoxLib/LockBoxLib.c]. + + Any module calling SaveLockBox() [OvmfPkg/Library/LockBoxLib/LockBoxLib.c] + will co-populate this area. + + (b) how it is protected from memory allocations during DXE + + If S3 is enabled, then InitializeRamRegions() + [OvmfPkg/PlatformPei/MemDetect.c] protects the range as AcpiNVS. + + Otherwise, the range is covered with a BootServicesData memory allocation + HOB. + + (c) how it is protected from the OS + + If S3 is enabled, then (2b) protects it sufficiently. + + Otherwise the range requires no runtime protection, and the + BootServicesData allocation type from (2b) ensures that the range will be + released to the OS. + + (d) how it is accessed on the S3 resume path + + The S3 Resume PEIM restores data from the LockBox, which has been correctly + protected in (2c). + + (e) how it is accessed on the warm reset path + + InitializeRamRegions() [OvmfPkg/PlatformPei/MemDetect.c] zeroes out the + range during PEI, effectively emptying the LockBox. Modules will + re-populate the LockBox as described in (2a). + +(3) SEC's table of GUIDed section handlers + + (a) when and how it is initialized after first boot of the VM + + The following two library instances are linked into SecMain: + - IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib, + - MdePkg/Library/BaseExtractGuidedSectionLib. + + The first library registers its LZMA decompressor plugin (which is a called + a "section handler") by calling the second library: + + LzmaDecompressLibConstructor() [GuidedSectionExtraction.c] + ExtractGuidedSectionRegisterHandlers() [BaseExtractGuidedSectionLib.c] + + The second library maintains its table of registered "section handlers", to + be indexed by GUID, in this fixed memory area, independently of S3 + enablement. + + (The decompression of FVMAIN_COMPACT's FFS file section that contains the + PEIFV and DXEFV firmware volumes occurs with the LZMA decompressor + registered above. See (6) and (7) below.) + + (b) how it is protected from memory allocations during DXE + + There is no need to protect this area from DXE: because nothing else in + OVMF links against BaseExtractGuidedSectionLib, the area loses its + significance as soon as OVMF progresses from SEC to PEI, therefore DXE is + allowed to overwrite the region. + + (c) how it is protected from the OS + + When S3 is enabled, we cover the range with an AcpiNVS memory allocation + HOB in InitializeRamRegions(). + + When S3 is disabled, the range is not protected. + + (d) how it is accessed on the S3 resume path + + The table of registered section handlers is again managed by + BaseExtractGuidedSectionLib linked into SecMain exclusively. Section + handler registrations update the table in-place (based on GUID matches). + + (e) how it is accessed on the warm reset path + + If S3 is enabled, then the OS won't damage the table (due to (3c)), thus + see (3d). + + If S3 is disabled, then the OS has most probably overwritten the range with + its own data, hence (3a) -- complete reinitialization -- will come into + effect, based on the table signature check in BaseExtractGuidedSectionLib. + +(4) temporary SEC/PEI heap and stack + + (a) when and how it is initialized after first boot of the VM + + The range is configured in [OvmfPkg/Sec/X64/SecEntry.S] and + SecCoreStartupWithStack() [OvmfPkg/Sec/SecMain.c]. The stack half is read & + written by the CPU transparently. The heap half is used for memory + allocations during PEI. + + Data is migrated out (to permanent PEI stack & memory) in (or soon after) + PublishPeiMemory() [OvmfPkg/PlatformPei/MemDetect.c]. + + (b) how it is protected from memory allocations during DXE + + It is not necessary to protect this range during DXE because its use ends + still in PEI. + + (c) how it is protected from the OS + + If S3 is enabled, then InitializeRamRegions() + [OvmfPkg/PlatformPei/MemDetect.c] reserves it as AcpiNVS. + + If S3 is disabled, then the range doesn't require protection. + + (d) how it is accessed on the S3 resume path + + Same as in (4a), except the target area of the migration triggered by + PublishPeiMemory() [OvmfPkg/PlatformPei/MemDetect.c] is different -- see + (5). + + (e) how it is accessed on the warm reset path + + Same as in (4a). The stack and heap halves both may contain garbage, but it + doesn't matter. + +(5) permanent PEI memory for the S3 resume path + + (a) when and how it is initialized after first boot of the VM + + No particular initialization or use. + + (b) how it is protected from memory allocations during DXE + + We don't need to protect this area during DXE. + + (c) how it is protected from the OS + + When S3 is enabled, InitializeRamRegions() + [OvmfPkg/PlatformPei/MemDetect.c] makes sure the OS stays away by covering + the range with an AcpiNVS memory allocation HOB. + + When S3 is disabled, the range needs no protection. + + (d) how it is accessed on the S3 resume path + + PublishPeiMemory() installs the range as permanent RAM for PEI. The range + will serve as stack and will satisfy allocation requests during the rest of + PEI. OS data won't overlap due to (5c). + + (e) how it is accessed on the warm reset path + + Same as (5a). + +(6) PEIFV -- decompressed firmware volume with PEI modules + + (a) when and how it is initialized after first boot of the VM + + DecompressMemFvs() [OvmfPkg/Sec/SecMain.c] populates the area, by + decompressing the flash-mapped FVMAIN_COMPACT volume's contents. (Refer to + "Firmware image structure".) + + (b) how it is protected from memory allocations during DXE + + When S3 is disabled, PeiFvInitialization() [OvmfPkg/PlatformPei/Fv.c] + covers the range with a BootServicesData memory allocation HOB. + + When S3 is enabled, the same is coverage is ensured, just with the stronger + AcpiNVS memory allocation type. + + (c) how it is protected from the OS + + When S3 is disabled, it is not necessary to keep the range from the OS. + + Otherwise the AcpiNVS type allocation from (6b) provides coverage. + + (d) how it is accessed on the S3 resume path + + Rather than decompressing it again from FVMAIN_COMPACT, GetS3ResumePeiFv() + [OvmfPkg/Sec/SecMain.c] reuses the protected area for parsing / execution + from (6c). + + (e) how it is accessed on the warm reset path + + Same as (6a). + +(7) DXEFV -- decompressed firmware volume with DXE modules + + (a) when and how it is initialized after first boot of the VM + + Same as (6a). + + (b) how it is protected from memory allocations during DXE + + PeiFvInitialization() [OvmfPkg/PlatformPei/Fv.c] covers the range with a + BootServicesData memory allocation HOB. + + (c) how it is protected from the OS + + The OS is allowed to release and reuse this range. + + (d) how it is accessed on the S3 resume path + + It's not; DXE never runs during S3 resume. + + (e) how it is accessed on the warm reset path + + Same as in (7a). + +Known Secure Boot limitations +----------------------------- + +Under "Motivation" we've mentioned that OVMF's Secure Boot implementation is +not suitable for production use yet -- it's only good for development and +testing of standards-conformant, non-malicious guest code (UEFI and operating +system alike). + +Now that we've examined the persistent flash device, the workings of S3, and +the memory map, we can discuss two currently known shortcomings of OVMF's +Secure Boot that in fact make it insecure. (Clearly problems other than these +two might exist; the set of issues considered here is not meant to be +exhaustive.) + +One trait of Secure Boot is tamper-evidence. Secure Boot may not prevent +malicious modification of software components (for example, operating system +drivers), but by being the root of integrity on a platform, it can catch (or +indirectly contribute to catching) unauthorized changes, by way of signature +and certificate checks at the earliest phases of boot. + +If an attacker can tamper with key material stored in authenticated and/or +boot-time only persistent variables (for example, PK, KEK, db, dbt, dbx), then +the intended security of this scheme is compromised. The UEFI 2.4A +specification says + +- in section 28.3.4: + + Platform Keys: + + The public key must be stored in non-volatile storage which is tamper and + delete resistant. + + Key Exchange Keys: + + The public key must be stored in non-volatile storage which is tamper + resistant. + +- in section 28.6.1: + + The signature database variables db, dbt, and dbx must be stored in + tamper-resistant non-volatile storage. + +(1) The combination of QEMU, KVM, and OVMF does not provide this kind of + resistance. The variable store in the emulated flash chip is directly + accessible to, and reprogrammable by, UEFI drivers, applications, and + operating systems. + +(2) Under "S3 (suspend to RAM and resume)" we pointed out that the LockBox + storage must be similarly secure and tamper-resistant. + + On the S3 resume path, the PEIM providing EFI_PEI_S3_RESUME2_PPI + (UefiCpuPkg/Universal/Acpi/S3Resume2Pei) restores and interprets data from + the LockBox that has been saved there during boot. This PEIM, being part of + the firmware, has full access to the platform. If an operating system can + tamper with the contents of the LockBox, then at the next resume the + platform's integrity might be subverted. + + OVMF stores the LockBox in normal guest RAM (refer to the memory map + section above). Operating systems and third party UEFI drivers and UEFI + applications that respect the UEFI memory map will not inadvertently + overwrite the LockBox storage, but there's nothing to prevent eg. a + malicious kernel from modifying the LockBox. + +One means to address these issues is SMM and SMRAM (System Management Mode and +System Management RAM). + +During boot and resume, the firmware can enter and leave SMM and access SMRAM. +Before the DXE phase is left, and control is transferred to the BDS phase (when +third party UEFI drivers and applications can be loaded, and an operating +system can be loaded), SMRAM is locked in hardware, and subsequent modules +cannot access it directly. (See EFI_DXE_SMM_READY_TO_LOCK_PROTOCOL.) + +Once SMRAM has been locked, UEFI drivers and the operating system can enter SMM +by raising a System Management Interrupt (SMI), at which point trusted code +(part of the platform firmware) takes control. SMRAM is also unlocked by +platform reset, at which point the boot firmware takes control again. + +Variable store and LockBox in SMRAM +----------------------------------- + +Edk2 provides almost all components to implement the variable store and the +LockBox in SMRAM. In this section we summarize ideas for utilizing those +facilities. + +The SMRAM and SMM infrastructure in edk2 is built up as follows: + +(1) The platform hardware provides SMM / SMI / SMRAM. + + Qemu/KVM doesn't support these features currently and should implement them + in the longer term. + +(2) The platform vendor (in this case, OVMF developers) implement device + drivers for the platform's System Management Mode: + + - EFI_SMM_CONTROL2_PROTOCOL: for raising a synchronous (and/or) periodic + SMI(s); that is, for entering SMM. + + - EFI_SMM_ACCESS2_PROTOCOL: for describing and accessing SMRAM. + + These protocols are documented in the PI Specification, Volume 4. + +(3) The platform DSC file is to include the following platform-independent + modules: + + - MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf: SMM Initial Program Load + - MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf: SMM Core + +(4) At this point, modules of type DXE_SMM_DRIVER can be loaded. + + Such drivers are privileged. They run in SMM, have access to SMRAM, and are + separated and switched from other drivers through SMIs. Secure + communication between unprivileged (non-SMM) and privileged (SMM) drivers + happens through EFI_SMM_COMMUNICATION_PROTOCOL (implemented by the SMM + Core, see (3)). + + DXE_SMM_DRIVER modules must sanitize their input (coming from unprivileged + drivers) carefully. + +(5) The authenticated runtime variable services driver (for Secure Boot builds) + is located under "SecurityPkg/VariableAuthenticated/RuntimeDxe". OVMF + currently builds the driver (a DXE_RUNTIME_DRIVER module) with the + "VariableRuntimeDxe.inf" control file (refer to "OvmfPkg/OvmfPkgX64.dsc"), + which does not use SMM. + + The directory includes two more INF files: + + - VariableSmm.inf -- module type: DXE_SMM_DRIVER. A privileged driver that + runs in SMM and has access to SMRAM. + + - VariableSmmRuntimeDxe.inf -- module type: DXE_RUNTIME_DRIVER. A + non-privileged driver that implements the variable runtime services + (replacing the current "VariableRuntimeDxe.inf" file) by communicating + with the above privileged SMM half via EFI_SMM_COMMUNICATION_PROTOCOL. + +(6) An SMRAM-based LockBox implementation needs to be discussed in two parts, + because the LockBox is accessed in both PEI and DXE. + + (a) During DXE, drivers save data in the LockBox. A save operation is + layered as follows: + + - The unprivileged driver wishing to store data in the LockBox links + against the "MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf" + library instance. + + The library allows the unprivileged driver to format requests for the + privileged SMM LockBox driver (see below), and to parse responses. + + - The privileged SMM LockBox driver is built from + "MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf". This + driver has module type DXE_SMM_DRIVER and can access SMRAM. + + The driver delegates command parsing and response formatting to + "MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf". + + - The above two halves (unprivileged and privileged) mirror what we've + seen in case of the variable service drivers, under (5). + + (b) In PEI, the S3 Resume PEIM (UefiCpuPkg/Universal/Acpi/S3Resume2Pei) + retrieves data from the LockBox. + + Presumably, S3Resume2Pei should be considered an "unprivileged PEIM", + and the SMRAM access should be layered as seen in DXE. Unfortunately, + edk2 does not implement all of the layers in PEI -- the code either + doesn't exist, or it is not open source: + + role | DXE: protocol/module | PEI: PPI/module + -------------+--------------------------------+------------------------------ + unprivileged | any | S3Resume2Pei.inf + driver | | + -------------+--------------------------------+------------------------------ + command | LIBRARY_CLASS = LockBoxLib | LIBRARY_CLASS = LockBoxLib + formatting | | + and response | SmmLockBoxDxeLib.inf | SmmLockBoxPeiLib.inf + parsing | | + -------------+--------------------------------+------------------------------ + privilege | EFI_SMM_COMMUNICATION_PROTOCOL | EFI_PEI_SMM_COMMUNICATION_PPI + separation | | + | PiSmmCore.inf | missing! + -------------+--------------------------------+------------------------------ + platform SMM | EFI_SMM_CONTROL2_PROTOCOL | PEI_SMM_CONTROL_PPI + and SMRAM | EFI_SMM_ACCESS2_PROTOCOL | PEI_SMM_ACCESS_PPI + access | | + | to be done in OVMF | to be done in OVMF + -------------+--------------------------------+------------------------------ + command | LIBRARY_CLASS = LockBoxLib | LIBRARY_CLASS = LockBoxLib + parsing and | | + response | SmmLockBoxSmmLib.inf | missing! + formatting | | + -------------+--------------------------------+------------------------------ + privileged | SmmLockBox.inf | missing! + LockBox | | + driver | | + + Alternatively, in the future OVMF might be able to provide a LockBoxLib + instance (an SmmLockBoxPeiLib substitute) for S3Resume2Pei that + accesses SMRAM directly, eliminating the need for deeper layers in the + stack (that is, EFI_PEI_SMM_COMMUNICATION_PPI and deeper). + + In fact, a "thin" EFI_PEI_SMM_COMMUNICATION_PPI implementation whose + sole Communicate() member invariably returns EFI_NOT_STARTED would + cause the current SmmLockBoxPeiLib library instance to directly perform + full-depth SMRAM access and LockBox search, obviating the "missing" + cells. (With reference to A Tour Beyond BIOS: Implementing S3 Resume + with EDK2, by Jiewen Yao and Vincent Zimmer, October 2014.) + +Select features +--------------- + +In this section we'll browse the top-level "OvmfPkg" package directory, and +discuss the more interesting drivers and libraries that have not been mentioned +thus far. + +X64-specific reset vector for OVMF +.................................. + +The "OvmfPkg/ResetVector" directory customizes the reset vector (found in +"UefiCpuPkg/ResetVector/Vtf0") for "OvmfPkgX64.fdf", that is, when the SEC/PEI +phases run in 64-bit (ie. long) mode. + +The reset vector's control flow looks roughly like: + + resetVector [Ia16/ResetVectorVtf0.asm] + EarlyBspInitReal16 [Ia16/Init16.asm] + Main16 [Main.asm] + EarlyInit16 [Ia16/Init16.asm] + + ; Transition the processor from + ; 16-bit real mode to 32-bit flat mode + TransitionFromReal16To32BitFlat [Ia16/Real16ToFlat32.asm] + + ; Search for the + ; Boot Firmware Volume (BFV) + Flat32SearchForBfvBase [Ia32/SearchForBfvBase.asm] + + ; Search for the SEC entry point + Flat32SearchForSecEntryPoint [Ia32/SearchForSecEntry.asm] + + %ifdef ARCH_IA32 + ; Jump to the 32-bit SEC entry point + %else + ; Transition the processor + ; from 32-bit flat mode + ; to 64-bit flat mode + Transition32FlatTo64Flat [Ia32/Flat32ToFlat64.asm] + + SetCr3ForPageTables64 [Ia32/PageTables64.asm] + ; set CR3 to page tables + ; built into the ROM image + + ; enable PAE + ; set LME + ; enable paging + + ; Jump to the 64-bit SEC entry point + %endif + +On physical platforms, the initial page tables referenced by +SetCr3ForPageTables64 are built statically into the flash device image, and are +present in ROM at runtime. This is fine on physical platforms because the +pre-built page table entries have the Accessed and Dirty bits set from the +start. + +Accordingly, for OVMF running in long mode on qemu/KVM, the initial page tables +were mapped as a KVM_MEM_READONLY slot, as part of QEMU's pflash device (refer +to "Firmware image structure" above). + +In spite of the Accessed and Dirty bits being pre-set in the read-only, +in-flash PTEs, in a virtual machine attempts are made to update said PTE bits, +differently from physical hardware. The component attempting to update the +read-only PTEs can be one of the following: + +- The processor itself, if it supports nested paging, and the user enables that + processor feature, + +- KVM code implementing shadow paging, otherwise. + +The first case presents no user-visible symptoms, but the second case (KVM, +shadow paging) used to cause a triple fault, prior to Linux commit ba6a354 +("KVM: mmu: allow page tables to be in read-only slots"). + +For compatibility with earlier KVM versions, the OvmfPkg/ResetVector directory +adapts the generic reset vector code as follows: + + Transition32FlatTo64Flat [UefiCpuPkg/.../Ia32/Flat32ToFlat64.asm] + + SetCr3ForPageTables64 [OvmfPkg/ResetVector/Ia32/PageTables64.asm] + + ; dynamically build the initial page tables in RAM, at address + ; PcdOvmfSecPageTablesBase (refer to the memory map above), + ; identity-mapping the first 4 GB of address space + + ; set CR3 to PcdOvmfSecPageTablesBase + + ; enable PAE + ; set LME + ; enable paging + +This way the PTEs that earlier KVM versions try to update (during shadow +paging) are located in a read-write memory slot, and the write attempts +succeed. + +Client library for QEMU's firmware configuration interface +.......................................................... + +QEMU provides a write-only, 16-bit wide control port, and a read-write, 8-bit +wide data port for exchanging configuration elements with the firmware. + +The firmware writes a selector (a key) to the control port (0x510), and then +reads the corresponding configuration data (produced by QEMU) from the data +port (0x511). + +If the selected entry is writable, the firmware may overwrite it. If QEMU has +associated a callback with the entry, then when the entry is completely +rewritten, QEMU runs the callback. (OVMF does not rewrite any entries at the +moment.) + +A number of selector values (keys) are predefined. In particular, key 0x19 +selects (returns) a directory of { name, selector, size } triplets, roughly +speaking. + +The firmware can request configuration elements by well-known name as well, by +looking up the selector value first in the directory, by name, and then writing +the selector to the control port. The number of bytes to read subsequently from +the data port is known from the directory entry's "size" field. + +By convention, directory entries (well-known symbolic names of configuration +elements) are formatted as POSIX pathnames. For example, the array selected by +the "etc/system-states" name indicates (among other things) whether the user +enabled S3 support in QEMU. + +The above interface is called "fw_cfg". + +The binary data associated with a symbolic name is called an "fw_cfg file". + +OVMF's fw_cfg client library is found in "OvmfPkg/Library/QemuFwCfgLib". OVMF +discovers many aspects of the virtual system with it; we refer to a few +examples below. + +Guest ACPI tables +................. + +An operating system discovers a good amount of its hardware by parsing ACPI +tables, and by interpreting ACPI objects and methods. On physical hardware, the +platform vendor's firmware installs ACPI tables in memory that match both the +hardware present in the system and the user's firmware configuration ("BIOS +setup"). + +Under qemu/KVM, the owner of the (virtual) hardware configuration is QEMU. +Hardware can easily be reconfigured on the command line. Furthermore, features +like CPU hotplug, PCI hotplug, memory hotplug are continuously developed for +QEMU, and operating systems need direct ACPI support to exploit these features. + +For this reason, QEMU builds its own ACPI tables dynamically, in a +self-descriptive manner, and exports them to the firmware through a complex, +multi-file fw_cfg interface. It is rooted in the "etc/table-loader" fw_cfg +file. (Further details of this interface are out of scope for this report.) + +OVMF's AcpiPlatformDxe driver fetches the ACPI tables, and installs them for +the guest OS with the EFI_ACPI_TABLE_PROTOCOL (which is in turn provided by the +generic "MdeModulePkg/Universal/Acpi/AcpiTableDxe" driver). + +For earlier QEMU versions and machine types (which we generally don't recommend +for OVMF; see "Scope"), the "OvmfPkg/AcpiTables" directory contains a few +static ACPI table templates. When the "etc/table-loader" fw_cfg file is +unavailable, AcpiPlatformDxe installs these default tables (with a little bit +of dynamic patching). + +When OVMF runs in a Xen domU, AcpiTableDxe also installs ACPI tables that +originate from the hypervisor's environment. + +Guest SMBIOS tables +................... + +Quoting the SMBIOS Reference Specification, + + [...] the System Management BIOS Reference Specification addresses how + motherboard and system vendors present management information about their + products in a standard format [...] + +In practice SMBIOS tables are just another set of tables that the platform +vendor's firmware installs in RAM for the operating system, and, importantly, +for management applications running on the OS. Without rehashing the "Guest +ACPI tables" section in full, let's map the OVMF roles seen there from ACPI to +SMBIOS: + + role | ACPI | SMBIOS + -------------------------+-------------------------+------------------------- + fw_cfg file | etc/table-loader | etc/smbios/smbios-tables + -------------------------+-------------------------+------------------------- + OVMF driver | AcpiPlatformDxe | SmbiosPlatformDxe + under "OvmfPkg" | | + -------------------------+-------------------------+------------------------- + Underlying protocol, | EFI_ACPI_TABLE_PROTOCOL | EFI_SMBIOS_PROTOCOL + implemented by generic | | + driver under | Acpi/AcpiTableDxe | SmbiosDxe + "MdeModulePkg/Universal" | | + -------------------------+-------------------------+------------------------- + default tables available | yes | [RHEL] yes, Type0 and + for earlier QEMU machine | | Type1 tables + types, with hot-patching | | + -------------------------+-------------------------+------------------------- + tables fetched in Xen | yes | yes + domUs | | + +Platform-specific boot policy +............................. + +OVMF's BDS (Boot Device Selection) phase is implemented by +IntelFrameworkModulePkg/Universal/BdsDxe. Roughly speaking, this large driver: + +- provides the EFI BDS architectural protocol (which DXE transfers control to + after dispatching all DXE drivers), + +- connects drivers to devices, + +- enumerates boot devices, + +- auto-generates boot options, + +- provides "BIOS setup" screens, such as: + + - Boot Manager, for booting an option, + + - Boot Maintenance Manager, for adding, deleting, and reordering boot + options, changing console properties etc, + + - Device Manager, where devices can register configuration forms, including + + - Secure Boot configuration forms, + + - OVMF's Platform Driver form (see under PlatformDxe). + +Firmware that includes the "IntelFrameworkModulePkg/Universal/BdsDxe" driver +can customize its behavior by providing an instance of the PlatformBdsLib +library class. The driver links against this platform library, and the +platform library can call Intel's BDS utility functions from +"IntelFrameworkModulePkg/Library/GenericBdsLib". + +OVMF's PlatformBdsLib instance can be found in +"OvmfPkg/Library/PlatformBdsLib". The main function where the BdsDxe driver +enters the library is PlatformBdsPolicyBehavior(). We mention two OVMF +particulars here. + +(1) OVMF is capable of loading kernel images directly from fw_cfg, matching + QEMU's -kernel, -initrd, and -append command line options. This feature is + useful for rapid, repeated Linux kernel testing, and is implemented in the + following call tree: + + PlatformBdsPolicyBehavior() [OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c] + TryRunningQemuKernel() [OvmfPkg/Library/PlatformBdsLib/QemuKernel.c] + LoadLinux*() [OvmfPkg/Library/LoadLinuxLib/Linux.c] + + OvmfPkg/Library/LoadLinuxLib ports the efilinux bootloader project into + OvmfPkg. + +(2) OVMF seeks to comply with the boot order specification passed down by QEMU + over fw_cfg. + + (a) About Boot Modes + + During the PEI phase, OVMF determines and stores the Boot Mode in the + PHIT HOB (already mentioned in "S3 (suspend to RAM and resume)"). The + boot mode is supposed to influence the rest of the system, for example it + distinguishes S3 resume (BOOT_ON_S3_RESUME) from a "normal" boot. + + In general, "normal" boots can be further differentiated from each other; + for example for speed reasons. When the firmware can tell during PEI that + the chassis has not been opened since last power-up, then it might want + to save time by not connecting all devices and not enumerating all boot + options from scratch; it could just rely on the stored results of the + last enumeration. The matching BootMode value, to be set during PEI, + would be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES. + + OVMF only sets one of the following two boot modes, based on CMOS + contents: + - BOOT_ON_S3_RESUME, + - BOOT_WITH_FULL_CONFIGURATION. + + For BOOT_ON_S3_RESUME, please refer to "S3 (suspend to RAM and resume)". + The other boot mode supported by OVMF, BOOT_WITH_FULL_CONFIGURATION, is + an appropriate "catch-all" for a virtual machine, where hardware can + easily change from boot to boot. + + (b) Auto-generation of boot options + + Accordingly, when not resuming from S3 sleep (*), OVMF always connects + all devices, and enumerates all bootable devices as new boot options + (non-volatile variables called Boot####). + + (*) During S3 resume, DXE is not reached, hence BDS isn't either. + + The auto-enumerated boot options are stored in the BootOrder non-volatile + variable after any preexistent options. (Boot options may exist before + auto-enumeration eg. because the user added them manually with the Boot + Maintenance Manager or the efibootmgr utility. They could also originate + from an earlier auto-enumeration.) + + PlatformBdsPolicyBehavior() [OvmfPkg/.../BdsPlatform.c] + TryRunningQemuKernel() [OvmfPkg/.../QemuKernel.c] + BdsLibConnectAll() [IntelFrameworkModulePkg/.../BdsConnect.c] + BdsLibEnumerateAllBootOption() [IntelFrameworkModulePkg/.../BdsBoot.c] + BdsLibBuildOptionFromHandle() [IntelFrameworkModulePkg/.../BdsBoot.c] + BdsLibRegisterNewOption() [IntelFrameworkModulePkg/.../BdsMisc.c] + // + // Append the new option number to the original option order + // + + (c) Relative UEFI device paths in boot options + + The handling of relative ("short-form") UEFI device paths is best + demonstrated through an example, and by quoting the UEFI 2.4A + specification. + + A short-form hard drive UEFI device path could be (displaying each device + path node on a separate line for readability): + + HD(1,GPT,14DD1CC5-D576-4BBF-8858-BAF877C8DF61,0x800,0x64000)/ + \EFI\fedora\shim.efi + + This device path lacks prefix nodes (eg. hardware or messaging type + nodes) that would lead to the hard drive. During load option processing, + the above short-form or relative device path could be matched against the + following absolute device path: + + PciRoot(0x0)/ + Pci(0x4,0x0)/ + HD(1,GPT,14DD1CC5-D576-4BBF-8858-BAF877C8DF61,0x800,0x64000)/ + \EFI\fedora\shim.efi + + The motivation for this type of device path matching / completion is to + allow the user to move around the hard drive (for example, to plug a + controller in a different PCI slot, or to expose the block device on a + different iSCSI path) and still enable the firmware to find the hard + drive. + + The UEFI specification says, + + 9.3.6 Media Device Path + 9.3.6.1 Hard Drive + + [...] Section 3.1.2 defines special rules for processing the Hard + Drive Media Device Path. These special rules enable a disk's location + to change and still have the system boot from the disk. [...] + + 3.1.2 Load Option Processing + + [...] The boot manager must [...] support booting from a short-form + device path that starts with the first element being a hard drive + media device path [...]. The boot manager must use the GUID or + signature and partition number in the hard drive device path to match + it to a device in the system. If the drive supports the GPT + partitioning scheme the GUID in the hard drive media device path is + compared with the UniquePartitionGuid field of the GUID Partition + Entry [...]. If the drive supports the PC-AT MBR scheme the signature + in the hard drive media device path is compared with the + UniqueMBRSignature in the Legacy Master Boot Record [...]. If a + signature match is made, then the partition number must also be + matched. The hard drive device path can be appended to the matching + hardware device path and normal boot behavior can then be used. If + more than one device matches the hard drive device path, the boot + manager will pick one arbitrarily. Thus the operating system must + ensure the uniqueness of the signatures on hard drives to guarantee + deterministic boot behavior. + + Edk2 implements and exposes the device path completion logic in the + already referenced "IntelFrameworkModulePkg/Library/GenericBdsLib" + library, in the BdsExpandPartitionPartialDevicePathToFull() function. + + (d) Filtering and reordering the boot options based on fw_cfg + + Once we have an "all-inclusive", partly preexistent, partly freshly + auto-generated boot option list from bullet (b), OVMF loads QEMU's + requested boot order from fw_cfg, and filters and reorders the list from + (b) with it: + + PlatformBdsPolicyBehavior() [OvmfPkg/.../BdsPlatform.c] + TryRunningQemuKernel() [OvmfPkg/.../QemuKernel.c] + BdsLibConnectAll() [IntelFrameworkModulePkg/.../BdsConnect.c] + BdsLibEnumerateAllBootOption() [IntelFrameworkModulePkg/.../BdsBoot.c] + SetBootOrderFromQemu() [OvmfPkg/.../QemuBootOrder.c] + + According to the (preferred) "-device ...,bootindex=N" and the (legacy) + '-boot order=drives' command line options, QEMU requests a boot order + from the firmware through the "bootorder" fw_cfg file. (For a bootindex + example, refer to the "Example qemu invocation" section.) + + This fw_cfg file consists of OpenFirmware (OFW) device paths -- note: not + UEFI device paths! --, one per line. An example list is: + + /pci@i0cf8/scsi@4/disk@0,0 + /pci@i0cf8/ide@1,1/drive@1/disk@0 + /pci@i0cf8/ethernet@3/ethernet-phy@0 + + OVMF filters and reorders the boot option list from bullet (b) with the + following nested loops algorithm: + + new_uefi_order := + for each qemu_ofw_path in QEMU's OpenFirmware device path list: + qemu_uefi_path_prefix := translate(qemu_ofw_path) + + for each boot_option in current_uefi_order: + full_boot_option := complete(boot_option) + + if match(qemu_uefi_path_prefix, full_boot_option): + append(new_uefi_order, boot_option) + break + + for each unmatched boot_option in current_uefi_order: + if survives(boot_option): + append(new_uefi_order, boot_option) + + current_uefi_order := new_uefi_order + + OVMF iterates over QEMU's OFW device paths in order, translates each to a + UEFI device path prefix, tries to match the translated prefix against the + UEFI boot options (which are completed from relative form to absolute + form for the purpose of prefix matching), and if there's a match, the + matching boot option is appended to the new boot order (which starts out + empty). + + (We elaborate on the translate() function under bullet (e). The + complete() function has been explained in bullet (c).) + + In addition, UEFI boot options that remain unmatched after filtering and + reordering are post-processed, and some of them "survive". Due to the + fact that OpenFirmware device paths have less expressive power than their + UEFI counterparts, some UEFI boot options are simply inexpressible (hence + unmatchable) by the nested loops algorithm. + + An important example is the memory-mapped UEFI shell, whose UEFI device + path is inexpressible by QEMU's OFW device paths: + + MemoryMapped(0xB,0x900000,0x10FFFFF)/ + FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1) + + (Side remark: notice that the address range visible in the MemoryMapped() + node corresponds to DXEFV under "comprehensive memory map of OVMF"! In + addition, the FvFile() node's GUID originates from the FILE_GUID entry of + "ShellPkg/Application/Shell/Shell.inf".) + + The UEFI shell can be booted by pressing ESC in OVMF on the TianoCore + splash screen, and navigating to Boot Manager | EFI Internal Shell. If + the "survival policy" was not implemented, the UEFI shell's boot option + would always be filtered out. + + The current "survival policy" preserves all boot options that start with + neither PciRoot() nor HD(). + + (e) Translating QEMU's OpenFirmware device paths to UEFI device path + prefixes + + In this section we list the (strictly heuristical) mappings currently + performed by OVMF. + + The "prefix only" nature of the translation output is rooted minimally in + the fact that QEMU's OpenFirmware device paths cannot carry pathnames + within filesystems. There's no way to specify eg. + + \EFI\fedora\shim.efi + + in an OFW device path, therefore a UEFI device path translated from an + OFW device path can at best be a prefix (not a full match) of a UEFI + device path that ends with "\EFI\fedora\shim.efi". + + - IDE disk, IDE CD-ROM: + + OpenFirmware device path: + + /pci@i0cf8/ide@1,1/drive@0/disk@0 + ^ ^ ^ ^ ^ + | | | | master or slave + | | | primary or secondary + | PCI slot & function holding IDE controller + PCI root at system bus port, PIO + + UEFI device path prefix: + + PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0) + ^ + fixed LUN + + - Floppy disk: + + OpenFirmware device path: + + /pci@i0cf8/isa@1/fdc@03f0/floppy@0 + ^ ^ ^ ^ + | | | A: or B: + | | ISA controller io-port (hex) + | PCI slot holding ISA controller + PCI root at system bus port, PIO + + UEFI device path prefix: + + PciRoot(0x0)/Pci(0x1,0x0)/Floppy(0x0) + ^ + ACPI UID (A: or B:) + + - Virtio-block disk: + + OpenFirmware device path: + + /pci@i0cf8/scsi@6[,3]/disk@0,0 + ^ ^ ^ ^ ^ + | | | fixed + | | PCI function corresponding to disk (optional) + | PCI slot holding disk + PCI root at system bus port, PIO + + UEFI device path prefixes (dependent on the presence of a nonzero PCI + function in the OFW device path): + + PciRoot(0x0)/Pci(0x6,0x0)/HD( + PciRoot(0x0)/Pci(0x6,0x3)/HD( + + - Virtio-scsi disk and virtio-scsi passthrough: + + OpenFirmware device path: + + /pci@i0cf8/scsi@7[,3]/channel@0/disk@2,3 + ^ ^ ^ ^ ^ + | | | | LUN + | | | target + | | channel (unused, fixed 0) + | PCI slot[, function] holding SCSI controller + PCI root at system bus port, PIO + + UEFI device path prefixes (dependent on the presence of a nonzero PCI + function in the OFW device path): + + PciRoot(0x0)/Pci(0x7,0x0)/Scsi(0x2,0x3) + PciRoot(0x0)/Pci(0x7,0x3)/Scsi(0x2,0x3) + + - Emulated and passed-through (physical) network cards: + + OpenFirmware device path: + + /pci@i0cf8/ethernet@3[,2] + ^ ^ + | PCI slot[, function] holding Ethernet card + PCI root at system bus port, PIO + + UEFI device path prefixes (dependent on the presence of a nonzero PCI + function in the OFW device path): + + PciRoot(0x0)/Pci(0x3,0x0) + PciRoot(0x0)/Pci(0x3,0x2) + +Virtio drivers +.............. + +UEFI abstracts various types of hardware resources into protocols, and allows +firmware developers to implement those protocols in device drivers. The Virtio +Specification defines various types of virtual hardware for virtual machines. +Connecting the two specifications, OVMF provides UEFI drivers for QEMU's +virtio-block, virtio-scsi, and virtio-net devices. + +The following diagram presents the protocol and driver stack related to Virtio +devices in edk2 and OVMF. Each node in the graph identifies a protocol and/or +the edk2 driver that produces it. Nodes on the top are more abstract. + + EFI_BLOCK_IO_PROTOCOL EFI_SIMPLE_NETWORK_PROTOCOL + [OvmfPkg/VirtioBlkDxe] [OvmfPkg/VirtioNetDxe] + | | + | EFI_EXT_SCSI_PASS_THRU_PROTOCOL | + | [OvmfPkg/VirtioScsiDxe] | + | | | + +------------------------+--------------------------+ + | + VIRTIO_DEVICE_PROTOCOL + | + +---------------------+---------------------+ + | | + [OvmfPkg/VirtioPciDeviceDxe] [custom platform drivers] + | | + | | + EFI_PCI_IO_PROTOCOL [OvmfPkg/Library/VirtioMmioDeviceLib] + [MdeModulePkg/Bus/Pci/PciBusDxe] direct MMIO register access + +The top three drivers produce standard UEFI abstractions: the Block IO +Protocol, the Extended SCSI Pass Thru Protocol, and the Simple Network +Protocol, for virtio-block, virtio-scsi, and virtio-net devices, respectively. + +Comparing these device-specific virtio drivers to each other, we can determine: + +- They all conform to the UEFI Driver Model. This means that their entry point + functions don't immediately start to search for devices and to drive them, + they only register instances of the EFI_DRIVER_BINDING_PROTOCOL. The UEFI + Driver Model then enumerates devices and chains matching drivers + automatically. + +- They are as minimal as possible, while remaining correct (refer to source + code comments for details). For example, VirtioBlkDxe and VirtioScsiDxe both + support only one request in flight. + + In theory, VirtioBlkDxe could implement EFI_BLOCK_IO2_PROTOCOL, which allows + queueing. Similarly, VirtioScsiDxe does not support the non-blocking mode of + EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru(). (Which is permitted by the UEFI + specification.) Both VirtioBlkDxe and VirtioScsiDxe delegate synchronous + request handling to "OvmfPkg/Library/VirtioLib". This limitation helps keep + the implementation simple, and testing thus far seems to imply satisfactory + performance, for a virtual boot firmware. + + VirtioNetDxe cannot avoid queueing, because EFI_SIMPLE_NETWORK_PROTOCOL + requires it on the interface level. Consequently, VirtioNetDxe is + significantly more complex than VirtioBlkDxe and VirtioScsiDxe. Technical + notes are provided in "OvmfPkg/VirtioNetDxe/TechNotes.txt". + +- None of these drivers access hardware directly. Instead, the Virtio Device + Protocol (OvmfPkg/Include/Protocol/VirtioDevice.h) collects / extracts virtio + operations defined in the Virtio Specification, and these backend-independent + virtio device drivers go through the abstract VIRTIO_DEVICE_PROTOCOL. + + IMPORTANT: the VIRTIO_DEVICE_PROTOCOL is not a standard UEFI protocol. It is + internal to edk2 and not described in the UEFI specification. It should only + be used by drivers and applications that live inside the edk2 source tree. + +Currently two providers exist for VIRTIO_DEVICE_PROTOCOL: + +- The first one is the "more traditional" virtio-pci backend, implemented by + OvmfPkg/VirtioPciDeviceDxe. This driver also complies with the UEFI Driver + Model. It consumes an instance of the EFI_PCI_IO_PROTOCOL, and, if the PCI + device/function under probing appears to be a virtio device, it produces a + Virtio Device Protocol instance for it. The driver translates abstract virtio + operations to PCI accesses. + +- The second provider, the virtio-mmio backend, is a library, not a driver, + living in OvmfPkg/Library/VirtioMmioDeviceLib. This library translates + abstract virtio operations to MMIO accesses. + + The virtio-mmio backend is only a library -- rather than a standalone, UEFI + Driver Model-compliant driver -- because the type of resource it consumes, an + MMIO register block base address, is not enumerable. + + In other words, while the PCI root bridge driver and the PCI bus driver + produce instances of EFI_PCI_IO_PROTOCOL automatically, thereby enabling the + UEFI Driver Model to probe devices and stack up drivers automatically, no + such enumeration exists for MMIO register blocks. + + For this reason, VirtioMmioDeviceLib needs to be linked into thin, custom + platform drivers that dispose over this kind of information. As soon as a + driver knows about the MMIO register block base addresses, it can pass each + to the library, and then the VIRTIO_DEVICE_PROTOCOL will be instantiated + (assuming a valid virtio-mmio register block of course). From that point on + the UEFI Driver Model again takes care of the chaining. + + Typically, such a custom driver does not conform to the UEFI Driver Model + (because that would presuppose auto-enumeration for MMIO register blocks). + Hence it has the following responsibilities: + + - it shall behave as a "wrapper" UEFI driver around the library, + + - it shall know virtio-mmio base addresses, + + - in its entry point function, it shall create a new UEFI handle with an + instance of the EFI_DEVICE_PATH_PROTOCOL for each virtio-mmio device it + knows the base address for, + + - it shall call VirtioMmioInstallDevice() on those handles, with the + corresponding base addresses. + + OVMF itself does not employ VirtioMmioDeviceLib. However, the library is used + (or has been tested as Proof-of-Concept) in the following 64-bit and 32-bit + ARM emulator setups: + + - in "RTSM_VE_FOUNDATIONV8_EFI.fd" and "FVP_AARCH64_EFI.fd", on ARM Holdings' + ARM(R) v8-A Foundation Model and ARM(R) AEMv8-A Base Platform FVP + emulators, respectively: + + EFI_BLOCK_IO_PROTOCOL + [OvmfPkg/VirtioBlkDxe] + | + VIRTIO_DEVICE_PROTOCOL + [ArmPlatformPkg/ArmVExpressPkg/ArmVExpressDxe/ArmFvpDxe.inf] + | + [OvmfPkg/Library/VirtioMmioDeviceLib] + direct MMIO register access + + - in "RTSM_VE_CORTEX-A15_EFI.fd" and "RTSM_VE_CORTEX-A15_MPCORE_EFI.fd", on + "qemu-system-arm -M vexpress-a15": + + EFI_BLOCK_IO_PROTOCOL EFI_SIMPLE_NETWORK_PROTOCOL + [OvmfPkg/VirtioBlkDxe] [OvmfPkg/VirtioNetDxe] + | | + +------------------+---------------+ + | + VIRTIO_DEVICE_PROTOCOL + [ArmPlatformPkg/ArmVExpressPkg/ArmVExpressDxe/ArmFvpDxe.inf] + | + [OvmfPkg/Library/VirtioMmioDeviceLib] + direct MMIO register access + + In the above ARM / VirtioMmioDeviceLib configurations, VirtioBlkDxe was + tested with booting Linux distributions, while VirtioNetDxe was tested with + pinging public IPv4 addresses from the UEFI shell. + +Platform Driver +............... + +Sometimes, elements of persistent firmware configuration are best exposed to +the user in a friendly way. OVMF's platform driver (OvmfPkg/PlatformDxe) +presents such settings on the "OVMF Platform Configuration" dialog: + +- Press ESC on the TianoCore splash screen, +- Navigate to Device Manager | OVMF Platform Configuration. + +At the moment, OVMF's platform driver handles only one setting: the preferred +graphics resolution. This is useful for two purposes: + +- Some UEFI shell commands, like DRIVERS and DEVICES, benefit from a wide + display. Using the MODE shell command, the user can switch to a larger text + resolution (limited by the graphics resolution), and see the command output + in a more easily consumable way. + + [RHEL] The list of text modes available to the MODE command is also limited + by ConSplitterDxe (found under MdeModulePkg/Universal/Console). + ConSplitterDxe builds an intersection of text modes that are + simultaneously supported by all consoles that ConSplitterDxe + multiplexes console output to. + + In practice, the strongest text mode restriction comes from + TerminalDxe, which provides console I/O on serial ports. TerminalDxe + has a very limited built-in list of text modes, heavily pruning the + intersection built by ConSplitterDxe, and made available to the MODE + command. + + On the Red Hat Enterprise Linux 7.1 host, TerminalDxe's list of modes + has been extended with text resolutions that match the Spice QXL GPU's + common graphics resolutions. This way a "full screen" text mode should + always be available in the MODE command. + +- The other advantage of controlling the graphics resolution lies with UEFI + operating systems that don't (yet) have a native driver for QEMU's virtual + video cards -- eg. the Spice QXL GPU. Such OSes may choose to inherit the + properties of OVMF's EFI_GRAPHICS_OUTPUT_PROTOCOL (provided by + OvmfPkg/QemuVideoDxe, see later). + + Although the display can be used at runtime in such cases, by direct + framebuffer access, its properties, for example, the resolution, cannot be + modified. The platform driver allows the user to select the preferred GOP + resolution, reboot, and let the guest OS inherit that preferred resolution. + +The platform driver has three access points: the "normal" driver entry point, a +set of HII callbacks, and a GOP installation callback. + +(1) Driver entry point: the PlatformInit() function. + + (a) First, this function loads any available settings, and makes them take + effect. For the preferred graphics resolution in particular, this means + setting the following PCDs: + + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution + + These PCDs influence the GraphicsConsoleDxe driver (located under + MdeModulePkg/Universal/Console), which switches to the preferred + graphics mode, and produces EFI_SIMPLE_TEXT_OUTPUT_PROTOCOLs on GOPs: + + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL + [MdeModulePkg/Universal/Console/GraphicsConsoleDxe] + | + EFI_GRAPHICS_OUTPUT_PROTOCOL + [OvmfPkg/QemuVideoDxe] + | + EFI_PCI_IO_PROTOCOL + [MdeModulePkg/Bus/Pci/PciBusDxe] + + (b) Second, the driver entry point registers the user interface, including + HII callbacks. + + (c) Third, the driver entry point registers a GOP installation callback. + +(2) HII callbacks and the user interface. + + The Human Interface Infrastructure (HII) "is a set of protocols that allow + a UEFI driver to provide the ability to register user interface and + configuration content with the platform firmware". + + OVMF's platform driver: + + - provides a static, basic, visual form (PlatformForms.vfr), written in the + Visual Forms Representation language, + + - includes a UCS-16 encoded message catalog (Platform.uni), + + - includes source code that dynamically populates parts of the form, with + the help of MdeModulePkg/Library/UefiHiiLib -- this library simplifies + the handling of IFR (Internal Forms Representation) opcodes, + + - processes form actions that the user takes (Callback() function), + + - loads and saves platform configuration in a private, non-volatile + variable (ExtractConfig() and RouteConfig() functions). + + The ExtractConfig() HII callback implements the following stack of + conversions, for loading configuration and presenting it to the user: + + MultiConfigAltResp -- form engine / HII communication + ^ + | + [BlockToConfig] + | + MAIN_FORM_STATE -- binary representation of form/widget + ^ state + | + [PlatformConfigToFormState] + | + PLATFORM_CONFIG -- accessible to DXE and UEFI drivers + ^ + | + [PlatformConfigLoad] + | + UEFI non-volatile variable -- accessible to external utilities + + The layers are very similar for the reverse direction, ie. when taking + input from the user, and saving the configuration (RouteConfig() HII + callback): + + ConfigResp -- form engine / HII communication + | + [ConfigToBlock] + | + v + MAIN_FORM_STATE -- binary representation of form/widget + | state + [FormStateToPlatformConfig] + | + v + PLATFORM_CONFIG -- accessible to DXE and UEFI drivers + | + [PlatformConfigSave] + | + v + UEFI non-volatile variable -- accessible to external utilities + +(3) When the platform driver starts, a GOP may not be available yet. Thus the + driver entry point registers a callback (the GopInstalled() function) for + GOP installations. + + When the first GOP is produced (usually by QemuVideoDxe, or potentially by + a third party video driver), PlatformDxe retrieves the list of graphics + modes the GOP supports, and dynamically populates the drop-down list of + available resolutions on the form. The GOP installation callback is then + removed. + +Video driver +............ + +OvmfPkg/QemuVideoDxe is OVMF's built-in video driver. We can divide its +services in two parts: graphics output protocol (primary), and Int10h (VBE) +shim (secondary). + +(1) QemuVideoDxe conforms to the UEFI Driver Model; it produces an instance of + the EFI_GRAPHICS_OUTPUT_PROTOCOL (GOP) on each PCI display that it supports + and is connected to: + + EFI_GRAPHICS_OUTPUT_PROTOCOL + [OvmfPkg/QemuVideoDxe] + | + EFI_PCI_IO_PROTOCOL + [MdeModulePkg/Bus/Pci/PciBusDxe] + + It supports the following QEMU video cards: + + - Cirrus 5430 ("-device cirrus-vga"), + - Standard VGA ("-device VGA"), + - QXL VGA ("-device qxl-vga", "-device qxl"). + + For Cirrus the following resolutions and color depths are available: + 640x480x32, 800x600x32, 1024x768x24. On stdvga and QXL a long list of + resolutions is available. The list is filtered against the frame buffer + size during initialization. + + The size of the QXL VGA compatibility framebuffer can be changed with the + + -device qxl-vga,vgamem_mb=$NUM_MB + + QEMU option. If $NUM_MB exceeds 32, then the following is necessary + instead: + + -device qxl-vga,vgamem_mb=$NUM_MB,ram_size_mb=$((NUM_MB*2)) + + because the compatibility framebuffer can't cover more than half of PCI BAR + #0. The latter defaults to 64MB in size, and is controlled by the + "ram_size_mb" property. + +(2) When QemuVideoDxe binds the first Standard VGA or QXL VGA device, and there + is no real VGA BIOS present in the C to F segments (which could originate + from a legacy PCI option ROM -- refer to "Compatibility Support Module + (CSM)"), then QemuVideoDxe installs a minimal, "fake" VGA BIOS -- an Int10h + (VBE) "shim". + + The shim is implemented in 16-bit assembly in + "OvmfPkg/QemuVideoDxe/VbeShim.asm". The "VbeShim.sh" shell script assembles + it and formats it as a C array ("VbeShim.h") with the help of the "nasm" + utility. The driver's InstallVbeShim() function copies the shim in place + (the C segment), and fills in the VBE Info and VBE Mode Info structures. + The real-mode 10h interrupt vector is pointed to the shim's handler. + + The shim is (correctly) irrelevant and invisible for all UEFI operating + systems we know about -- except Windows Server 2008 R2 and other Windows + operating systems in that family. + + Namely, the Windows 2008 R2 SP1 (and Windows 7) UEFI guest's default video + driver dereferences the real mode Int10h vector, loads the pointed-to + handler code, and executes what it thinks to be VGA BIOS services in an + internal real-mode emulator. Consequently, video mode switching used not to + work in Windows 2008 R2 SP1 when it ran on the "pure UEFI" build of OVMF, + making the guest uninstallable. Hence the (otherwise optional, non-default) + Compatibility Support Module (CSM) ended up a requirement for running such + guests. + + The hard dependency on the sophisticated SeaBIOS CSM and the complex + supporting edk2 infrastructure, for enabling this family of guests, was + considered suboptimal by some members of the upstream community, + + [RHEL] and was certainly considered a serious maintenance disadvantage for + Red Hat Enterprise Linux 7.1 hosts. + + Thus, the shim has been collaboratively developed for the Windows 7 / + Windows Server 2008 R2 family. The shim provides a real stdvga / QXL + implementation for the few services that are in fact necessary for the + Windows 2008 R2 SP1 (and Windows 7) UEFI guest, plus some "fakes" that the + guest invokes but whose effect is not important. The only supported mode is + 1024x768x32, which is enough to install the guest and then upgrade its + video driver to the full-featured QXL XDDM one. + + The C segment is not present in the UEFI memory map prepared by OVMF. + Memory space that would cover it is never added (either in PEI, in the form + of memory resource descriptor HOBs, or in DXE, via gDS->AddMemorySpace()). + This way the handler body is invisible to all other UEFI guests, and the + rest of edk2. + + The Int10h real-mode IVT entry is covered with a Boot Services Code page, + making that too inaccessible to the rest of edk2. Due to the allocation + type, UEFI guest OSes different from the Windows Server 2008 family can + reclaim the page at zero. (The Windows 2008 family accesses that page + regardless of the allocation type.) + +Afterword +--------- + +After the bulk of this document was written in July 2014, OVMF development has +not stopped. To name two significant code contributions from the community: in +January 2015, OVMF runs on the "q35" machine type of QEMU, and it features a +driver for Xen paravirtual block devices (and another for the underlying Xen +bus). + +Furthermore, a dedicated virtualization platform has been contributed to +ArmPlatformPkg that plays a role parallel to OvmfPkg's. It targets the "virt" +machine type of qemu-system-arm and qemu-system-aarch64. Parts of OvmfPkg are +being refactored and modularized so they can be reused in +"ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc". diff --git a/SPECS/edk2.spec b/SPECS/edk2.spec new file mode 100644 index 0000000..5445493 --- /dev/null +++ b/SPECS/edk2.spec @@ -0,0 +1,1527 @@ +ExclusiveArch: x86_64 aarch64 + +%define GITDATE 20220126 +%define GITCOMMIT bb1bba3d77 +%define TOOLCHAIN GCC5 +%define OPENSSL_VER 1.1.1k + +Name: edk2 +Version: %{GITDATE}git%{GITCOMMIT} +Release: 12%{?dist} +Summary: UEFI firmware for 64-bit virtual machines +Group: Applications/Emulators +License: BSD-2-Clause-Patent and OpenSSL and MIT +URL: http://www.tianocore.org + +# The source tarball is created using following commands: +# COMMIT=bb1bba3d77 +# git archive --format=tar --prefix=edk2-$COMMIT/ $COMMIT \ +# | 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-cf317b2bb227899cb2e761b9163210f62cab1b1e.tar.xz +Source3: ovmf-vars-generator +Source4: LICENSE.qosb +Source5: RedHatSecureBootPkKek1.pem + +Source10: edk2-aarch64-verbose.json +Source11: edk2-aarch64.json +Source12: edk2-ovmf-sb.json +Source13: edk2-ovmf.json +Source14: edk2-ovmf-cc.json + +Patch0008: 0008-BaseTools-do-not-build-BrotliCompress-RH-only.patch +Patch0009: 0009-MdeModulePkg-remove-package-private-Brotli-include-p.patch +Patch0010: 0010-OvmfPkg-increase-max-debug-message-length-to-512-RHE.patch +Patch0011: 0011-MdeModulePkg-TerminalDxe-add-other-text-resolutions-.patch +Patch0012: 0012-MdeModulePkg-TerminalDxe-set-xterm-resolution-on-mod.patch +Patch0013: 0013-OvmfPkg-take-PcdResizeXterm-from-the-QEMU-command-li.patch +Patch0014: 0014-ArmVirtPkg-take-PcdResizeXterm-from-the-QEMU-command.patch +Patch0015: 0015-OvmfPkg-allow-exclusion-of-the-shell-from-the-firmwa.patch +Patch0016: 0016-ArmPlatformPkg-introduce-fixed-PCD-for-early-hello-m.patch +Patch0017: 0017-ArmPlatformPkg-PrePeiCore-write-early-hello-message-.patch +Patch0018: 0018-ArmVirtPkg-set-early-hello-message-RH-only.patch +Patch0019: 0019-OvmfPkg-enable-DEBUG_VERBOSE-RHEL-only.patch +Patch0020: 0020-OvmfPkg-silence-DEBUG_VERBOSE-0x00400000-in-QemuVide.patch +Patch0021: 0021-ArmVirtPkg-silence-DEBUG_VERBOSE-0x00400000-in-QemuR.patch +Patch0022: 0022-OvmfPkg-QemuRamfbDxe-Do-not-report-DXE-failure-on-Aa.patch +Patch0023: 0023-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-NvmExpre.patch +Patch0024: 0024-CryptoPkg-OpensslLib-list-RHEL8-specific-OpenSSL-fil.patch +Patch0025: 0025-OvmfPkg-QemuKernelLoaderFsDxe-suppress-error-on-no-k.patch +Patch0026: 0026-SecurityPkg-Tcg2Dxe-suppress-error-on-no-swtpm-in-si.patch +# For bz#2112307 - Mark SEV launch secret area as reserved +Patch27: edk2-OvmfPkg-AmdSev-SecretPei-Mark-SEV-launch-secret-area.patch +# For bz#2164531 - CVE-2023-0286 edk2: openssl: X.400 address type confusion in X.509 GeneralName [rhel-8] +# For bz#2164543 - CVE-2022-4304 edk2: openssl: timing attack in RSA Decryption implementation [rhel-8] +# For bz#2164558 - CVE-2023-0215 edk2: openssl: use-after-free following BIO_new_NDEF [rhel-8] +# For bz#2164581 - CVE-2022-4450 edk2: openssl: double free after calling PEM_read_bio_ex [rhel-8] +Patch28: edk2-rh-openssl-add-crypto-bn-rsa_sup_mul.c-to-file-list.patch +# For bz#1861743 - CVE-2019-14560 edk2: Function GetEfiGlobalVariable2() return value not checked in DxeImageVerificationHandler() [rhel-8] +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 + + +# 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". +BuildRequires: python3-devel +BuildRequires: libuuid-devel +BuildRequires: /usr/bin/iasl +BuildRequires: binutils gcc git + +%ifarch x86_64 +# Only OVMF includes 80x86 assembly files (*.nasm*). +BuildRequires: nasm + +# Only OVMF includes the Secure Boot feature, for which we need to separate out +# the UEFI shell. +BuildRequires: dosfstools +BuildRequires: mtools +BuildRequires: genisoimage + +# For generating the variable store template with the default certificates +# enrolled, we need the qemu-kvm executable. +BuildRequires: qemu-kvm-core >= 2.12.0-89 + +# For verifying SB enablement in the above variable store template, we need a +# guest kernel that prints "Secure boot enabled". +BuildRequires: kernel-core >= 4.18.0-161 +BuildRequires: rpmdevtools + +%package ovmf +Summary: UEFI firmware for x86_64 virtual machines +BuildArch: noarch +Provides: OVMF = %{version}-%{release} +Obsoletes: OVMF < 20180508-100.gitee3198e672e2.el7 + +# OVMF includes the Secure Boot and IPv6 features; it has a builtin OpenSSL +# library. +Provides: bundled(openssl) = %{OPENSSL_VER} +License: BSD-2-Clause-Patent and OpenSSL + +# URL taken from the Maintainers.txt file. +URL: http://www.tianocore.org/ovmf/ + +%description ovmf +OVMF (Open Virtual Machine Firmware) is a project to enable UEFI support for +Virtual Machines. This package contains a sample 64-bit UEFI firmware for QEMU +and KVM. + +%else +%package aarch64 +Summary: UEFI firmware for aarch64 virtual machines +BuildArch: noarch +Provides: AAVMF = %{version}-%{release} +Obsoletes: AAVMF < 20180508-100.gitee3198e672e2.el7 + +# No Secure Boot for AAVMF yet, but we include OpenSSL for the IPv6 stack. +Provides: bundled(openssl) = %{OPENSSL_VER} +License: BSD-2-Clause-Patent and OpenSSL + +# URL taken from the Maintainers.txt file. +URL: https://github.com/tianocore/tianocore.github.io/wiki/ArmVirtPkg + +%description aarch64 +AAVMF (ARM Architecture Virtual Machine Firmware) is an EFI Development Kit II +platform that enables UEFI support for QEMU/KVM ARM Virtual Machines. This +package contains a 64-bit build. +%endif + +%package tools +Summary: EFI Development Kit II Tools +Group: Development/Tools +License: BSD-2-Clause-Patent +URL: https://github.com/tianocore/tianocore.github.io/wiki/BaseTools +%description tools +This package provides tools that are needed to +build EFI executables and ROMs using the GNU tools. + +%package tools-doc +Summary: Documentation for EFI Development Kit II Tools +Group: Development/Tools +BuildArch: noarch +License: BSD-2-Clause-Patent +URL: https://github.com/tianocore/tianocore.github.io/wiki/BaseTools +%description tools-doc +This package documents the tools that are needed to +build EFI executables and ROMs using the GNU tools. + +%description +EDK II is a modern, feature-rich, cross-platform firmware development +environment for the UEFI and PI specifications. This package contains sample +64-bit UEFI firmware builds for QEMU and KVM. + +%prep +%setup -q -n edk2-%{GITCOMMIT} + +%{lua: + tmp = os.tmpname(); + f = io.open(tmp, "w+"); + count = 0; + for i, p in ipairs(patches) do + f:write(p.."\n"); + count = count + 1; + end; + f:close(); + print("PATCHCOUNT="..count.."\n") + print("PATCHLIST="..tmp.."\n") +} + +git init -q +git config user.name rpm-build +git config user.email rpm-build +git config core.whitespace cr-at-eol +git config am.keepcr true +git add -A . +git commit -q -a --author 'rpm-build ' \ + -m '%{name}-%{GITCOMMIT} base' + +COUNT=$(grep '\.patch$' $PATCHLIST | wc -l) +if [ $COUNT -ne $PATCHCOUNT ]; then + echo "Found $COUNT patches in $PATCHLIST, expected $PATCHCOUNT" + exit 1 +fi +if [ $COUNT -gt 0 ]; then + for pf in `cat $PATCHLIST`; do + git am $pf + done +fi +echo "Applied $COUNT patches" +rm -f $PATCHLIST + +cp -a -- %{SOURCE1} %{SOURCE3} . +cp -a -- %{SOURCE10} %{SOURCE11} %{SOURCE12} %{SOURCE13} %{SOURCE14} . +tar -C CryptoPkg/Library/OpensslLib -a -f %{SOURCE2} -x + +# Format the Red Hat-issued certificate that is to be enrolled as both Platform +# Key and first Key Exchange Key, as an SMBIOS OEM String. This means stripping +# the PEM header and footer, and prepending the textual representation of the +# GUID that identifies this particular OEM String to "EnrollDefaultKeys.efi", +# plus the separator ":". For details, see +# comments 2, 7, 14. +sed \ + -e 's/^-----BEGIN CERTIFICATE-----$/4e32566d-8e9e-4f52-81d3-5bb9715f9727:/' \ + -e '/^-----END CERTIFICATE-----$/d' \ + %{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 . + +%build +export PYTHON_COMMAND=%{__python3} +source ./edksetup.sh +make -C "$EDK_TOOLS_PATH" \ + %{?_smp_mflags} \ + EXTRA_OPTFLAGS="%{optflags}" \ + EXTRA_LDFLAGS="%{__global_ldflags}" + +SMP_MFLAGS="%{?_smp_mflags}" +if [[ x"$SMP_MFLAGS" = x-j* ]]; then + CC_FLAGS="$CC_FLAGS -n ${SMP_MFLAGS#-j}" +elif [ -n "%{?jobs}" ]; then + CC_FLAGS="$CC_FLAGS -n %{?jobs}" +fi + +CC_FLAGS="$CC_FLAGS --cmd-len=65536 -t %{TOOLCHAIN} -b DEBUG --hash" +CC_FLAGS="$CC_FLAGS -D NETWORK_IP6_ENABLE" +CC_FLAGS="$CC_FLAGS -D NETWORK_HTTP_BOOT_ENABLE -D NETWORK_TLS_ENABLE" + +%ifarch x86_64 +# Build with neither SB nor SMM; include UEFI shell. +build ${CC_FLAGS} -D TPM_ENABLE -D FD_SIZE_4MB -a X64 \ + -D PVSCSI_ENABLE=FALSE -D MPT_SCSI_ENABLE=FALSE \ + -p OvmfPkg/OvmfPkgX64.dsc + +# Build with SB and SMM; exclude UEFI shell. +build -D SECURE_BOOT_ENABLE -D EXCLUDE_SHELL_FROM_FD ${CC_FLAGS} \ + -a IA32 -a X64 -p OvmfPkg/OvmfPkgIa32X64.dsc -D SMM_REQUIRE \ + -D PVSCSI_ENABLE=FALSE -D MPT_SCSI_ENABLE=FALSE \ + -D TPM_ENABLE -D FD_SIZE_4MB + +# Sanity check: the varstore templates must be identical. +cmp Build/OvmfX64/DEBUG_%{TOOLCHAIN}/FV/OVMF_VARS.fd \ + Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/FV/OVMF_VARS.fd + +# Prepare an ISO image that boots the UEFI shell. +( + UEFI_SHELL_BINARY=Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/X64/Shell.efi + ENROLLER_BINARY=Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/X64/EnrollDefaultKeys.efi + UEFI_SHELL_IMAGE=uefi_shell.img + ISO_IMAGE=UefiShell.iso + + UEFI_SHELL_BINARY_BNAME=$(basename -- "$UEFI_SHELL_BINARY") + UEFI_SHELL_SIZE=$(stat --format=%s -- "$UEFI_SHELL_BINARY") + ENROLLER_SIZE=$(stat --format=%s -- "$ENROLLER_BINARY") + + # add 1MB then 10% for metadata + UEFI_SHELL_IMAGE_KB=$(( + (UEFI_SHELL_SIZE + ENROLLER_SIZE + 1 * 1024 * 1024) * 11 / 10 / 1024 + )) + + # create non-partitioned FAT image + rm -f -- "$UEFI_SHELL_IMAGE" + mkdosfs -C "$UEFI_SHELL_IMAGE" -n UEFI_SHELL -- "$UEFI_SHELL_IMAGE_KB" + + # copy the shell binary into the FAT image + export MTOOLS_SKIP_CHECK=1 + mmd -i "$UEFI_SHELL_IMAGE" ::efi + mmd -i "$UEFI_SHELL_IMAGE" ::efi/boot + mcopy -i "$UEFI_SHELL_IMAGE" "$UEFI_SHELL_BINARY" ::efi/boot/bootx64.efi + mcopy -i "$UEFI_SHELL_IMAGE" "$ENROLLER_BINARY" :: + mdir -i "$UEFI_SHELL_IMAGE" -/ :: + + # build ISO with FAT image file as El Torito EFI boot image + genisoimage -input-charset ASCII -J -rational-rock \ + -efi-boot "$UEFI_SHELL_IMAGE" -no-emul-boot \ + -o "$ISO_IMAGE" -- "$UEFI_SHELL_IMAGE" +) + +# Enroll the default certificates in a separate variable store template. +%{__python3} ovmf-vars-generator --verbose --verbose \ + --qemu-binary /usr/libexec/qemu-kvm \ + --ovmf-binary Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/FV/OVMF_CODE.fd \ + --ovmf-template-vars Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/FV/OVMF_VARS.fd \ + --uefi-shell-iso UefiShell.iso \ + --oem-string "$(< PkKek1.oemstr)" \ + --skip-testing \ + OVMF_VARS.secboot.fd + +%else +# Build with a verbose debug mask first, and stash the binary. +build ${CC_FLAGS} -a AARCH64 \ + -p ArmVirtPkg/ArmVirtQemu.dsc \ + -D TPM2_ENABLE \ + -D DEBUG_PRINT_ERROR_LEVEL=0x8040004F +cp -a Build/ArmVirtQemu-AARCH64/DEBUG_%{TOOLCHAIN}/FV/QEMU_EFI.fd \ + QEMU_EFI.verbose.fd + +# Rebuild with a silent (errors only) debug mask. +build ${CC_FLAGS} -a AARCH64 \ + -p ArmVirtPkg/ArmVirtQemu.dsc \ + -D TPM2_ENABLE \ + -D DEBUG_PRINT_ERROR_LEVEL=0x80000000 +%endif + +%install + +cp -a OvmfPkg/License.txt License.OvmfPkg.txt +mkdir -p $RPM_BUILD_ROOT%{_datadir}/qemu/firmware + +%ifarch x86_64 +mkdir -p \ + $RPM_BUILD_ROOT%{_datadir}/OVMF \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/ovmf + +install -m 0644 Build/OvmfX64/DEBUG_%{TOOLCHAIN}/FV/OVMF_CODE.fd \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/ovmf/OVMF_CODE.cc.fd +install -m 0644 Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/FV/OVMF_CODE.fd \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/ovmf/OVMF_CODE.secboot.fd + +install -m 0644 Build/OvmfX64/DEBUG_%{TOOLCHAIN}/FV/OVMF_VARS.fd \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/ovmf/OVMF_VARS.fd +install -m 0644 OVMF_VARS.secboot.fd \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/ovmf/OVMF_VARS.secboot.fd +install -m 0644 UefiShell.iso \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/ovmf/UefiShell.iso + +ln -s ../%{name}/ovmf/OVMF_CODE.secboot.fd $RPM_BUILD_ROOT%{_datadir}/OVMF/ +ln -s ../%{name}/ovmf/OVMF_VARS.fd $RPM_BUILD_ROOT%{_datadir}/OVMF/ +ln -s ../%{name}/ovmf/OVMF_VARS.secboot.fd $RPM_BUILD_ROOT%{_datadir}/OVMF/ +ln -s ../%{name}/ovmf/UefiShell.iso $RPM_BUILD_ROOT%{_datadir}/OVMF/ + +install -m 0644 Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/X64/Shell.efi \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/ovmf/Shell.efi +install -m 0644 Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/X64/EnrollDefaultKeys.efi \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/ovmf/EnrollDefaultKeys.efi + +install -m 0644 edk2-ovmf-sb.json \ + $RPM_BUILD_ROOT%{_datadir}/qemu/firmware/40-edk2-ovmf-sb.json +install -m 0644 edk2-ovmf.json \ + $RPM_BUILD_ROOT%{_datadir}/qemu/firmware/50-edk2-ovmf.json +install -m 0644 edk2-ovmf-cc.json \ + $RPM_BUILD_ROOT%{_datadir}/qemu/firmware/50-edk2-ovmf-cc.json + +%else +mkdir -p \ + $RPM_BUILD_ROOT%{_datadir}/AAVMF \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/aarch64 + +# Pad and install the verbose binary. +cat QEMU_EFI.verbose.fd \ + /dev/zero \ +| head -c 64m \ + > $RPM_BUILD_ROOT%{_datadir}/%{name}/aarch64/QEMU_EFI-pflash.raw + +# Pad and install the silent (default) binary. +cat Build/ArmVirtQemu-AARCH64/DEBUG_%{TOOLCHAIN}/FV/QEMU_EFI.fd \ + /dev/zero \ +| head -c 64m \ + > $RPM_BUILD_ROOT%{_datadir}/%{name}/aarch64/QEMU_EFI-silent-pflash.raw + +# Create varstore template. +cat Build/ArmVirtQemu-AARCH64/DEBUG_%{TOOLCHAIN}/FV/QEMU_VARS.fd \ + /dev/zero \ +| head -c 64m \ + > $RPM_BUILD_ROOT%{_datadir}/%{name}/aarch64/vars-template-pflash.raw + +ln -s ../%{name}/aarch64/QEMU_EFI-pflash.raw \ + $RPM_BUILD_ROOT%{_datadir}/AAVMF/AAVMF_CODE.verbose.fd +ln -s ../%{name}/aarch64/QEMU_EFI-silent-pflash.raw \ + $RPM_BUILD_ROOT%{_datadir}/AAVMF/AAVMF_CODE.fd +ln -s ../%{name}/aarch64/vars-template-pflash.raw \ + $RPM_BUILD_ROOT%{_datadir}/AAVMF/AAVMF_VARS.fd + +chmod 0644 -- $RPM_BUILD_ROOT%{_datadir}/AAVMF/AAVMF_*.fd + +install -m 0644 QEMU_EFI.verbose.fd \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/aarch64/QEMU_EFI.fd +install -m 0644 Build/ArmVirtQemu-AARCH64/DEBUG_%{TOOLCHAIN}/FV/QEMU_EFI.fd \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/aarch64/QEMU_EFI.silent.fd +install -m 0644 Build/ArmVirtQemu-AARCH64/DEBUG_%{TOOLCHAIN}/FV/QEMU_VARS.fd \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/aarch64/QEMU_VARS.fd + +install -m 0644 edk2-aarch64.json \ + $RPM_BUILD_ROOT%{_datadir}/qemu/firmware/60-edk2-aarch64.json +install -m 0644 edk2-aarch64-verbose.json \ + $RPM_BUILD_ROOT%{_datadir}/qemu/firmware/70-edk2-aarch64-verbose.json + +%endif + +cp -a CryptoPkg/Library/OpensslLib/openssl/LICENSE LICENSE.openssl + +# install the tools +mkdir -p %{buildroot}%{_bindir} \ + %{buildroot}%{_datadir}/%{name}/Conf \ + %{buildroot}%{_datadir}/%{name}/Scripts +install BaseTools/Source/C/bin/* \ + %{buildroot}%{_bindir} +install BaseTools/BinWrappers/PosixLike/LzmaF86Compress \ + %{buildroot}%{_bindir} +install BaseTools/BuildEnv \ + %{buildroot}%{_datadir}/%{name} +install BaseTools/Conf/*.template \ + %{buildroot}%{_datadir}/%{name}/Conf +install BaseTools/Scripts/GccBase.lds \ + %{buildroot}%{_datadir}/%{name}/Scripts + +%ifarch x86_64 +%files ovmf +%else +%files aarch64 +%endif + +%defattr(-,root,root,-) +%license License.txt +%license License.OvmfPkg.txt +%license License-History.txt +%license LICENSE.openssl +%dir %{_datadir}/%{name}/ +%dir %{_datadir}/qemu +%dir %{_datadir}/qemu/firmware + +%ifarch x86_64 +%doc OvmfPkg/README +%doc ovmf-whitepaper-c770f8c.txt +%dir %{_datadir}/OVMF/ +%dir %{_datadir}/%{name}/ovmf/ +%{_datadir}/%{name}/ovmf/OVMF_CODE.cc.fd +%{_datadir}/%{name}/ovmf/OVMF_CODE.secboot.fd +%{_datadir}/%{name}/ovmf/OVMF_VARS.fd +%{_datadir}/%{name}/ovmf/OVMF_VARS.secboot.fd +%{_datadir}/%{name}/ovmf/UefiShell.iso +%{_datadir}/OVMF/OVMF_CODE.secboot.fd +%{_datadir}/OVMF/OVMF_VARS.fd +%{_datadir}/OVMF/OVMF_VARS.secboot.fd +%{_datadir}/OVMF/UefiShell.iso +%{_datadir}/%{name}/ovmf/Shell.efi +%{_datadir}/%{name}/ovmf/EnrollDefaultKeys.efi +%{_datadir}/qemu/firmware/40-edk2-ovmf-sb.json +%{_datadir}/qemu/firmware/50-edk2-ovmf-cc.json +%{_datadir}/qemu/firmware/50-edk2-ovmf.json + +%else +%dir %{_datadir}/AAVMF/ +%dir %{_datadir}/%{name}/aarch64/ +%{_datadir}/%{name}/aarch64/QEMU_EFI-pflash.raw +%{_datadir}/%{name}/aarch64/QEMU_EFI-silent-pflash.raw +%{_datadir}/%{name}/aarch64/vars-template-pflash.raw +%{_datadir}/AAVMF/AAVMF_CODE.verbose.fd +%{_datadir}/AAVMF/AAVMF_CODE.fd +%{_datadir}/AAVMF/AAVMF_VARS.fd +%{_datadir}/%{name}/aarch64/QEMU_EFI.fd +%{_datadir}/%{name}/aarch64/QEMU_EFI.silent.fd +%{_datadir}/%{name}/aarch64/QEMU_VARS.fd +%{_datadir}/qemu/firmware/60-edk2-aarch64.json +%{_datadir}/qemu/firmware/70-edk2-aarch64-verbose.json +%endif + +%files tools +%license License.txt +%license License-History.txt +%{_bindir}/DevicePath +%{_bindir}/EfiRom +%{_bindir}/GenCrc32 +%{_bindir}/GenFfs +%{_bindir}/GenFv +%{_bindir}/GenFw +%{_bindir}/GenSec +%{_bindir}/LzmaCompress +%{_bindir}/LzmaF86Compress +%{_bindir}/TianoCompress +%{_bindir}/VfrCompile +%{_bindir}/VolInfo +%dir %{_datadir}/%{name} +%{_datadir}/%{name}/BuildEnv +%{_datadir}/%{name}/Conf +%{_datadir}/%{name}/Scripts + +%files tools-doc +%doc BaseTools/UserManuals/*.rtf + +%check + +%ifarch x86_64 +# Of the installed host kernels, boot the one with the highest Version-Release +# under OVMF, and check if it prints "Secure boot enabled". +KERNEL_PKG=$(rpm -q kernel-core | rpmdev-sort | tail -n 1) +KERNEL_IMG=$(rpm -q -l $KERNEL_PKG | egrep '^/lib/modules/[^/]+/vmlinuz$') + +%{__python3} ovmf-vars-generator --verbose --verbose \ + --qemu-binary /usr/libexec/qemu-kvm \ + --ovmf-binary Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/FV/OVMF_CODE.fd \ + --ovmf-template-vars Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/FV/OVMF_VARS.fd \ + --uefi-shell-iso UefiShell.iso \ + --kernel-path $KERNEL_IMG \ + --skip-enrollment \ + --no-download \ + OVMF_VARS.secboot.fd + +%else +true + +%endif + +%changelog +* Fri Mar 29 2024 MSVSphere Packaging Team - 20220126gitbb1bba3d77-12 +- Rebuilt for MSVSphere 8.10 beta + +* 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] +- Resolves: bz#2150267 + (ovmf must consider max cpu count not boot cpu count for apic mode [rhel-8]) + +* Thu Apr 06 2023 Miroslav Rezanina - 20220126gitbb1bba3d77-5 +- edk2-SecurityPkg-DxeImageVerificationLib-Check-result-of-.patch [bz#1861743] +- Resolves: bz#1861743 + (CVE-2019-14560 edk2: Function GetEfiGlobalVariable2() return value not checked in DxeImageVerificationHandler() [rhel-8]) + +* Wed Feb 15 2023 Jon Maloy - 20220126gitbb1bba3d77-4 +- edk2-openssl-update.patch [bz#2164531 bz#2164543 bz#2164558 bz#2164581] +- edk2-rh-openssl-add-crypto-bn-rsa_sup_mul.c-to-file-list.patch [bz#2164531 bz#2164543 bz#2164558 bz#2164581] +- Resolves: bz#2164531 + (CVE-2023-0286 edk2: openssl: X.400 address type confusion in X.509 GeneralName [rhel-8]) +- Resolves: bz#2164543 + (CVE-2022-4304 edk2: openssl: timing attack in RSA Decryption implementation [rhel-8]) +- Resolves: bz#2164558 + (CVE-2023-0215 edk2: openssl: use-after-free following BIO_new_NDEF [rhel-8]) +- Resolves: bz#2164581 + (CVE-2022-4450 edk2: openssl: double free after calling PEM_read_bio_ex [rhel-8]) + +* Tue Aug 02 2022 Camilla Conte - 20220126gitbb1bba3d77-3 +- Bumping OpenSSL version [bz# 2074834] +- Resolves: bz# 2074834 + (edk2: sync openssl sources with rhel openssl rpm) + +* Tue Mar 01 2022 Jon Maloy - 20220126gitbb1bba3d77-2 +- edk2-OvmfPkg-AmdSev-SecretPei-Mark-SEV-launch-secret-area.patch [bz#2112307] +- Resolves: bz#2112307 + (Mark SEV launch secret area as reserved) + +* Wed Feb 02 2022 Jon Maloy - 20220126gitbb1bba3d77-1.el8 +- Rebase to latest upstream release [bz#2018386] +- Resolves: bz#2018386 + ([rebase] update edk2 to nov '21 release (edk2-stable202111xx)) + +* Fri Aug 06 2021 Miroslav Rezanina - 20210527gite1999b264f1f-3 +- edk2-MdeModulePkg-PartitionDxe-Ignore-PMBR-BootIndicator-.patch [bz#1988762] +- Resolves: bz#1988762 + (edk2 does not ignore PMBR protective record BootIndicator as required by UEFI spec) + +* Fri Jul 02 2021 Miroslav Rezanina - 20210527gite1999b264f1f-2 +- edk2-NetworkPkg-IScsiDxe-wrap-IScsiCHAP-source-files-to-8.patch [bz#1956408] +- edk2-NetworkPkg-IScsiDxe-simplify-ISCSI_CHAP_AUTH_DATA.In.patch [bz#1956408] +- edk2-NetworkPkg-IScsiDxe-clean-up-ISCSI_CHAP_AUTH_DATA.Ou.patch [bz#1956408] +- edk2-NetworkPkg-IScsiDxe-clean-up-library-class-dependenc.patch [bz#1956408] +- edk2-NetworkPkg-IScsiDxe-fix-potential-integer-overflow-i.patch [bz#1956408] +- edk2-NetworkPkg-IScsiDxe-assert-that-IScsiBinToHex-always.patch [bz#1956408] +- edk2-NetworkPkg-IScsiDxe-reformat-IScsiHexToBin-leading-c.patch [bz#1956408] +- edk2-NetworkPkg-IScsiDxe-fix-IScsiHexToBin-hex-parsing.patch [bz#1956408] +- edk2-NetworkPkg-IScsiDxe-fix-IScsiHexToBin-buffer-overflo.patch [bz#1956408] +- edk2-NetworkPkg-IScsiDxe-check-IScsiHexToBin-return-value.patch [bz#1956408] +- Resolves: bz#1956408 + (edk2: remote buffer overflow in IScsiHexToBin function in NetworkPkg/IScsiDxe [rhel-8.5.0]) + +* Wed Jun 23 2021 Miroslav Rezanina - 20210527gite1999b264f1f-1 +- Rebase to edk2-stable202105 [bz#1938238] +- Resolves: bz#1938238 + ((edk2-rebase-rhel-8.5) - rebase edk2 to edk2-stable202105 for RHEL-8.5) + +* Wed May 12 2021 Miroslav Rezanina - 20200602gitca407c7246bf-5.el8 +- edk2-MdeModulePkg-LzmaCustomDecompressLib-catch-4GB-uncom.patch [bz#1892318] +- edk2-redhat-add-OVMF-binary-that-will-support-SEV-ES.patch [bz#1956837] +- Resolves: bz#1892318 + (edk2: possible heap corruption with LzmaUefiDecompressGetInfo [rhel-8]) +- Resolves: bz#1956837 + (Additional build of edk2 without SMM (dual build / sub-package) for SEV-ES) + +* Mon Nov 23 2020 Miroslav Rezanina - 20200602gitca407c7246bf-4.el8 +- edk2-OvmfPkg-SmmControl2Dxe-negotiate-ICH9_LPC_SMI_F_CPU_.patch [bz#1849177] +- edk2-OvmfPkg-CpuHotplugSmm-fix-CPU-hotplug-race-just-befo.patch [bz#1849177] +- edk2-OvmfPkg-CpuHotplugSmm-fix-CPU-hotplug-race-just-afte.patch [bz#1849177] +- edk2-CryptoPkg-OpensslLib-Upgrade-OpenSSL-to-1.1.1g.patch [bz#1893806] +- edk2-redhat-bump-OpenSSL-dist-git-submodule-to-1.1.1g-RHE.patch [bz#1893806] +- Resolves: bz#1849177 + (OVMF: negotiate "SMI on VCPU hotplug" with QEMU) +- Resolves: bz#1893806 + (attempt advancing RHEL8 edk2's OpenSSL submodule to RHEL8 OpenSSL 1.1.1g (or later)) + +* Mon Aug 10 2020 Miroslav Rezanina - 20200602gitca407c7246bf-3.el8 +- edk2-UefiCpuPkg-PiSmmCpuDxeSmm-pause-in-WaitForSemaphore-.patch [bz#1861718] +- Resolves: bz#1861718 + (Very slow boot when overcommitting CPU) + +* Wed Jun 24 2020 Miroslav Rezanina - 20200602gitca407c7246bf-2.el8 +- edk2-OvmfPkg-QemuKernelLoaderFsDxe-suppress-error-on-no-k.patch [bz#1844682] +- edk2-OvmfPkg-GenericQemuLoadImageLib-log-Not-Found-at-INF.patch [bz#1844682] +- edk2-SecurityPkg-Tcg2Dxe-suppress-error-on-no-swtpm-in-si.patch [bz#1844682] +- Resolves: bz#1844682 + (silent build of edk2-aarch64 logs DEBUG_ERROR messages that don't actually report serious errors) + +* Sat Jun 13 2020 Miroslav Rezanina - 20200602gitca407c7246bf-1.el8 +- Rebase to edk2-stable202005 [bz#1817035] +- Resolves: bz#1817035 + ((edk2-rebase-rhel-8.3) - rebase edk2 to upstream tag edk2-stable202005 for RHEL-8.3) + +* Fri Mar 27 2020 Miroslav Rezanina - 20190829git37eef91017ad-9.el8 +- edk2-OvmfPkg-QemuVideoDxe-unbreak-secondary-vga-and-bochs.patch [bz#1806359] +- Resolves: bz#1806359 + (bochs-display cannot show graphic wihout driver attach) + +* Tue Feb 18 2020 Miroslav Rezanina - 20190829git37eef91017ad-8.el8 +- edk2-MdeModulePkg-Enable-Disable-S3BootScript-dynamically.patch [bz#1801274] +- edk2-MdeModulePkg-PiDxeS3BootScriptLib-Fix-potential-nume.patch [bz#1801274] +- Resolves: bz#1801274 + (CVE-2019-14563 edk2: numeric truncation in MdeModulePkg/PiDxeS3BootScriptLib [rhel-8]) + +* Tue Feb 11 2020 Miroslav Rezanina - 20190829git37eef91017ad-7.el8 +- edk2-SecurityPkg-Fix-spelling-errors-PARTIAL-PICK.patch [bz#1751993] +- edk2-SecurityPkg-DxeImageVerificationHandler-simplify-Ver.patch [bz#1751993] +- edk2-SecurityPkg-DxeImageVerificationHandler-remove-else-.patch [bz#1751993] +- edk2-SecurityPkg-DxeImageVerificationHandler-keep-PE-COFF.patch [bz#1751993] +- edk2-SecurityPkg-DxeImageVerificationHandler-narrow-down-.patch [bz#1751993] +- edk2-SecurityPkg-DxeImageVerificationHandler-fix-retval-o.patch [bz#1751993] +- edk2-SecurityPkg-DxeImageVerificationHandler-remove-super.patch [bz#1751993] +- edk2-SecurityPkg-DxeImageVerificationHandler-unnest-AddIm.patch [bz#1751993] +- edk2-SecurityPkg-DxeImageVerificationHandler-eliminate-St.patch [bz#1751993] +- edk2-SecurityPkg-DxeImageVerificationHandler-fix-retval-f.patch [bz#1751993] +- edk2-SecurityPkg-DxeImageVerificationHandler-fix-imgexec-.patch [bz#1751993] +- edk2-SecurityPkg-DxeImageVerificationHandler-fix-defer-vs.patch [bz#1751993] +- Resolves: bz#1751993 + (DxeImageVerificationLib handles "DENY execute on security violation" like "DEFER execute on security violation" [rhel8]) + +* Tue Jan 21 2020 Miroslav Rezanina - 20190829git37eef91017ad-6.el8 +- edk2-UefiCpuPkg-PiSmmCpuDxeSmm-fix-2M-4K-page-splitting-r.patch [bz#1789335] +- Resolves: bz#1789335 + (VM with edk2 can't boot when setting memory with '-m 2001') + +* Thu Jan 16 2020 Miroslav Rezanina - 20190829git37eef91017ad-5.el8 +- edk2-MdeModulePkg-UefiBootManagerLib-log-reserved-mem-all.patch [bz#1789797] +- edk2-NetworkPkg-HttpDxe-fix-32-bit-truncation-in-HTTPS-do.patch [bz#1789797] +- Resolves: bz#1789797 + (Backport upstream patch series: "UefiBootManagerLib, HttpDxe: tweaks for large HTTP(S) downloads" to improve HTTP(S) Boot experience with large (4GiB+) files) + +* Wed Dec 11 2019 Miroslav Rezanina - 20190829git37eef91017ad-4.el8 +- edk2-redhat-set-guest-RAM-size-to-768M-for-SB-varstore-te.patch [bz#1778301] +- edk2-redhat-re-enable-Secure-Boot-varstore-template-verif.patch [bz#1778301] +- Resolves: bz#1778301 + (re-enable Secure Boot (varstore template) verification in %check) + +* Thu Dec 05 2019 Miroslav Rezanina - 20190829git37eef91017ad-3.el8 +- Update used openssl version [bz#1616029] +- Resolves: bz#1616029 + (rebuild edk2 against the final RHEL-8.2.0 version of OpenSSL-1.1.1) + +* Mon Dec 02 2019 Miroslav Rezanina - 20190829git37eef91017ad-2.el8 +- edk2-MdePkg-Include-Protocol-Tls.h-Add-the-data-type-of-E.patch [bz#1536624] +- edk2-CryptoPkg-TlsLib-Add-the-new-API-TlsSetVerifyHost-CV.patch [bz#1536624] +- edk2-CryptoPkg-Crt-turn-strchr-into-a-function-CVE-2019-1.patch [bz#1536624] +- edk2-CryptoPkg-Crt-satisfy-inet_pton.c-dependencies-CVE-2.patch [bz#1536624] +- edk2-CryptoPkg-Crt-import-inet_pton.c-CVE-2019-14553.patch [bz#1536624] +- edk2-CryptoPkg-TlsLib-TlsSetVerifyHost-parse-IP-address-l.patch [bz#1536624] +- edk2-NetworkPkg-TlsDxe-Add-the-support-of-host-validation.patch [bz#1536624] +- edk2-NetworkPkg-HttpDxe-Set-the-HostName-for-the-verifica.patch [bz#1536624] +- edk2-redhat-enable-HTTPS-Boot.patch [bz#1536624] +- Resolves: bz#1536624 + (HTTPS enablement in OVMF) + +* Fri Nov 29 2019 Miroslav Rezanina - 20190829git37eef91017ad-1.el8 +- Rebase to edk2-stable201908 [bz#1748180] +- Resolves: bz#1748180 + ((edk2-rebase-rhel-8.2) - rebase edk2 to upstream tag edk2-stable201908 for RHEL-8.2) + +* Mon Aug 05 2019 Miroslav Rezanina - 20190308git89910a39dcfd-6.el8 +- edk2-ArmVirtPkg-silence-DEBUG_VERBOSE-masking-0x00400000-.patch [bz#1714446] +- edk2-OvmfPkg-QemuRamfbDxe-Do-not-report-DXE-failure-on-Aa.patch [bz#1714446] +- edk2-ArmPkg-DebugPeCoffExtraActionLib-debugger-commands-a.patch [bz#1714446] +- Resolves: bz#1714446 + (edk2-aarch64 silent build is not silent enough) + +* Tue Jul 02 2019 Miroslav Rezanina - 20190308git89910a39dcfd-5.el8 +- edk2-redhat-add-D-TPM2_ENABLE-to-the-edk2-ovmf-build-flag.patch [bz#1693205] +- Resolves: bz#1693205 + (edk2: Enable TPM2 support) + +* Tue Jun 11 2019 Miroslav Rezanina - 20190308git89910a39dcfd-4.el8 +- edk2-OvmfPkg-raise-the-PCIEXBAR-base-to-2816-MB-on-Q35.patch [bz#1666941] +- edk2-OvmfPkg-PlatformPei-set-32-bit-UC-area-at-PciBase-Pc.patch [bz#1666941] +- Resolves: bz#1666941 + (UEFI guest cannot boot into os when setting some special memory size) + +* Tue Apr 09 2019 Danilo Cesar Lemes de Paula - 20190308git89910a39dcfd-2.el8 +- edk2-redhat-provide-firmware-descriptor-meta-files.patch [bz#1600230] +- Resolves: bz#1600230 + ([RHEL 8.1] RFE: provide firmware descriptor meta-files for the edk2-ovmf and edk2-aarch64 firmware images) + +* Mon Apr 08 2019 Danilo Cesar Lemes de Paula - 20190308git89910a39dcfd-1.el8 +- Rebase to edk2-20190308git89910a39dcfd + +* Mon Jan 21 2019 Danilo Cesar Lemes de Paula - 20180508gitee3198e672e2-9.el8 +- edk2-BaseTools-Fix-UEFI-and-Tiano-Decompression-logic-iss.patch [bz#1662184] +- edk2-MdePkg-BaseUefiDecompressLib-Fix-UEFI-Decompression-.patch [bz#1662184] +- edk2-IntelFrameworkModulePkg-Fix-UEFI-and-Tiano-Decompres.patch [bz#1662184] +- edk2-git-Use-HTTPS-support.patch [] +- Resolves: bz#1662184 + (backport fix for (theoretical?) regression introduced by earlier CVE fixes) + +* Wed Nov 21 2018 Danilo Cesar Lemes de Paula - 20180508gitee3198e672e2-8.el8 +- edk2-NetworkPkg-UefiPxeBcDxe-Add-EXCLUSIVE-attribute-when.patch [bz#1643377] +- Resolves: bz#1643377 + (Exception when grubx64.efi used for UEFI netboot) + +* Tue Nov 06 2018 Danilo Cesar Lemes de Paula - 20180508gitee3198e672e2-5.el8 +- edk2-MdeModulePkg-Variable-Fix-Timestamp-zeroing-issue-on.patch [bz#1641436] +- edk2-MdePkg-Add-more-checker-in-UefiDecompressLib-to-acce.patch [bz#1641449 bz#1641453 bz#1641464 bz#1641469] +- edk2-IntelFrameworkModulePkg-Add-more-checker-in-UefiTian.patch [bz#1641453 bz#1641464 bz#1641469] +- edk2-BaseTools-Add-more-checker-in-Decompress-algorithm-t.patch [bz#1641445 bz#1641453 bz#1641464 bz#1641469] +- Resolves: bz#1641436 + (CVE-2018-3613 edk2: Logic error in MdeModulePkg in EDK II firmware allows for privilege escalation by authenticated users [rhel-8]) +- Resolves: bz#1641445 + (CVE-2017-5731 edk2: Privilege escalation via processing of malformed files in TianoCompress.c [rhel-8]) +- Resolves: bz#1641449 + (CVE-2017-5732 edk2: Privilege escalation via processing of malformed files in BaseUefiDecompressLib.c [rhel-8]) +- Resolves: bz#1641453 + (CVE-2017-5733 edk2: Privilege escalation via heap-based buffer overflow in MakeTable() function [rhel-8]) +- Resolves: bz#1641464 + (CVE-2017-5734 edk2: Privilege escalation via stack-based buffer overflow in MakeTable() function [rhel-8]) +- Resolves: bz#1641469 + (CVE-2017-5735 edk2: Privilege escalation via heap-based buffer overflow in Decode() function [rhel-8]) + +* Tue Sep 04 2018 Danilo Cesar Lemes de Paula - 20180508gitee3198e672e2-5.el8 +- edk2-BaseTools-footer.makefile-expand-BUILD_CFLAGS-last-f.patch [bz#1607906] +- edk2-BaseTools-header.makefile-remove-c-from-BUILD_CFLAGS.patch [bz#1607906] +- edk2-BaseTools-Source-C-split-O2-to-BUILD_OPTFLAGS.patch [bz#1607906] +- edk2-BaseTools-Source-C-take-EXTRA_OPTFLAGS-from-the-call.patch [bz#1607906] +- edk2-BaseTools-Source-C-take-EXTRA_LDFLAGS-from-the-calle.patch [bz#1607906] +- edk2-BaseTools-VfrCompile-honor-EXTRA_LDFLAGS.patch [bz#1607906] +- edk2-redhat-inject-the-RPM-compile-and-link-options-to-th.patch [bz#1607906] +- Resolves: bz#1607906 + (edk2-tools: Does not use RPM build flags) + +* Wed Aug 08 2018 Danilo Cesar Lemes de Paula - 20180508gitee3198e672e2-4.el8 +- edk2-redhat-provide-virtual-bundled-OpenSSL-in-edk2-ovmf-.patch [bz#1607801] +- Resolves: bz#1607801 + (add 'Provides: bundled(openssl) = 1.1.0h' to the spec file) + +* Tue Jul 24 2018 Danilo Cesar Lemes de Paula - 20180508gitee3198e672e2-3.el8 +- edk2-redhat-Provide-and-Obsolete-OVMF-and-AAVMF.patch [bz#1596148] +- edk2-ArmVirtPkg-unify-HttpLib-resolutions-in-ArmVirt.dsc..patch [bz#1536627] +- edk2-ArmVirtPkg-ArmVirtQemu-enable-the-IPv6-stack.patch [bz#1536627] +- edk2-advertise-OpenSSL-due-to-IPv6-enablement-too-RHEL-on.patch [bz#1536627] +- edk2-redhat-add-D-NETWORK_IP6_ENABLE-to-the-build-flags.patch [bz#1536627] +- edk2-redhat-update-license-fields-and-files-in-the-spec-f.patch [bz#1536627] +- Resolves: bz#1536627 + (IPv6 enablement in OVMF) +- Resolves: bz#1596148 + (restore Provides/Obsoletes macros for OVMF and AAVMF, from RHEL-8 Alpha) + +* Tue Jul 10 2018 Danilo C. L. de Paula - 20180508gitee3198e672e2-2.el8 +- Rebase edk2 on top of 20180508gitee3198e672e2 + +* Fri Jun 08 2018 Miroslav Rezanina - 20180508-2.gitee3198e672e2 +- OvmfPkg/PlatformBootManagerLib: connect consoles unconditionally [bz#1577546] +- build OVMF varstore template with SB enabled / certs enrolled [bz#1561128] +- connect Virtio RNG devices again [bz#1579518] +- Resolves: bz#1577546 + (no input consoles connected under certain circumstances) +- Resolves: bz#1561128 + (OVMF Secure boot enablement (enrollment of default keys)) +- Resolves: bz#1579518 + (EFI_RNG_PROTOCOL no longer produced for virtio-rng) +* Wed Dec 06 2017 Miroslav Rezanina - 20171011-4.git92d07e48907f.el7 +- ovmf-MdeModulePkg-Core-Dxe-log-informative-memprotect-msg.patch [bz#1520485] +- ovmf-MdeModulePkg-BdsDxe-fall-back-to-a-Boot-Manager-Menu.patch [bz#1515418] +- Resolves: bz#1515418 + (RFE: Provide diagnostics for failed boot) +- Resolves: bz#1520485 + (AAVMF: two new messages with silent build) + +* Fri Dec 01 2017 Miroslav Rezanina - 20171011-3.git92d07e48907f.el7 +- ovmf-UefiCpuPkg-CpuDxe-Fix-multiple-entries-of-RT_CODE-in.patch [bz#1518308] +- ovmf-MdeModulePkg-DxeCore-Filter-out-all-paging-capabilit.patch [bz#1518308] +- ovmf-MdeModulePkg-Core-Merge-memory-map-after-filtering-p.patch [bz#1518308] +- Resolves: bz#1518308 + (UEFI memory map regression (runtime code entry splitting) introduced by c1cab54ce57c) + +* Mon Nov 27 2017 Miroslav Rezanina - 20171011-2.git92d07e48907f.el7 +- ovmf-MdeModulePkg-Bds-Remove-assertion-in-BmCharToUint.patch [bz#1513632] +- ovmf-MdeModulePkg-Bds-Check-variable-name-even-if-OptionN.patch [bz#1513632] +- ovmf-MdeModulePkg-PciBus-Fix-bug-that-PCI-BUS-claims-too-.patch [bz#1514105] +- ovmf-OvmfPkg-make-it-a-proper-BASE-library.patch [bz#1488247] +- ovmf-OvmfPkg-create-a-separate-PlatformDebugLibIoPort-ins.patch [bz#1488247] +- ovmf-OvmfPkg-save-on-I-O-port-accesses-when-the-debug-por.patch [bz#1488247] +- ovmf-OvmfPkg-enable-DEBUG_VERBOSE-RHEL-only.patch [bz#1488247] +- ovmf-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-QemuVide.patch [bz#1488247] +- ovmf-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-NvmExpre.patch [bz#1488247] +- ovmf-Revert-redhat-introduce-separate-silent-and-verbose-.patch [bz#1488247] +- Resolves: bz#1488247 + (make debug logging no-op unless a debug console is active) +- Resolves: bz#1513632 + ([RHEL-ALT 7.5] AAVMF fails to boot after setting BootNext) +- Resolves: bz#1514105 + (backport edk2 commit 6e3287442774 so that PciBusDxe not over-claim resources) + +* Wed Oct 18 2017 Miroslav Rezanina - 20171011-1.git92d07e48907f.el7 +- Rebase to 92d07e48907f [bz#1469787] +- Resolves: bz#1469787 + ((ovmf-rebase-rhel-7.5) Rebase OVMF for RHEL-7.5) +- Resolves: bz#1434740 + (OvmfPkg/PciHotPlugInitDxe: don't reserve IO space when IO support is disabled) +- Resolves: bz#1434747 + ([Q35] code12 error when hotplug x710 device in win2016) +- Resolves: bz#1447027 + (Guest cannot boot with 240 or above vcpus when using ovmf) +- Resolves: bz#1458192 + ([Q35] recognize "usb-storage" devices in XHCI ports) +- Resolves: bz#1468526 + (>1TB RAM support) +- Resolves: bz#1488247 + (provide "OVMF_CODE.secboot.verbose.fd" for log capturing; silence "OVMF_CODE.secboot.fd") +- Resolves: bz#1496170 + (Inconsistent MOR control variables exposed by OVMF, breaks Windows Device Guard) + +* Fri May 12 2017 Miroslav Rezanina - 20170228-5.gitc325e41585e3.el7 +- ovmf-OvmfPkg-EnrollDefaultKeys-update-SignatureOwner-GUID.patch [bz#1443351] +- ovmf-OvmfPkg-EnrollDefaultKeys-expose-CertType-parameter-.patch [bz#1443351] +- ovmf-OvmfPkg-EnrollDefaultKeys-blacklist-empty-file-in-db.patch [bz#1443351] +- ovmf-OvmfPkg-introduce-the-FD_SIZE_IN_KB-macro-build-flag.patch [bz#1443351] +- ovmf-OvmfPkg-OvmfPkg.fdf.inc-extract-VARS_LIVE_SIZE-and-V.patch [bz#1443351] +- ovmf-OvmfPkg-introduce-4MB-flash-image-mainly-for-Windows.patch [bz#1443351] +- ovmf-OvmfPkg-raise-max-variable-size-auth-non-auth-to-33K.patch [bz#1443351] +- ovmf-OvmfPkg-PlatformPei-handle-non-power-of-two-spare-si.patch [bz#1443351] +- ovmf-redhat-update-local-build-instructions-with-D-FD_SIZ.patch [bz#1443351] +- ovmf-redhat-update-OVMF-build-commands-with-D-FD_SIZE_4MB.patch [bz#1443351] +- Resolves: bz#1443351 + ([svvp][ovmf] job "Secure Boot Logo Test" failed with q35&ovmf) + +* Fri Apr 28 2017 Miroslav Rezanina - 20170228-4.gitc325e41585e3.el7 +- ovmf-ShellPkg-Shell-clean-up-bogus-member-types-in-SPLIT_.patch [bz#1442908] +- ovmf-ShellPkg-Shell-eliminate-double-free-in-RunSplitComm.patch [bz#1442908] +- Resolves: bz#1442908 + (Guest hang when running a wrong command in Uefishell) + +* Tue Apr 04 2017 Miroslav Rezanina - 20170228-3.gitc325e41585e3.el7 +- ovmf-ArmVirtPkg-FdtClientDxe-supplement-missing-EFIAPI-ca.patch [bz#1430262] +- ovmf-ArmVirtPkg-ArmVirtPL031FdtClientLib-unconditionally-.patch [bz#1430262] +- ovmf-MdeModulePkg-RamDiskDxe-fix-C-string-literal-catenat.patch [bz#1430262] +- ovmf-EmbeddedPkg-introduce-EDKII-Platform-Has-ACPI-GUID.patch [bz#1430262] +- ovmf-EmbeddedPkg-introduce-PlatformHasAcpiLib.patch [bz#1430262] +- ovmf-EmbeddedPkg-introduce-EDKII-Platform-Has-Device-Tree.patch [bz#1430262] +- ovmf-ArmVirtPkg-add-PlatformHasAcpiDtDxe.patch [bz#1430262] +- ovmf-ArmVirtPkg-enable-AcpiTableDxe-and-EFI_ACPI_TABLE_PR.patch [bz#1430262] +- ovmf-ArmVirtPkg-FdtClientDxe-install-DT-as-sysconfig-tabl.patch [bz#1430262] +- ovmf-ArmVirtPkg-PlatformHasAcpiDtDxe-don-t-expose-DT-if-Q.patch [bz#1430262] +- ovmf-ArmVirtPkg-remove-PURE_ACPI_BOOT_ENABLE-and-PcdPureA.patch [bz#1430262] +- Resolves: bz#1430262 + (AAVMF: forward QEMU's DT to the guest OS only if ACPI payload is unavailable) + +* Mon Mar 27 2017 Miroslav Rezanina - 20170228-2.gitc325e41585e3.el7 +- ovmf-MdeModulePkg-Core-Dxe-downgrade-CodeSegmentCount-is-.patch [bz#1433428] +- Resolves: bz#1433428 + (AAVMF: Fix error message during ARM guest VM installation) + +* Wed Mar 08 2017 Laszlo Ersek - ovmf-20170228-1.gitc325e41585e3.el7 +- Rebase to upstream c325e41585e3 [bz#1416919] +- Resolves: bz#1373812 + (guest boot from network even set 'boot order=1' for virtio disk with OVMF) +- Resolves: bz#1380282 + (Update OVMF to openssl-1.0.2k-hobbled) +- Resolves: bz#1412313 + (select broadcast SMI if available) +- Resolves: bz#1416919 + (Rebase OVMF for RHEL-7.4) +- Resolves: bz#1426330 + (disable libssl in CryptoPkg) + +* Mon Sep 12 2016 Laszlo Ersek - ovmf-20160608b-1.git988715a.el7 +- rework downstream-only commit dde83a75b566 "setup the tree for the secure + boot feature (RHEL only)", excluding patent-encumbered files from the + upstream OpenSSL 1.0.2g tarball [bz#1374710] +- rework downstream-only commit dfc3ca1ee509 "CryptoPkg/OpensslLib: Upgrade + OpenSSL version to 1.0.2h", excluding patent-encumbered files from the + upstream OpenSSL 1.0.2h tarball [bz#1374710] + +* Thu Aug 04 2016 Miroslav Rezanina - OVMF-20160608-3.git988715a.el7 +- ovmf-MdePkg-PCI-Add-missing-PCI-PCIE-definitions.patch [bz#1332408] +- ovmf-ArmPlatformPkg-NorFlashDxe-accept-both-non-secure-an.patch [bz#1353494] +- ovmf-ArmVirtPkg-ArmVirtQemu-switch-secure-boot-build-to-N.patch [bz#1353494] +- ovmf-ArmPlatformPkg-NorFlashAuthenticatedDxe-remove-this-.patch [bz#1353494] +- ovmf-ArmVirtPkg-add-FDF-definition-for-empty-varstore.patch [bz#1353494] +- ovmf-redhat-package-the-varstore-template-produced-by-the.patch [bz#1353494] +- ovmf-ArmVirtPkg-Re-add-the-Driver-Health-Manager.patch [bz#1353494] +- ovmf-ArmVirtPkg-HighMemDxe-allow-patchable-PCD-for-PcdSys.patch [bz#1353494] +- ovmf-ArmVirtPkg-ArmVirtQemuKernel-make-ACPI-support-AARCH.patch [bz#1353494] +- ovmf-ArmVirtPkg-align-ArmVirtQemuKernel-with-ArmVirtQemu.patch [bz#1353494] +- ovmf-ArmVirtPkg-ArmVirtQemu-factor-out-shared-FV.FvMain-d.patch [bz#1353494] +- ovmf-ArmVirtPkg-factor-out-Rules-FDF-section.patch [bz#1353494] +- ovmf-ArmVirtPkg-add-name-GUIDs-to-FvMain-instances.patch [bz#1353494] +- ovmf-OvmfPkg-add-a-Name-GUID-to-each-Firmware-Volume.patch [bz#1353494] +- ovmf-OvmfPkg-PlatformBootManagerLib-remove-stale-FvFile-b.patch [bz#1353494] +- ovmf-MdePkg-IndustryStandard-introduce-EFI_PCI_CAPABILITY.patch [bz#1332408] +- ovmf-MdeModulePkg-PciBusDxe-look-for-the-right-capability.patch [bz#1332408] +- ovmf-MdeModulePkg-PciBusDxe-recognize-hotplug-capable-PCI.patch [bz#1332408] +- ovmf-OvmfPkg-add-PciHotPlugInitDxe.patch [bz#1332408] +- ovmf-ArmPkg-ArmGicLib-manage-GICv3-SPI-state-at-the-distr.patch [bz#1356655] +- ovmf-ArmVirtPkg-PlatformBootManagerLib-remove-stale-FvFil.patch [bz#1353494] +- ovmf-OvmfPkg-EnrollDefaultKeys-assign-Status-before-readi.patch [bz#1356913] +- ovmf-OvmfPkg-EnrollDefaultKeys-silence-VS2015x86-warning-.patch [bz#1356913] +- ovmf-CryptoPkg-update-openssl-to-ignore-RVCT-3079.patch [bz#1356184] +- ovmf-CryptoPkg-Fix-typos-in-comments.patch [bz#1356184] +- ovmf-CryptoPkg-BaseCryptLib-Avoid-passing-NULL-ptr-to-fun.patch [bz#1356184] +- ovmf-CryptoPkg-BaseCryptLib-Init-the-content-of-struct-Ce.patch [bz#1356184] +- ovmf-CryptoPkg-OpensslLib-Upgrade-OpenSSL-version-to-1.0..patch [bz#1356184] +- Resolves: bz#1332408 + (Q35 machine can not hot-plug scsi controller under switch) +- Resolves: bz#1353494 + ([OVMF] "EFI Internal Shell" should be removed from "Boot Manager") +- Resolves: bz#1356184 + (refresh embedded OpenSSL to 1.0.2h) +- Resolves: bz#1356655 + (AAVMF: stop accessing unmapped gicv3 registers) +- Resolves: bz#1356913 + (fix use-without-initialization in EnrollDefaultKeys.efi) + +* Tue Jul 12 2016 Miroslav Rezanina - OVMF-20160608-2.git988715a.el7 +- ovmf-ArmPkg-ArmGicV3Dxe-configure-all-interrupts-as-non-s.patch [bz#1349407] +- ovmf-ArmVirtPkg-PlatformBootManagerLib-Postpone-the-shell.patch [bz#1353689] +- Resolves: bz#1349407 + (AArch64: backport fix to run over gicv3 emulation) +- Resolves: bz#1353689 + (AAVMF: Drops to shell with uninitialized NVRAM file) + +* Thu Jun 9 2016 Laszlo Ersek - ovmf-20160608-1.git988715a.el7 +- Resolves: bz#1341733 + (prevent SMM stack overflow in OVMF while enrolling certificates in "db") +- Resolves: bz#1257882 + (FEAT: support to boot from virtio 1.0 modern devices) +- Resolves: bz#1333238 + (Q35 machine can not boot up successfully with more than 3 virtio-scsi + storage controller under switch) +- Resolves: bz#1330955 + (VM can not be booted up from hard disk successfully when with a passthrough + USB stick) + +* Thu May 19 2016 Laszlo Ersek - ovmf-20160419-2.git90bb4c5.el7 +- Submit scratch builds from the exploded tree again to + supp-rhel-7.3-candidate, despite FatPkg being OSS at this point; see + bz#1329559. + +* Wed Apr 20 2016 Laszlo Ersek - ovmf-20160419-1.git90bb4c5.el7 +- FatPkg is under the 2-clause BSDL now; "ovmf" has become OSS +- upgrade to openssl-1.0.2g +- Resolves: bz#1323363 + (remove "-D SECURE_BOOT_ENABLE" from AAVMF) +- Resolves: bz#1257882 + (FEAT: support to boot from virtio 1.0 modern devices) +- Resolves: bz#1308678 + (clearly separate SB-less, SMM-less OVMF binary from SB+SMM OVMF binary) + +* Fri Feb 19 2016 Miroslav Rezanina - OVMF-20160202-2.gitd7c0dfa.el7 +- ovmf-restore-TianoCore-splash-logo-without-OpenSSL-advert.patch [bz#1308678] +- ovmf-OvmfPkg-ArmVirtPkg-show-OpenSSL-less-logo-without-Se.patch [bz#1308678] +- ovmf-OvmfPkg-simplify-VARIABLE_STORE_HEADER-generation.patch [bz#1308678] +- ovmf-redhat-bring-back-OVMF_CODE.fd-but-without-SB-and-wi.patch [bz#1308678] +- ovmf-redhat-rename-OVMF_CODE.smm.fd-to-OVMF_CODE.secboot..patch [bz#1308678] + +* Tue Feb 2 2016 Laszlo Ersek - ovmf-20160202-1.gitd7c0dfa.el7 +- rebase to upstream d7c0dfa +- update OpenSSL to 1.0.2e (upstream) +- update FatPkg to SVN r97 (upstream) +- drive NVMe devices (upstream) +- resize xterm on serial console mode change, when requested with + -fw_cfg name=opt/(ovmf|aavmf)/PcdResizeXterm,string=y + (downstream) +- Resolves: bz#1259395 + (revert / roll back AAVMF fix for BZ 1188054) +- Resolves: bz#1202819 + (OVMF: secure boot limitations) +- Resolves: bz#1182495 + (OVMF rejects iPXE oprom when Secure Boot is enabled) + +* Thu Nov 5 2015 Laszlo Ersek - ovmf-20151104-1.gitb9ffeab.el7 +- rebase to upstream b9ffeab +- Resolves: bz#1207554 + ([AAVMF] AArch64: populate SMBIOS) +- Resolves: bz#1270279 + (AAVMF: output improvements) + +* Thu Jun 25 2015 Miroslav Rezanina - OVMF-20150414-2.gitc9e5618.el7 +- ovmf-OvmfPkg-PlatformPei-set-SMBIOS-entry-point-version-d.patch [bz#1232876] +- Resolves: bz#1232876 + (OVMF should install a version 2.8 SMBIOS entry point) + +* Sat Apr 18 2015 Laszlo Ersek - 20150414-1.gitc9e5618.el7 +- rebase from upstream 9ece15a to c9e5618 +- adapt .gitignore files +- update to openssl-0.9.8zf +- create Logo-OpenSSL.bmp rather than modifying Logo.bmp in-place +- update to FatPkg SVN r93 (git 8ff136aa) +- drop the following downstream-only patches (obviated by upstream + counterparts): + "tools_def.template: use forward slash with --add-gnu-debuglink (RHEL only)" + "tools_def.template: take GCC48 prefixes from environment (RHEL only)" + "OvmfPkg: set video resolution of text setup to 640x480 (RHEL only)" + "OvmfPkg: resolve OrderedCollectionLib with base red-black tree instance" + "OvmfPkg: AcpiPlatformDxe: actualize QemuLoader.h comments" + "OvmfPkg: AcpiPlatformDxe: remove current ACPI table loader" + "OvmfPkg: AcpiPlatformDxe: implement QEMU's full ACPI table loader interface" + "OvmfPkg: QemuVideoDxe: fix querying of QXL's drawable buffer size" + "OvmfPkg: disable stale fork of SecureBootConfigDxe" + "OvmfPkg: SecureBootConfigDxe: remove stale fork" + "Try to read key strike even when ..." + "OvmfPkg: BDS: remove dead call to PlatformBdsEnterFrontPage()" + "OvmfPkg: BDS: drop useless return statement" + "OvmfPkg: BDS: don't overwrite the BDS Front Page timeout" + "OvmfPkg: BDS: optimize second argument in PlatformBdsEnterFrontPage() call" + 'OvmfPkg: BDS: drop superfluous "connect first boot option" logic' + "OvmfPkg: BDS: drop custom boot timeout, revert to IntelFrameworkModulePkg's" + "Add comments to clarify mPubKeyStore buffer MemCopy. ..." + "MdeModulePkg/SecurityPkg Variable: Add boundary check..." + "OvmfPkg: AcpiPlatformDxe: make dependency on PCI enumeration explicit" + "MdePkg: UefiScsiLib: do not encode LUN in CDB for READ and WRITE" + "MdePkg: UefiScsiLib: do not encode LUN in CDB for other SCSI commands" +- merge downstream AAVMF patch "adapt packaging to Arm64", which forces us to + rename the main package from "OVMF" to "ovmf" +- drop the following ARM BDS specific tweaks (we'll only build the Intel BDS): + "ArmPlatformPkg/Bds: generate ESP Image boot option if user pref is unset + (Acadia)" + "ArmPlatformPkg/Bds: check for other defaults too if user pref is unset + (Acadia)" + "ArmPlatformPkg/ArmVirtualizationPkg: auto-detect boot path (Acadia)" + "ArmPlatformPkg/Bds: initialize ConIn/ConOut/ErrOut before connecting + terminals" + "ArmPlatformPkg/Bds: let FindCandidate() search all filesystems" + "ArmPlatformPkg/Bds: FindCandidateOnHandle(): log full device path" + "ArmPlatformPkg/Bds: fall back to Boot Menu when no default option was found" + "ArmPlatformPkg/Bds: always connect drivers before looking at boot options" +- drop patch "ArmPlatformPkg/ArmVirtualizationPkg: enable DEBUG_VERBOSE (Acadia + only)", obsoleted by fixed bug 1197141 +- tweak patch "write up build instructions (for interactive, local development) + (RHELSA)". The defaults in "BaseTools/Conf/target.template", ie. + ACTIVE_PLATFORM and TARGET_ARCH, are set for OVMF / X64. The AAVMF build + instructions now spell out the necessary override options (-p and -a, + respectively). +- extend patch "build FAT driver from source (RHELSA)" to the Xen build as well + (only for consistency; we don't build for Xen). +- drop the following downstream-only AAVMF patches, due to the 77d5dac -> + c9e5618 AAVMF rebase & join: + "redhat/process-rh-specific.sh: fix check for hunk-less filtered patches" + "redhat/process-rh-specific.sh: suppress missing files in final 'rm'" + "ArmVirtualizationQemu: build UEFI shell from source (Acadia only)" + "MdePkg: UefiScsiLib: do not encode LUN in CDB for READ and WRITE" + "MdePkg: UefiScsiLib: do not encode LUN in CDB for other SCSI commands" + "ArmVirtualizationPkg: work around cache incoherence on KVM affecting DTB" + "Changed build target to supp-rhel-7.1-candidate" + "ArmVirtualizationPkg: VirtFdtDxe: forward FwCfg addresses from DTB to PCDs" + "ArmVirtualizationPkg: introduce QemuFwCfgLib instance for DXE drivers" + "ArmVirtualizationPkg: clone PlatformIntelBdsLib from ArmPlatformPkg" + "ArmVirtualizationPkg: PlatformIntelBdsLib: add basic policy" + "OvmfPkg: extract QemuBootOrderLib" + "OvmfPkg: QemuBootOrderLib: featurize PCI-like device path translation" + "OvmfPkg: introduce VIRTIO_MMIO_TRANSPORT_GUID" + "ArmVirtualizationPkg: VirtFdtDxe: use dedicated VIRTIO_MMIO_TRANSPORT_GUID" + "OvmfPkg: QemuBootOrderLib: widen ParseUnitAddressHexList() to UINT64" + "OvmfPkg: QemuBootOrderLib: OFW-to-UEFI translation for virtio-mmio" + "ArmVirtualizationPkg: PlatformIntelBdsLib: adhere to QEMU's boot order" + "ArmVirtualizationPkg: identify "new shell" as builtin shell for Intel BDS" + "ArmVirtualizationPkg: Intel BDS: load EFI-stubbed Linux kernel from fw_cfg" + 'Revert "ArmVirtualizationPkg: work around cache incoherence on KVM affecting + DTB"' + "OvmfPkg: QemuBootOrderLib: expose QEMU's "-boot menu=on[, splash-time=N]"" + "OvmfPkg: PlatformBdsLib: get front page timeout from QEMU" + "ArmVirtualizationPkg: PlatformIntelBdsLib: get front page timeout from QEMU" + "ArmPkg: ArmArchTimerLib: clean up comments" + "ArmPkg: ArmArchTimerLib: use edk2-conformant (UINT64 * UINT32) / UINT32" + "ArmPkg: ArmArchTimerLib: conditionally rebase to actual timer frequency" + "ArmVirtualizationQemu: ask the hardware for the timer frequency" + "ArmPkg: DebugPeCoffExtraActionLib: debugger commands are not errors" + "ArmPlatformPkg: PEIM startup is not an error" + "ArmVirtualizationPkg: PlatformIntelBdsLib: lack of QEMU kernel is no error" + "ArmVirtualizationPkg: expose debug message bitmask on build command line" +- tweak patch "rebase to upstream 77d5dac (Acadia only)": update spec changelog + only +- tweak patch "spec: build AAVMF with the Intel BDS driver (RHELSA only)": + apply "-D INTEL_BDS" to manual build instructions in redhat/README too +- tweak patch "spec: build and install verbose and silent (default) AAVMF + binaries": apply DEBUG_PRINT_ERROR_LEVEL setting to interactive build + instructions in redhat/README too +- install OVMF whitepaper as part of the OVMF build's documentation +- Resolves: bz#1211337 + (merge AAVMF into OVMF) +- Resolves: bz#1206523 + ([AAVMF] fix missing cache maintenance) + +* Fri Mar 06 2015 Miroslav Rezanina - AAVMF-20141113-5.git77d5dac.el7_1 +- aavmf-ArmPkg-DebugPeCoffExtraActionLib-debugger-commands-a.patch [bz#1197141] +- aavmf-ArmPlatformPkg-PEIM-startup-is-not-an-error.patch [bz#1197141] +- aavmf-ArmVirtualizationPkg-PlatformIntelBdsLib-lack-of-QEM.patch [bz#1197141] +- aavmf-ArmVirtualizationPkg-expose-debug-message-bitmask-on.patch [bz#1197141] +- aavmf-spec-build-and-install-verbose-and-silent-default-AA.patch [bz#1197141] +- Resolves: bz#1197141 + (create silent & verbose builds) + +* Tue Feb 10 2015 Miroslav Rezanina - AAVMF-20141113-4.git77d5dac.el7 +- aavmf-ArmPkg-ArmArchTimerLib-clean-up-comments.patch [bz#1188247] +- aavmf-ArmPkg-ArmArchTimerLib-use-edk2-conformant-UINT64-UI.patch [bz#1188247] +- aavmf-ArmPkg-ArmArchTimerLib-conditionally-rebase-to-actua.patch [bz#1188247] +- aavmf-ArmVirtualizationQemu-ask-the-hardware-for-the-timer.patch [bz#1188247] +- aavmf-ArmPkg-TimerDxe-smack-down-spurious-timer-interrupt-.patch [bz#1188054] +- Resolves: bz#1188054 + (guest reboot (asked from within AAVMF) regressed in 3.19.0-0.rc5.58.aa7a host kernel) +- Resolves: bz#1188247 + (backport "fix gBS->Stall()" series) + +* Mon Jan 19 2015 Miroslav Rezanina - AAVMF-20141113-3.git77d5dac.el7 +- aavmf-OvmfPkg-QemuBootOrderLib-expose-QEMU-s-boot-menu-on-.patch [bz#1172756] +- aavmf-OvmfPkg-PlatformBdsLib-get-front-page-timeout-from-Q.patch [bz#1172756] +- aavmf-ArmVirtualizationPkg-PlatformIntelBdsLib-get-front-p.patch [bz#1172756] +- Resolves: bz#1172756 + ([RFE]Expose boot-menu shortcut to domain via AAVMF) + +* Wed Jan 14 2015 Miroslav Rezanina - AAVMF-20141113-2.git77d5dac.el7 +- aavmf-ArmVirtualizationPkg-VirtFdtDxe-forward-FwCfg-addres.patch [bz#1172749] +- aavmf-ArmVirtualizationPkg-introduce-QemuFwCfgLib-instance.patch [bz#1172749] +- aavmf-ArmVirtualizationPkg-clone-PlatformIntelBdsLib-from-.patch [bz#1172749] +- aavmf-ArmVirtualizationPkg-PlatformIntelBdsLib-add-basic-p.patch [bz#1172749] +- aavmf-OvmfPkg-extract-QemuBootOrderLib.patch [bz#1172749] +- aavmf-OvmfPkg-QemuBootOrderLib-featurize-PCI-like-device-p.patch [bz#1172749] +- aavmf-OvmfPkg-introduce-VIRTIO_MMIO_TRANSPORT_GUID.patch [bz#1172749] +- aavmf-ArmVirtualizationPkg-VirtFdtDxe-use-dedicated-VIRTIO.patch [bz#1172749] +- aavmf-OvmfPkg-QemuBootOrderLib-widen-ParseUnitAddressHexLi.patch [bz#1172749] +- aavmf-OvmfPkg-QemuBootOrderLib-OFW-to-UEFI-translation-for.patch [bz#1172749] +- aavmf-ArmVirtualizationPkg-PlatformIntelBdsLib-adhere-to-Q.patch [bz#1172749] +- aavmf-ArmVirtualizationPkg-identify-new-shell-as-builtin-s.patch [bz#1172749] +- aavmf-ArmVirtualizationPkg-Intel-BDS-load-EFI-stubbed-Linu.patch [bz#1172749] +- aavmf-spec-build-AAVMF-with-the-Intel-BDS-driver-RHELSA-on.patch [bz#1172749] +- aavmf-Revert-ArmVirtualizationPkg-work-around-cache-incohe.patch [bz#1172910] +- Resolves: bz#1172749 + (implement fw_cfg, boot order handling, and -kernel booting in ArmVirtualizationQemu) +- Resolves: bz#1172910 + (revert Acadia-only workaround (commit df7bca4e) once Acadia host kernel (KVM) is fixed) + +* Fri Dec 05 2014 Miroslav Rezanina - OVMF-20140822-7.git9ece15a.el7 +- ovmf-MdePkg-UefiScsiLib-do-not-encode-LUN-in-CDB-for-READ.patch [bz#1166971] +- ovmf-MdePkg-UefiScsiLib-do-not-encode-LUN-in-CDB-for-othe.patch [bz#1166971] +- Resolves: bz#1166971 + (virtio-scsi disks and cd-roms with nonzero LUN are rejected with errors) + +* Tue Nov 25 2014 Miroslav Rezanina - OVMF-20140822-6.git9ece15a.el7 +- ovmf-OvmfPkg-AcpiPlatformDxe-make-dependency-on-PCI-enume.patch [bz#1166027] +- Resolves: bz#1166027 + (backport "OvmfPkg: AcpiPlatformDxe: make dependency on PCI enumeration explicit") + +* Tue Nov 18 2014 Miroslav Rezanina - OVMF-20140822-4.git9ece15a.el7 +- ovmf-Add-comments-to-clarify-mPubKeyStore-buffer-MemCopy.patch [bz#1162314] +- ovmf-MdeModulePkg-SecurityPkg-Variable-Add-boundary-check.patch [bz#1162314] +- Resolves: bz#1162314 + (EMBARGOED OVMF: uefi: INTEL-TA-201410-001 && INTEL-TA-201410-002 [rhel-7.1]) + +* Thu Nov 13 2014 Laszlo Ersek - AAVMF-20141113-1.git77d5dac +- rebased to upstream 77d5dac + +- patch "ArmVirtualizationPkg: FdtPL011SerialPortLib: support UEFI_APPLICATION" + is now upstream (SVN r16219, git edb5073) + +* Thu Nov 13 2014 Miroslav Rezanina - OVMF-20140822-3.git9ece15a.el7 +- ovmf-Revert-OvmfPkg-set-video-resolution-of-text-setup-to.patch [bz#1153927] +- ovmf-Try-to-read-key-strike-even-when-the-TimeOuts-value-.patch [bz#1153927] +- ovmf-OvmfPkg-BDS-remove-dead-call-to-PlatformBdsEnterFron.patch [bz#1153927] +- ovmf-OvmfPkg-BDS-drop-useless-return-statement.patch [bz#1153927] +- ovmf-OvmfPkg-BDS-don-t-overwrite-the-BDS-Front-Page-timeo.patch [bz#1153927] +- ovmf-OvmfPkg-BDS-optimize-second-argument-in-PlatformBdsE.patch [bz#1153927] +- ovmf-OvmfPkg-BDS-drop-superfluous-connect-first-boot-opti.patch [bz#1153927] +- ovmf-OvmfPkg-BDS-drop-custom-boot-timeout-revert-to-Intel.patch [bz#1153927] +- ovmf-OvmfPkg-set-video-resolution-of-text-setup-to-640x48.patch [bz#1153927] +- Resolves: bz#1153927 + (set NEXTBOOT to uefi setting failed from Windows Recovery console) + +* Tue Nov 11 2014 Miroslav Rezanina - OVMF-20140822-2.git9ece15a +- ovmf-redhat-process-rh-specific.sh-suppress-missing-files.patch [bz#1145784] +- ovmf-Revert-RH-only-OvmfPkg-QemuVideoDxe-fix-querying-of-.patch [bz#1145784] +- ovmf-Revert-RH-only-OvmfPkg-AcpiPlatformDxe-implement-QEM.patch [bz#1145784] +- ovmf-Revert-RH-only-OvmfPkg-AcpiPlatformDxe-remove-curren.patch [bz#1145784] +- ovmf-Revert-RH-only-OvmfPkg-AcpiPlatformDxe-actualize-Qem.patch [bz#1145784] +- ovmf-Revert-RH-only-OvmfPkg-resolve-OrderedCollectionLib-.patch [bz#1145784] +- ovmf-OvmfPkg-QemuVideoDxe-work-around-misreported-QXL-fra.patch [bz#1145784] +- ovmf-OvmfPkg-resolve-OrderedCollectionLib-with-base-red-b.patch [bz#1145784] +- ovmf-OvmfPkg-AcpiPlatformDxe-actualize-QemuLoader.h-comme.patch [bz#1145784] +- ovmf-OvmfPkg-AcpiPlatformDxe-remove-current-ACPI-table-lo.patch [bz#1145784] +- ovmf-OvmfPkg-AcpiPlatformDxe-implement-QEMU-s-full-ACPI-t.patch [bz#1145784] +- ovmf-spec-build-small-bootable-ISO-with-standalone-UEFI-s.patch [bz#1147592] +- ovmf-OvmfPkg-allow-exclusion-of-the-shell-from-the-firmwa.patch [bz#1147592] +- ovmf-spec-exclude-the-UEFI-shell-from-the-SecureBoot-enab.patch [bz#1147592] +- ovmf-OvmfPkg-EnrollDefaultKeys-application-for-enrolling-.patch [bz#1148296] +- ovmf-spec-package-EnrollDefaultKeys.efi-on-UefiShell.iso-.patch [bz#1148296] +- ovmf-OvmfPkg-disable-stale-fork-of-SecureBootConfigDxe.patch [bz#1148294] +- ovmf-OvmfPkg-SecureBootConfigDxe-remove-stale-fork.patch [bz#1148294] +- Resolves: bz#1145784 + (OVMF sync with QXL and ACPI patches up to edk2 7a9612ce) +- Resolves: bz#1147592 + (the binary RPM should include a small ISO file with a directly bootable UEFI shell binary) +- Resolves: bz#1148294 + (drop OvmfPkg's stale fork of SecureBootConfigDxe) +- Resolves: bz#1148296 + (provide a non-interactive way to auto-enroll important SecureBoot certificates) + +* Wed Oct 15 2014 Laszlo Ersek - AAVMF-20141015-1.gitc373687 +- ported packaging to aarch64 / AAVMF + +* Fri Aug 22 2014 Laszlo Ersek - 20140822-1.git9ece15a.el7 +- rebase from upstream 3facc08 to 9ece15a +- update to openssl-0.9.8zb +- update to FatPkg SVN r86 (git 2355ea2c) +- the following patches of Paolo Bonzini have been merged in upstream; drop the + downstream-only copies: + 7bc1421 edksetup.sh: Look for BuildEnv under EDK_TOOLS_PATH + d549344 edksetup.sh: Ensure that WORKSPACE points to the top of an edk2 + checkout + 1c023eb BuildEnv: remove useless check before setting $WORKSPACE +- include the following patches that have been pending review on the upstream + list for a long time: + [PATCH 0/4] OvmfPkg: complete client for QEMU's ACPI loader interface + http://thread.gmane.org/gmane.comp.bios.tianocore.devel/8369 + [PATCH] OvmfPkg: QemuVideoDxe: fix querying of QXL's drawable buffer size + http://thread.gmane.org/gmane.comp.bios.tianocore.devel/8515 +- nasm is a build-time dependency now because upstream BuildTools has started + to call it directly + +* Wed Jul 23 2014 Laszlo Ersek - 20140723-1.git3facc08.el7 +- rebase from upstream a618eaa to 3facc08 +- update to openssl-0.9.8za +- drop downstream-only split varstore patch, rely on upstream's + +* Tue Jun 24 2014 Miroslav Rezanina - 20140619-1.gita618eaa.el7 +- Initial version