public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​
@ 2023-11-27 18:17 Taylor Beebe
  2023-11-27 18:17 ` [edk2-devel] [PATCH v5 01/16] MdeModulePkg: Add ImagePropertiesRecordLib Taylor Beebe
                   ` (16 more replies)
  0 siblings, 17 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:17 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Ard Biesheuvel, Dandan Bi, Eric Dong, Gerd Hoffmann,
	Guo Dong, Gua Guo, James Lu, Jian J Wang, Jiewen Yao,
	Jordan Justen, Leif Lindholm, Liming Gao, Rahul Kumar, Ray Ni,
	Sami Mujawar, Sean Rhodes, Lazlo Ersek

v5:
This version is purely an update of commit messages and orientation.
No code changes were made.
- Split patch 9 into 3 separate patches so each fix is in its own
  commit.
- Updated the commit comment of patch 11 to add context.

v4:
- Expose additional functions in the Library API
- Add NULL checks to library functions and return a
  status where applicable.

v3:
- Refactor patch series so the transition of logic from the DXE
  MAT logic to the new library is more clear.
- Update function headers to improve clarity and follow EDK2
  standards.
- Add Create and Delete functions for Image Properties Records
  and redirect some of the SMM and DXE MAT code to use these
  functions.
- Update/Add DumpImageRecords() to print the image name and code
  sections of each runtime image which will be put in the MAT.
  The DXE and SMM MAT logic will now invoke the DumpImageRecords()
  on DEBUG builds at the EndOfDxe event to install the MAT.

v2:
- A one-line change in patch 3 was moved to patch 9 for correctness.

Reference: https://github.com/tianocore/edk2/pull/4590
Bugzilla: https://bugzilla.tianocore.org/show_bug.cgi?id=4492

The UEFI and SMM MAT logic contains duplicate logic for manipulating image
properties records which is used to track runtime images.
This patch series adds a new library, ImagePropertiesRecordLib,
which consolidates this logic and fixes the bugs which currently exist in
the MAT logic.

The first patch adds the ImagePropertiesRecordLib implementation which
is a copy of the UEFI MAT logic with minor modifications to remove the
reliance on globabl variables and make the code unit testable.

The second patch adds a unit test for the ImagePropertiesRecordLib. The
logic tests various potential layouts of the EFI memory map and runtime
images. 3/4 of these tests will fail which demonstrates the MAT logic
bugs.

The third patch fixes the logic in the ImagePropertiesRecordLib so
that all of the unit tests pass and the MAT logic can be fixed by
using the library.

The remaining patches add library instances to DSC files and remove
the image properties record logic from the SMM and UEFI MAT logic.

Cc: Andrew Fish <afish@apple.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Guo Dong <guo.dong@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Cc: James Lu <james.lu@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Sean Rhodes <sean@starlabs.systems>
Cc: Lazlo Ersek <lersek@redhat.com>

Taylor Beebe (16):
  MdeModulePkg: Add ImagePropertiesRecordLib
  ArmVirtPkg: Add ImagePropertiesRecordLib Instance
  EmulatorPkg: Add ImagePropertiesRecordLib Instance
  OvmfPkg: Add ImagePropertiesRecordLib Instance
  UefiPayloadPkg: Add ImagePropertiesRecordLib Instance
  MdeModulePkg: Update MemoryAttributesTable.c to Reduce Global Variable
    Use
  MdeModulePkg: Move Some DXE MAT Logic to ImagePropertiesRecordLib
  MdeModulePkg: Add ImagePropertiesRecordLib Host-Based Unit Test
  MdeModulePkg: Fix MAT Descriptor Count Calculation
  MdeModulePkg: Fix MAT SplitRecord() Logic
  MdeModulePkg: Fix MAT SplitTable() Logic
  MdeModulePkg: Add NULL checks and Return Status to
    ImagePropertiesRecordLib
  UefiCpuPkg: Use Attribute From SMM MemoryAttributesTable if Nonzero
  MdeModulePkg: Transition SMM MAT Logic to Use ImagePropertiesRecordLib
  MdeModulePkg: Add Logic to Create/Delete Image Properties Records
  MdeModulePkg: Update DumpImageRecord() in ImagePropertiesRecordLib

 MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c                                              |  967 +----------------
 MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c                                                   |   24 +-
 MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c                                             |  958 +---------------
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c                        | 1144 ++++++++++++++++++++
 MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.c   |  938 ++++++++++++++++
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c                                              |   19 +-
 ArmVirtPkg/ArmVirt.dsc.inc                                                                      |    1 +
 EmulatorPkg/EmulatorPkg.dsc                                                                     |    1 +
 MdeModulePkg/Core/Dxe/DxeMain.h                                                                 |   20 -
 MdeModulePkg/Core/Dxe/DxeMain.inf                                                               |    1 +
 MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf                                                       |    1 +
 MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h                                         |  234 ++++
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf                      |   31 +
 MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.inf |   35 +
 MdeModulePkg/MdeModulePkg.dec                                                                   |    5 +
 MdeModulePkg/MdeModulePkg.dsc                                                                   |    2 +
 MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                                      |    6 +
 OvmfPkg/AmdSev/AmdSevX64.dsc                                                                    |    1 +
 OvmfPkg/Bhyve/BhyveX64.dsc                                                                      |    1 +
 OvmfPkg/CloudHv/CloudHvX64.dsc                                                                  |    1 +
 OvmfPkg/IntelTdx/IntelTdxX64.dsc                                                                |    1 +
 OvmfPkg/Microvm/MicrovmX64.dsc                                                                  |    1 +
 OvmfPkg/OvmfPkgIa32.dsc                                                                         |    1 +
 OvmfPkg/OvmfPkgIa32X64.dsc                                                                      |    1 +
 OvmfPkg/OvmfPkgX64.dsc                                                                          |    1 +
 OvmfPkg/OvmfXen.dsc                                                                             |    1 +
 OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc                                                             |    1 +
 UefiPayloadPkg/UefiPayloadPkg.dsc                                                               |    1 +
 28 files changed, 2524 insertions(+), 1874 deletions(-)
 create mode 100644 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
 create mode 100644 MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.c
 create mode 100644 MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
 create mode 100644 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 create mode 100644 MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.inf

-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111737): https://edk2.groups.io/g/devel/message/111737
Mute This Topic: https://groups.io/mt/102834905/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 01/16] MdeModulePkg: Add ImagePropertiesRecordLib
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
@ 2023-11-27 18:17 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 02/16] ArmVirtPkg: Add ImagePropertiesRecordLib Instance Taylor Beebe
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:17 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Liming Gao, Dandan Bi

Create a library for manipulating image properties records. The
library is currently blank and will be filled in a future patch
to help with reviewer readability.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c   |  9 +++++++
 MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h                    | 14 +++++++++++
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf | 25 ++++++++++++++++++++
 MdeModulePkg/MdeModulePkg.dec                                              |  5 ++++
 MdeModulePkg/MdeModulePkg.dsc                                              |  2 ++
 5 files changed, 55 insertions(+)

diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
new file mode 100644
index 000000000000..df7c54ebb793
--- /dev/null
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
@@ -0,0 +1,9 @@
+/** @file
+
+  Provides definitions and functionality for manipulating IMAGE_PROPERTIES_RECORD.
+
+  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) Microsoft Corporation.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
diff --git a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
new file mode 100644
index 000000000000..728008a2e5bb
--- /dev/null
+++ b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
@@ -0,0 +1,14 @@
+/** @file
+
+  Provides definitions and functionality for manipulating IMAGE_PROPERTIES_RECORD.
+
+  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) Microsoft Corporation.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_
+#define IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_
+
+#endif
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
new file mode 100644
index 000000000000..b7e493056889
--- /dev/null
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
@@ -0,0 +1,25 @@
+## @file
+#  Provides definitions and functionality for manipulating
+#  IMAGE_PROPERTIES_RECORD.
+#
+#  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) Microsoft Corporation.
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = ImagePropertiesRecordLib
+  FILE_GUID                      = 5CCA36C1-C430-4A90-8BF7-23D2719D5928
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ImagePropertiesRecordLib
+
+[Sources.common]
+  ImagePropertiesRecordLib.c
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index d2fede4f87c0..1a162e97e6fb 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -164,6 +164,11 @@ [LibraryClasses]
   #
   VariableFlashInfoLib|Include/Library/VariableFlashInfoLib.h
 
+  ##  @libraryclass   Memory Attribute Table support logic for tracking and reporting
+  #                   runtime images
+  #
+  ImagePropertiesRecordLib|Include/Library/ImagePropertiesRecordLib.h
+
 [Guids]
   ## MdeModule package token space guid
   # Include/Guid/MdeModulePkgTokenSpace.h
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index c7af921782ee..6b3052ff4614 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -96,6 +96,7 @@ [LibraryClasses]
   VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
   FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
   NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
   FmpAuthenticationLib|MdeModulePkg/Library/FmpAuthenticationLibNull/FmpAuthenticationLibNull.inf
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
@@ -237,6 +238,7 @@ [Components]
   MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
   MdeModulePkg/Library/BaseMemoryAllocationLibNull/BaseMemoryAllocationLibNull.inf
   MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
+  MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
   MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
   MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111738): https://edk2.groups.io/g/devel/message/111738
Mute This Topic: https://groups.io/mt/102834906/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 02/16] ArmVirtPkg: Add ImagePropertiesRecordLib Instance
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
  2023-11-27 18:17 ` [edk2-devel] [PATCH v5 01/16] MdeModulePkg: Add ImagePropertiesRecordLib Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 03/16] EmulatorPkg: " Taylor Beebe
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel
  Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Gerd Hoffmann,
	Michael D Kinney

Add an instance of ImagePropertiesRecordLib which will be used by the
DXE Core.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
---
 ArmVirtPkg/ArmVirt.dsc.inc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ArmVirtPkg/ArmVirt.dsc.inc b/ArmVirtPkg/ArmVirt.dsc.inc
index fe6488ee9910..6bc72f1decbd 100644
--- a/ArmVirtPkg/ArmVirt.dsc.inc
+++ b/ArmVirtPkg/ArmVirt.dsc.inc
@@ -52,6 +52,7 @@ [LibraryClasses.common]
   IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf
   UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
   CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
   UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
   HobLib|ArmVirtPkg/Library/ArmVirtDxeHobLib/ArmVirtDxeHobLib.inf
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111739): https://edk2.groups.io/g/devel/message/111739
Mute This Topic: https://groups.io/mt/102834907/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 03/16] EmulatorPkg: Add ImagePropertiesRecordLib Instance
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
  2023-11-27 18:17 ` [edk2-devel] [PATCH v5 01/16] MdeModulePkg: Add ImagePropertiesRecordLib Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 02/16] ArmVirtPkg: Add ImagePropertiesRecordLib Instance Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 04/16] OvmfPkg: " Taylor Beebe
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Andrew Fish, Ray Ni, Michael D Kinney

Add an instance of ImagePropertiesRecordLib which will be used by the
DXE Core.

Cc: Andrew Fish <afish@apple.com>
Cc: Ray Ni <ray.ni@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
---
 EmulatorPkg/EmulatorPkg.dsc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc
index b14654739b54..85134b07816e 100644
--- a/EmulatorPkg/EmulatorPkg.dsc
+++ b/EmulatorPkg/EmulatorPkg.dsc
@@ -126,6 +126,7 @@ [LibraryClasses]
   SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
   ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
   FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   RngLib|MdeModulePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111740): https://edk2.groups.io/g/devel/message/111740
Mute This Topic: https://groups.io/mt/102834908/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 04/16] OvmfPkg: Add ImagePropertiesRecordLib Instance
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (2 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 03/16] EmulatorPkg: " Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 05/16] UefiPayloadPkg: " Taylor Beebe
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel
  Cc: Ard Biesheuvel, Jiewen Yao, Jordan Justen, Gerd Hoffmann,
	Michael D Kinney, Jiewen Yao

Add an instance of ImagePropertiesRecordLib which will be used by the
DXE Core.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
Acked-by: Jiewen Yao <Jiewen.yao@intel.com>
---
 OvmfPkg/AmdSev/AmdSevX64.dsc        | 1 +
 OvmfPkg/Bhyve/BhyveX64.dsc          | 1 +
 OvmfPkg/CloudHv/CloudHvX64.dsc      | 1 +
 OvmfPkg/IntelTdx/IntelTdxX64.dsc    | 1 +
 OvmfPkg/Microvm/MicrovmX64.dsc      | 1 +
 OvmfPkg/OvmfPkgIa32.dsc             | 1 +
 OvmfPkg/OvmfPkgIa32X64.dsc          | 1 +
 OvmfPkg/OvmfPkgX64.dsc              | 1 +
 OvmfPkg/OvmfXen.dsc                 | 1 +
 OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc | 1 +
 10 files changed, 10 insertions(+)

diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc
index 302c90e7c2b4..3a1f788eb37f 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.dsc
+++ b/OvmfPkg/AmdSev/AmdSevX64.dsc
@@ -171,6 +171,7 @@ [LibraryClasses]
   MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
   PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
   DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
   PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
diff --git a/OvmfPkg/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc
index 6693342c5f6e..8f0cd93a2d6c 100644
--- a/OvmfPkg/Bhyve/BhyveX64.dsc
+++ b/OvmfPkg/Bhyve/BhyveX64.dsc
@@ -173,6 +173,7 @@ [LibraryClasses]
   MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
   PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
   DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
   CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
   FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
diff --git a/OvmfPkg/CloudHv/CloudHvX64.dsc b/OvmfPkg/CloudHv/CloudHvX64.dsc
index c23c7eaf6cc2..821ad1b9fab2 100644
--- a/OvmfPkg/CloudHv/CloudHvX64.dsc
+++ b/OvmfPkg/CloudHv/CloudHvX64.dsc
@@ -182,6 +182,7 @@ [LibraryClasses]
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
   PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
   DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 !if $(SMM_REQUIRE) == FALSE
   LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
 !endif
diff --git a/OvmfPkg/IntelTdx/IntelTdxX64.dsc b/OvmfPkg/IntelTdx/IntelTdxX64.dsc
index 182ec3705dd3..0ed36daf7c44 100644
--- a/OvmfPkg/IntelTdx/IntelTdxX64.dsc
+++ b/OvmfPkg/IntelTdx/IntelTdxX64.dsc
@@ -171,6 +171,7 @@ [LibraryClasses]
   MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
   PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
   DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
   LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
   CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
diff --git a/OvmfPkg/Microvm/MicrovmX64.dsc b/OvmfPkg/Microvm/MicrovmX64.dsc
index ea1fa3e2963f..8817006f90c4 100644
--- a/OvmfPkg/Microvm/MicrovmX64.dsc
+++ b/OvmfPkg/Microvm/MicrovmX64.dsc
@@ -185,6 +185,7 @@ [LibraryClasses]
   MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
   PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
   DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
   PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index ed3a19feebe6..bce2aedcd781 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -187,6 +187,7 @@ [LibraryClasses]
   MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLibNull.inf
   PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
   DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 !if $(SMM_REQUIRE) == FALSE
   LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
 !endif
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 16ca139b2973..631e909a543d 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -192,6 +192,7 @@ [LibraryClasses]
   MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLibNull.inf
   PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
   DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 !if $(SMM_REQUIRE) == FALSE
   LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
 !endif
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index dc1a0942aa8b..4ea3008cc69a 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -204,6 +204,7 @@ [LibraryClasses]
   MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
   PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
   DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
 !if $(SMM_REQUIRE) == FALSE
   LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc
index 0063245b5659..ddaa441cabff 100644
--- a/OvmfPkg/OvmfXen.dsc
+++ b/OvmfPkg/OvmfXen.dsc
@@ -176,6 +176,7 @@ [LibraryClasses]
   MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf
   PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
   DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
   PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
diff --git a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc
index 34b2037824f1..f8b9479345d7 100644
--- a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc
+++ b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc
@@ -101,6 +101,7 @@ [LibraryClasses.common]
   PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf
   PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
   PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 
 !if $(TPM2_ENABLE) == TRUE
   Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111741): https://edk2.groups.io/g/devel/message/111741
Mute This Topic: https://groups.io/mt/102834911/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 05/16] UefiPayloadPkg: Add ImagePropertiesRecordLib Instance
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (3 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 04/16] OvmfPkg: " Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 06/16] MdeModulePkg: Update MemoryAttributesTable.c to Reduce Global Variable Use Taylor Beebe
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Guo Dong, Sean Rhodes, James Lu, Gua Guo, Michael D Kinney

Add an instance of ImagePropertiesRecordLib which will be used by the
DXE Core.

Cc: Guo Dong <guo.dong@intel.com>
Cc: Sean Rhodes <sean@starlabs.systems>
Cc: James Lu <james.lu@intel.com>
Cc: Gua Guo <gua.guo@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Gua Guo <gua.guo@intel.com>
---
 UefiPayloadPkg/UefiPayloadPkg.dsc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc
index af9308ef8ed7..a65f9d5b831a 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkg.dsc
@@ -284,6 +284,7 @@ [LibraryClasses]
   #
   DebugPrintErrorLevelLib|UefiPayloadPkg/Library/DebugPrintErrorLevelLibHob/DebugPrintErrorLevelLibHob.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+  ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
 !if $(SOURCE_DEBUG_ENABLE) == TRUE
   PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
   DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111742): https://edk2.groups.io/g/devel/message/111742
Mute This Topic: https://groups.io/mt/102834912/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 06/16] MdeModulePkg: Update MemoryAttributesTable.c to Reduce Global Variable Use
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (4 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 05/16] UefiPayloadPkg: " Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 07/16] MdeModulePkg: Move Some DXE MAT Logic to ImagePropertiesRecordLib Taylor Beebe
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Liming Gao, Dandan Bi

This patch updates MemoryAttributesTable.c to reduce reliance on global
variables and allow some logic to move to a library.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c | 102 +++++++++++---------
 1 file changed, 54 insertions(+), 48 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
index fd127ee167e1..64b0aa1ff5e5 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
@@ -541,8 +541,9 @@ EnforceMemoryMapAttribute (
 /**
   Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
 
-  @param Buffer  Start Address
-  @param Length  Address length
+  @param Buffer           Start Address
+  @param Length           Address length
+  @param ImageRecordList  Image record list
 
   @return first image record covered by [buffer, length]
 **/
@@ -550,14 +551,12 @@ STATIC
 IMAGE_PROPERTIES_RECORD *
 GetImageRecordByAddress (
   IN EFI_PHYSICAL_ADDRESS  Buffer,
-  IN UINT64                Length
+  IN UINT64                Length,
+  IN LIST_ENTRY            *ImageRecordList
   )
 {
   IMAGE_PROPERTIES_RECORD  *ImageRecord;
   LIST_ENTRY               *ImageRecordLink;
-  LIST_ENTRY               *ImageRecordList;
-
-  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
 
   for (ImageRecordLink = ImageRecordList->ForwardLink;
        ImageRecordLink != ImageRecordList;
@@ -692,7 +691,8 @@ SetNewRecord (
 STATIC
 UINTN
 GetMaxSplitRecordCount (
-  IN EFI_MEMORY_DESCRIPTOR  *OldRecord
+  IN EFI_MEMORY_DESCRIPTOR  *OldRecord,
+  IN LIST_ENTRY             *ImageRecordList
   )
 {
   IMAGE_PROPERTIES_RECORD  *ImageRecord;
@@ -705,7 +705,7 @@ GetMaxSplitRecordCount (
   PhysicalEnd      = OldRecord->PhysicalStart + EfiPagesToSize (OldRecord->NumberOfPages);
 
   do {
-    ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
+    ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
     if (ImageRecord == NULL) {
       break;
     }
@@ -725,13 +725,16 @@ GetMaxSplitRecordCount (
   Split the memory map to new entries, according to one old entry,
   based upon PE code section and data section.
 
-  @param  OldRecord              A pointer to one old memory map entry.
-  @param  NewRecord              A pointer to several new memory map entries.
-                                 The caller gurantee the buffer size be 1 +
-                                 (SplitRecordCount * DescriptorSize) calculated
-                                 below.
-  @param  MaxSplitRecordCount    The max number of splitted entries
-  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param        OldRecord             A pointer to one old memory map entry.
+  @param        NewRecord             A pointer to several new memory map entries.
+                                      The caller gurantee the buffer size be 1 +
+                                      (SplitRecordCount * DescriptorSize) calculated
+                                      below.
+  @param        MaxSplitRecordCount   The max number of splitted entries
+  @param        DescriptorSize        Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param        ImageRecordList       A list of IMAGE_PROPERTIES_RECORD entries used when searching
+                                      for an image record contained by the memory range described in
+                                      the existing EFI memory map descriptor OldRecord
 
   @retval  0 no entry is splitted.
   @return  the real number of splitted record.
@@ -742,7 +745,8 @@ SplitRecord (
   IN EFI_MEMORY_DESCRIPTOR      *OldRecord,
   IN OUT EFI_MEMORY_DESCRIPTOR  *NewRecord,
   IN UINTN                      MaxSplitRecordCount,
-  IN UINTN                      DescriptorSize
+  IN UINTN                      DescriptorSize,
+  IN LIST_ENTRY                 *ImageRecordList
   )
 {
   EFI_MEMORY_DESCRIPTOR    TempRecord;
@@ -770,7 +774,7 @@ SplitRecord (
 
   ImageRecord = NULL;
   do {
-    NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
+    NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
     if (NewImageRecord == NULL) {
       //
       // No more image covered by this range, stop
@@ -867,23 +871,29 @@ SplitRecord (
    | Record Y      |
    +---------------+
 
-  @param  MemoryMapSize          A pointer to the size, in bytes, of the
-                                 MemoryMap buffer. On input, this is the size of
-                                 old MemoryMap before split. The actual buffer
-                                 size of MemoryMap is MemoryMapSize +
-                                 (AdditionalRecordCount * DescriptorSize) calculated
-                                 below. On output, it is the size of new MemoryMap
-                                 after split.
-  @param  MemoryMap              A pointer to the buffer in which firmware places
-                                 the current memory map.
-  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param  MemoryMapSize                   A pointer to the size, in bytes, of the
+                                          MemoryMap buffer. On input, this is the size of
+                                          old MemoryMap before split. The actual buffer
+                                          size of MemoryMap is MemoryMapSize +
+                                          (AdditionalRecordCount * DescriptorSize) calculated
+                                          below. On output, it is the size of new MemoryMap
+                                          after split.
+  @param  MemoryMap                       A pointer to the buffer in which firmware places
+                                          the current memory map.
+  @param  DescriptorSize                  Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param  ImageRecordList                 A list of IMAGE_PROPERTIES_RECORD entries used when searching
+                                          for an image record contained by the memory range described in
+                                          EFI memory map descriptors.
+  @param  NumberOfAdditionalDescriptors   The number of unused descriptors at the end of the input MemoryMap.
 **/
 STATIC
 VOID
 SplitTable (
   IN OUT UINTN                  *MemoryMapSize,
   IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
-  IN UINTN                      DescriptorSize
+  IN     UINTN                  DescriptorSize,
+  IN     LIST_ENTRY             *ImageRecordList,
+  IN     UINTN                  NumberOfAdditionalDescriptors
   )
 {
   INTN   IndexOld;
@@ -891,9 +901,6 @@ SplitTable (
   UINTN  MaxSplitRecordCount;
   UINTN  RealSplitRecordCount;
   UINTN  TotalSplitRecordCount;
-  UINTN  AdditionalRecordCount;
-
-  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;
 
   TotalSplitRecordCount = 0;
   //
@@ -903,9 +910,9 @@ SplitTable (
   //
   // Let new record point to end of full MemoryMap buffer.
   //
-  IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + AdditionalRecordCount;
+  IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + NumberOfAdditionalDescriptors;
   for ( ; IndexOld >= 0; IndexOld--) {
-    MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize));
+    MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), ImageRecordList);
     //
     // Split this MemoryMap record
     //
@@ -914,7 +921,8 @@ SplitTable (
                              (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),
                              (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
                              MaxSplitRecordCount,
-                             DescriptorSize
+                             DescriptorSize,
+                             ImageRecordList
                              );
     //
     // Adjust IndexNew according to real split.
@@ -934,7 +942,7 @@ SplitTable (
   //
   CopyMem (
     MemoryMap,
-    (UINT8 *)MemoryMap + (AdditionalRecordCount - TotalSplitRecordCount) * DescriptorSize,
+    (UINT8 *)MemoryMap + (NumberOfAdditionalDescriptors - TotalSplitRecordCount) * DescriptorSize,
     (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize
     );
 
@@ -1035,7 +1043,7 @@ CoreGetMemoryMapWithSeparatedImageSection (
       //
       // Split PE code/data
       //
-      SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize);
+      SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize, &mImagePropertiesPrivateData.ImageRecordList, AdditionalRecordCount);
     }
   }
 
@@ -1233,11 +1241,13 @@ SwapImageRecord (
 
 /**
   Sort image record based upon the ImageBase from low to high.
+
+  @param ImageRecordList    Image record list to be sorted
 **/
 STATIC
 VOID
 SortImageRecord (
-  VOID
+  IN LIST_ENTRY  *ImageRecordList
   )
 {
   IMAGE_PROPERTIES_RECORD  *ImageRecord;
@@ -1245,9 +1255,6 @@ SortImageRecord (
   LIST_ENTRY               *ImageRecordLink;
   LIST_ENTRY               *NextImageRecordLink;
   LIST_ENTRY               *ImageRecordEndLink;
-  LIST_ENTRY               *ImageRecordList;
-
-  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
 
   ImageRecordLink     = ImageRecordList->ForwardLink;
   NextImageRecordLink = ImageRecordLink->ForwardLink;
@@ -1456,7 +1463,7 @@ InsertImageRecord (
     mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;
   }
 
-  SortImageRecord ();
+  SortImageRecord (&mImagePropertiesPrivateData.ImageRecordList);
 
 Finish:
   return;
@@ -1465,8 +1472,9 @@ Finish:
 /**
   Find image record according to image base and size.
 
-  @param  ImageBase    Base of PE image
-  @param  ImageSize    Size of PE image
+  @param  ImageBase           Base of PE image
+  @param  ImageSize           Size of PE image
+  @param  ImageRecordList     Image record list to be searched
 
   @return image record
 **/
@@ -1474,14 +1482,12 @@ STATIC
 IMAGE_PROPERTIES_RECORD *
 FindImageRecord (
   IN EFI_PHYSICAL_ADDRESS  ImageBase,
-  IN UINT64                ImageSize
+  IN UINT64                ImageSize,
+  IN LIST_ENTRY            *ImageRecordList
   )
 {
   IMAGE_PROPERTIES_RECORD  *ImageRecord;
   LIST_ENTRY               *ImageRecordLink;
-  LIST_ENTRY               *ImageRecordList;
-
-  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
 
   for (ImageRecordLink = ImageRecordList->ForwardLink;
        ImageRecordLink != ImageRecordList;
@@ -1526,7 +1532,7 @@ RemoveImageRecord (
     return;
   }
 
-  ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize);
+  ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize, &mImagePropertiesPrivateData.ImageRecordList);
   if (ImageRecord == NULL) {
     DEBUG ((DEBUG_ERROR, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
     return;
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111743): https://edk2.groups.io/g/devel/message/111743
Mute This Topic: https://groups.io/mt/102834913/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 07/16] MdeModulePkg: Move Some DXE MAT Logic to ImagePropertiesRecordLib
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (5 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 06/16] MdeModulePkg: Update MemoryAttributesTable.c to Reduce Global Variable Use Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 08/16] MdeModulePkg: Add ImagePropertiesRecordLib Host-Based Unit Test Taylor Beebe
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Liming Gao, Dandan Bi

Move some DXE MAT logic to ImagePropertiesRecordLib to consolidate
code and enable unit testability.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c                         | 774 +-------------------
 MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c                              |  24 +-
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c   | 770 +++++++++++++++++++
 MdeModulePkg/Core/Dxe/DxeMain.h                                            |  20 -
 MdeModulePkg/Core/Dxe/DxeMain.inf                                          |   1 +
 MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h                    | 159 ++++
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf |   4 +
 7 files changed, 947 insertions(+), 805 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
index 64b0aa1ff5e5..51630f504ea1 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
@@ -14,6 +14,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/DxeServicesTableLib.h>
 #include <Library/DebugLib.h>
 #include <Library/UefiLib.h>
+#include <Library/ImagePropertiesRecordLib.h>
 
 #include <Guid/EventGroup.h>
 
@@ -333,45 +334,6 @@ CoreInitializeMemoryAttributesTable (
 // Below functions are for MemoryMap
 //
 
-/**
-  Converts a number of EFI_PAGEs to a size in bytes.
-
-  NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
-
-  @param  Pages     The number of EFI_PAGES.
-
-  @return  The number of bytes associated with the number of EFI_PAGEs specified
-           by Pages.
-**/
-STATIC
-UINT64
-EfiPagesToSize (
-  IN UINT64  Pages
-  )
-{
-  return LShiftU64 (Pages, EFI_PAGE_SHIFT);
-}
-
-/**
-  Converts a size, in bytes, to a number of EFI_PAGESs.
-
-  NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
-
-  @param  Size      A size in bytes.
-
-  @return  The number of EFI_PAGESs associated with the number of bytes specified
-           by Size.
-
-**/
-STATIC
-UINT64
-EfiSizeToPages (
-  IN UINT64  Size
-  )
-{
-  return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0);
-}
-
 /**
   Acquire memory lock on mMemoryAttributesTableLock.
 **/
@@ -396,48 +358,6 @@ CoreReleasemMemoryAttributesTableLock (
   CoreReleaseLock (&mMemoryAttributesTableLock);
 }
 
-/**
-  Sort memory map entries based upon PhysicalStart, from low to high.
-
-  @param  MemoryMap              A pointer to the buffer in which firmware places
-                                 the current memory map.
-  @param  MemoryMapSize          Size, in bytes, of the MemoryMap buffer.
-  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-**/
-STATIC
-VOID
-SortMemoryMap (
-  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
-  IN UINTN                      MemoryMapSize,
-  IN UINTN                      DescriptorSize
-  )
-{
-  EFI_MEMORY_DESCRIPTOR  *MemoryMapEntry;
-  EFI_MEMORY_DESCRIPTOR  *NextMemoryMapEntry;
-  EFI_MEMORY_DESCRIPTOR  *MemoryMapEnd;
-  EFI_MEMORY_DESCRIPTOR  TempMemoryMap;
-
-  MemoryMapEntry     = MemoryMap;
-  NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
-  MemoryMapEnd       = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
-  while (MemoryMapEntry < MemoryMapEnd) {
-    while (NextMemoryMapEntry < MemoryMapEnd) {
-      if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {
-        CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
-        CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
-        CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof (EFI_MEMORY_DESCRIPTOR));
-      }
-
-      NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
-    }
-
-    MemoryMapEntry     = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
-    NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
-  }
-
-  return;
-}
-
 /**
   Merge continous memory map entries whose have same attributes.
 
@@ -471,7 +391,7 @@ MergeMemoryMap (
 
     do {
       MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart);
-      MemoryBlockLength = (UINT64)(EfiPagesToSize (NewMemoryMapEntry->NumberOfPages));
+      MemoryBlockLength = LShiftU64 (NewMemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT);
       if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
           (NewMemoryMapEntry->Type == NextMemoryMapEntry->Type) &&
           (NewMemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&
@@ -538,434 +458,6 @@ EnforceMemoryMapAttribute (
   return;
 }
 
-/**
-  Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
-
-  @param Buffer           Start Address
-  @param Length           Address length
-  @param ImageRecordList  Image record list
-
-  @return first image record covered by [buffer, length]
-**/
-STATIC
-IMAGE_PROPERTIES_RECORD *
-GetImageRecordByAddress (
-  IN EFI_PHYSICAL_ADDRESS  Buffer,
-  IN UINT64                Length,
-  IN LIST_ENTRY            *ImageRecordList
-  )
-{
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  LIST_ENTRY               *ImageRecordLink;
-
-  for (ImageRecordLink = ImageRecordList->ForwardLink;
-       ImageRecordLink != ImageRecordList;
-       ImageRecordLink = ImageRecordLink->ForwardLink)
-  {
-    ImageRecord = CR (
-                    ImageRecordLink,
-                    IMAGE_PROPERTIES_RECORD,
-                    Link,
-                    IMAGE_PROPERTIES_RECORD_SIGNATURE
-                    );
-
-    if ((Buffer <= ImageRecord->ImageBase) &&
-        (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize))
-    {
-      return ImageRecord;
-    }
-  }
-
-  return NULL;
-}
-
-/**
-  Set the memory map to new entries, according to one old entry,
-  based upon PE code section and data section in image record
-
-  @param  ImageRecord            An image record whose [ImageBase, ImageSize] covered
-                                 by old memory map entry.
-  @param  NewRecord              A pointer to several new memory map entries.
-                                 The caller gurantee the buffer size be 1 +
-                                 (SplitRecordCount * DescriptorSize) calculated
-                                 below.
-  @param  OldRecord              A pointer to one old memory map entry.
-  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-**/
-STATIC
-UINTN
-SetNewRecord (
-  IN IMAGE_PROPERTIES_RECORD    *ImageRecord,
-  IN OUT EFI_MEMORY_DESCRIPTOR  *NewRecord,
-  IN EFI_MEMORY_DESCRIPTOR      *OldRecord,
-  IN UINTN                      DescriptorSize
-  )
-{
-  EFI_MEMORY_DESCRIPTOR                 TempRecord;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-  LIST_ENTRY                            *ImageRecordCodeSectionLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionList;
-  UINTN                                 NewRecordCount;
-  UINT64                                PhysicalEnd;
-  UINT64                                ImageEnd;
-
-  CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));
-  PhysicalEnd    = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);
-  NewRecordCount = 0;
-
-  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
-
-  ImageRecordCodeSectionLink    = ImageRecordCodeSectionList->ForwardLink;
-  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
-  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-    ImageRecordCodeSection = CR (
-                               ImageRecordCodeSectionLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-
-    if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {
-      //
-      // DATA
-      //
-      NewRecord->Type          = TempRecord.Type;
-      NewRecord->PhysicalStart = TempRecord.PhysicalStart;
-      NewRecord->VirtualStart  = 0;
-      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart);
-      NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
-      if (NewRecord->NumberOfPages != 0) {
-        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-        NewRecordCount++;
-      }
-
-      //
-      // CODE
-      //
-      NewRecord->Type          = TempRecord.Type;
-      NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase;
-      NewRecord->VirtualStart  = 0;
-      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize);
-      NewRecord->Attribute     = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO;
-      if (NewRecord->NumberOfPages != 0) {
-        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-        NewRecordCount++;
-      }
-
-      TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize));
-      TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - TempRecord.PhysicalStart);
-      if (TempRecord.NumberOfPages == 0) {
-        break;
-      }
-    }
-  }
-
-  ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
-
-  //
-  // Final DATA
-  //
-  if (TempRecord.PhysicalStart < ImageEnd) {
-    NewRecord->Type          = TempRecord.Type;
-    NewRecord->PhysicalStart = TempRecord.PhysicalStart;
-    NewRecord->VirtualStart  = 0;
-    NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart);
-    NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
-    NewRecordCount++;
-  }
-
-  return NewRecordCount;
-}
-
-/**
-  Return the max number of new splitted entries, according to one old entry,
-  based upon PE code section and data section.
-
-  @param  OldRecord              A pointer to one old memory map entry.
-
-  @retval  0 no entry need to be splitted.
-  @return  the max number of new splitted entries
-**/
-STATIC
-UINTN
-GetMaxSplitRecordCount (
-  IN EFI_MEMORY_DESCRIPTOR  *OldRecord,
-  IN LIST_ENTRY             *ImageRecordList
-  )
-{
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  UINTN                    SplitRecordCount;
-  UINT64                   PhysicalStart;
-  UINT64                   PhysicalEnd;
-
-  SplitRecordCount = 0;
-  PhysicalStart    = OldRecord->PhysicalStart;
-  PhysicalEnd      = OldRecord->PhysicalStart + EfiPagesToSize (OldRecord->NumberOfPages);
-
-  do {
-    ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
-    if (ImageRecord == NULL) {
-      break;
-    }
-
-    SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1);
-    PhysicalStart     = ImageRecord->ImageBase + ImageRecord->ImageSize;
-  } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
-
-  if (SplitRecordCount != 0) {
-    SplitRecordCount--;
-  }
-
-  return SplitRecordCount;
-}
-
-/**
-  Split the memory map to new entries, according to one old entry,
-  based upon PE code section and data section.
-
-  @param        OldRecord             A pointer to one old memory map entry.
-  @param        NewRecord             A pointer to several new memory map entries.
-                                      The caller gurantee the buffer size be 1 +
-                                      (SplitRecordCount * DescriptorSize) calculated
-                                      below.
-  @param        MaxSplitRecordCount   The max number of splitted entries
-  @param        DescriptorSize        Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-  @param        ImageRecordList       A list of IMAGE_PROPERTIES_RECORD entries used when searching
-                                      for an image record contained by the memory range described in
-                                      the existing EFI memory map descriptor OldRecord
-
-  @retval  0 no entry is splitted.
-  @return  the real number of splitted record.
-**/
-STATIC
-UINTN
-SplitRecord (
-  IN EFI_MEMORY_DESCRIPTOR      *OldRecord,
-  IN OUT EFI_MEMORY_DESCRIPTOR  *NewRecord,
-  IN UINTN                      MaxSplitRecordCount,
-  IN UINTN                      DescriptorSize,
-  IN LIST_ENTRY                 *ImageRecordList
-  )
-{
-  EFI_MEMORY_DESCRIPTOR    TempRecord;
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  IMAGE_PROPERTIES_RECORD  *NewImageRecord;
-  UINT64                   PhysicalStart;
-  UINT64                   PhysicalEnd;
-  UINTN                    NewRecordCount;
-  UINTN                    TotalNewRecordCount;
-  BOOLEAN                  IsLastRecordData;
-
-  if (MaxSplitRecordCount == 0) {
-    CopyMem (NewRecord, OldRecord, DescriptorSize);
-    return 0;
-  }
-
-  TotalNewRecordCount = 0;
-
-  //
-  // Override previous record
-  //
-  CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));
-  PhysicalStart = TempRecord.PhysicalStart;
-  PhysicalEnd   = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);
-
-  ImageRecord = NULL;
-  do {
-    NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
-    if (NewImageRecord == NULL) {
-      //
-      // No more image covered by this range, stop
-      //
-      if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {
-        //
-        // If this is still address in this record, need record.
-        //
-        NewRecord        = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-        IsLastRecordData = FALSE;
-        if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) {
-          IsLastRecordData = TRUE;
-        }
-
-        if (IsLastRecordData) {
-          //
-          // Last record is DATA, just merge it.
-          //
-          NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - NewRecord->PhysicalStart);
-        } else {
-          //
-          // Last record is CODE, create a new DATA entry.
-          //
-          NewRecord                = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-          NewRecord->Type          = TempRecord.Type;
-          NewRecord->PhysicalStart = TempRecord.PhysicalStart;
-          NewRecord->VirtualStart  = 0;
-          NewRecord->NumberOfPages = TempRecord.NumberOfPages;
-          NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
-          TotalNewRecordCount++;
-        }
-      }
-
-      break;
-    }
-
-    ImageRecord = NewImageRecord;
-
-    //
-    // Set new record
-    //
-    NewRecordCount       = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);
-    TotalNewRecordCount += NewRecordCount;
-    NewRecord            = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);
-
-    //
-    // Update PhysicalStart, in order to exclude the image buffer already splitted.
-    //
-    PhysicalStart            = ImageRecord->ImageBase + ImageRecord->ImageSize;
-    TempRecord.PhysicalStart = PhysicalStart;
-    TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
-  } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
-
-  //
-  // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the
-  // code reaches here.
-  //
-  ASSERT (TotalNewRecordCount != 0);
-  return TotalNewRecordCount - 1;
-}
-
-/**
-  Split the original memory map, and add more entries to describe PE code section and data section.
-  This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
-  This function will merge entries with same attributes finally.
-
-  NOTE: It assumes PE code/data section are page aligned.
-  NOTE: It assumes enough entry is prepared for new memory map.
-
-  Split table:
-   +---------------+
-   | Record X      |
-   +---------------+
-   | Record RtCode |
-   +---------------+
-   | Record Y      |
-   +---------------+
-   ==>
-   +---------------+
-   | Record X      |
-   +---------------+ ----
-   | Record RtData |     |
-   +---------------+     |
-   | Record RtCode |     |-> PE/COFF1
-   +---------------+     |
-   | Record RtData |     |
-   +---------------+ ----
-   | Record RtData |     |
-   +---------------+     |
-   | Record RtCode |     |-> PE/COFF2
-   +---------------+     |
-   | Record RtData |     |
-   +---------------+ ----
-   | Record Y      |
-   +---------------+
-
-  @param  MemoryMapSize                   A pointer to the size, in bytes, of the
-                                          MemoryMap buffer. On input, this is the size of
-                                          old MemoryMap before split. The actual buffer
-                                          size of MemoryMap is MemoryMapSize +
-                                          (AdditionalRecordCount * DescriptorSize) calculated
-                                          below. On output, it is the size of new MemoryMap
-                                          after split.
-  @param  MemoryMap                       A pointer to the buffer in which firmware places
-                                          the current memory map.
-  @param  DescriptorSize                  Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-  @param  ImageRecordList                 A list of IMAGE_PROPERTIES_RECORD entries used when searching
-                                          for an image record contained by the memory range described in
-                                          EFI memory map descriptors.
-  @param  NumberOfAdditionalDescriptors   The number of unused descriptors at the end of the input MemoryMap.
-**/
-STATIC
-VOID
-SplitTable (
-  IN OUT UINTN                  *MemoryMapSize,
-  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
-  IN     UINTN                  DescriptorSize,
-  IN     LIST_ENTRY             *ImageRecordList,
-  IN     UINTN                  NumberOfAdditionalDescriptors
-  )
-{
-  INTN   IndexOld;
-  INTN   IndexNew;
-  UINTN  MaxSplitRecordCount;
-  UINTN  RealSplitRecordCount;
-  UINTN  TotalSplitRecordCount;
-
-  TotalSplitRecordCount = 0;
-  //
-  // Let old record point to end of valid MemoryMap buffer.
-  //
-  IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1;
-  //
-  // Let new record point to end of full MemoryMap buffer.
-  //
-  IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + NumberOfAdditionalDescriptors;
-  for ( ; IndexOld >= 0; IndexOld--) {
-    MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), ImageRecordList);
-    //
-    // Split this MemoryMap record
-    //
-    IndexNew            -= MaxSplitRecordCount;
-    RealSplitRecordCount = SplitRecord (
-                             (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),
-                             (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
-                             MaxSplitRecordCount,
-                             DescriptorSize,
-                             ImageRecordList
-                             );
-    //
-    // Adjust IndexNew according to real split.
-    //
-    CopyMem (
-      ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),
-      ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
-      RealSplitRecordCount * DescriptorSize
-      );
-    IndexNew               = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;
-    TotalSplitRecordCount += RealSplitRecordCount;
-    IndexNew--;
-  }
-
-  //
-  // Move all records to the beginning.
-  //
-  CopyMem (
-    MemoryMap,
-    (UINT8 *)MemoryMap + (NumberOfAdditionalDescriptors - TotalSplitRecordCount) * DescriptorSize,
-    (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize
-    );
-
-  *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount;
-
-  //
-  // Sort from low to high (Just in case)
-  //
-  SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
-
-  //
-  // Set RuntimeData to XP
-  //
-  EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, DescriptorSize);
-
-  //
-  // Merge same type to save entry size
-  //
-  MergeMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize);
-
-  return;
-}
-
 /**
   This function for GetMemoryMap() with properties table capability.
 
@@ -1044,6 +536,16 @@ CoreGetMemoryMapWithSeparatedImageSection (
       // Split PE code/data
       //
       SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize, &mImagePropertiesPrivateData.ImageRecordList, AdditionalRecordCount);
+
+      //
+      // Set RuntimeData to XP
+      //
+      EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, *DescriptorSize);
+
+      //
+      // Merge same type to save entry size
+      //
+      MergeMemoryMap (MemoryMap, MemoryMapSize, *DescriptorSize);
     }
   }
 
@@ -1074,217 +576,6 @@ SetMemoryAttributesTableSectionAlignment (
   }
 }
 
-/**
-  Swap two code sections in image record.
-
-  @param  FirstImageRecordCodeSection    first code section in image record
-  @param  SecondImageRecordCodeSection   second code section in image record
-**/
-STATIC
-VOID
-SwapImageRecordCodeSection (
-  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *FirstImageRecordCodeSection,
-  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *SecondImageRecordCodeSection
-  )
-{
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  TempImageRecordCodeSection;
-
-  TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;
-  TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;
-
-  FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase;
-  FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize;
-
-  SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;
-  SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;
-}
-
-/**
-  Sort code section in image record, based upon CodeSegmentBase from low to high.
-
-  @param  ImageRecord    image record to be sorted
-**/
-VOID
-SortImageRecordCodeSection (
-  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
-  )
-{
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *NextImageRecordCodeSection;
-  LIST_ENTRY                            *ImageRecordCodeSectionLink;
-  LIST_ENTRY                            *NextImageRecordCodeSectionLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionList;
-
-  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
-
-  ImageRecordCodeSectionLink     = ImageRecordCodeSectionList->ForwardLink;
-  NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-  ImageRecordCodeSectionEndLink  = ImageRecordCodeSectionList;
-  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-    ImageRecordCodeSection = CR (
-                               ImageRecordCodeSectionLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-      NextImageRecordCodeSection = CR (
-                                     NextImageRecordCodeSectionLink,
-                                     IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                                     Link,
-                                     IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                                     );
-      if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {
-        SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);
-      }
-
-      NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;
-    }
-
-    ImageRecordCodeSectionLink     = ImageRecordCodeSectionLink->ForwardLink;
-    NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-  }
-}
-
-/**
-  Check if code section in image record is valid.
-
-  @param  ImageRecord    image record to be checked
-
-  @retval TRUE  image record is valid
-  @retval FALSE image record is invalid
-**/
-BOOLEAN
-IsImageRecordCodeSectionValid (
-  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
-  )
-{
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *LastImageRecordCodeSection;
-  LIST_ENTRY                            *ImageRecordCodeSectionLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionList;
-
-  DEBUG ((DEBUG_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));
-
-  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
-
-  ImageRecordCodeSectionLink    = ImageRecordCodeSectionList->ForwardLink;
-  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
-  LastImageRecordCodeSection    = NULL;
-  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-    ImageRecordCodeSection = CR (
-                               ImageRecordCodeSectionLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    if (ImageRecordCodeSection->CodeSegmentSize == 0) {
-      return FALSE;
-    }
-
-    if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {
-      return FALSE;
-    }
-
-    if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {
-      return FALSE;
-    }
-
-    if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
-      return FALSE;
-    }
-
-    if (LastImageRecordCodeSection != NULL) {
-      if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) {
-        return FALSE;
-      }
-    }
-
-    LastImageRecordCodeSection = ImageRecordCodeSection;
-    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-  }
-
-  return TRUE;
-}
-
-/**
-  Swap two image records.
-
-  @param  FirstImageRecord   first image record.
-  @param  SecondImageRecord  second image record.
-**/
-STATIC
-VOID
-SwapImageRecord (
-  IN IMAGE_PROPERTIES_RECORD  *FirstImageRecord,
-  IN IMAGE_PROPERTIES_RECORD  *SecondImageRecord
-  )
-{
-  IMAGE_PROPERTIES_RECORD  TempImageRecord;
-
-  TempImageRecord.ImageBase        = FirstImageRecord->ImageBase;
-  TempImageRecord.ImageSize        = FirstImageRecord->ImageSize;
-  TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;
-
-  FirstImageRecord->ImageBase        = SecondImageRecord->ImageBase;
-  FirstImageRecord->ImageSize        = SecondImageRecord->ImageSize;
-  FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;
-
-  SecondImageRecord->ImageBase        = TempImageRecord.ImageBase;
-  SecondImageRecord->ImageSize        = TempImageRecord.ImageSize;
-  SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;
-
-  SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);
-}
-
-/**
-  Sort image record based upon the ImageBase from low to high.
-
-  @param ImageRecordList    Image record list to be sorted
-**/
-STATIC
-VOID
-SortImageRecord (
-  IN LIST_ENTRY  *ImageRecordList
-  )
-{
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  IMAGE_PROPERTIES_RECORD  *NextImageRecord;
-  LIST_ENTRY               *ImageRecordLink;
-  LIST_ENTRY               *NextImageRecordLink;
-  LIST_ENTRY               *ImageRecordEndLink;
-
-  ImageRecordLink     = ImageRecordList->ForwardLink;
-  NextImageRecordLink = ImageRecordLink->ForwardLink;
-  ImageRecordEndLink  = ImageRecordList;
-  while (ImageRecordLink != ImageRecordEndLink) {
-    ImageRecord = CR (
-                    ImageRecordLink,
-                    IMAGE_PROPERTIES_RECORD,
-                    Link,
-                    IMAGE_PROPERTIES_RECORD_SIGNATURE
-                    );
-    while (NextImageRecordLink != ImageRecordEndLink) {
-      NextImageRecord = CR (
-                          NextImageRecordLink,
-                          IMAGE_PROPERTIES_RECORD,
-                          Link,
-                          IMAGE_PROPERTIES_RECORD_SIGNATURE
-                          );
-      if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {
-        SwapImageRecord (ImageRecord, NextImageRecord);
-      }
-
-      NextImageRecordLink = NextImageRecordLink->ForwardLink;
-    }
-
-    ImageRecordLink     = ImageRecordLink->ForwardLink;
-    NextImageRecordLink = ImageRecordLink->ForwardLink;
-  }
-}
-
 /**
   Insert image record.
 
@@ -1469,47 +760,6 @@ Finish:
   return;
 }
 
-/**
-  Find image record according to image base and size.
-
-  @param  ImageBase           Base of PE image
-  @param  ImageSize           Size of PE image
-  @param  ImageRecordList     Image record list to be searched
-
-  @return image record
-**/
-STATIC
-IMAGE_PROPERTIES_RECORD *
-FindImageRecord (
-  IN EFI_PHYSICAL_ADDRESS  ImageBase,
-  IN UINT64                ImageSize,
-  IN LIST_ENTRY            *ImageRecordList
-  )
-{
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  LIST_ENTRY               *ImageRecordLink;
-
-  for (ImageRecordLink = ImageRecordList->ForwardLink;
-       ImageRecordLink != ImageRecordList;
-       ImageRecordLink = ImageRecordLink->ForwardLink)
-  {
-    ImageRecord = CR (
-                    ImageRecordLink,
-                    IMAGE_PROPERTIES_RECORD,
-                    Link,
-                    IMAGE_PROPERTIES_RECORD_SIGNATURE
-                    );
-
-    if ((ImageBase == ImageRecord->ImageBase) &&
-        (ImageSize == ImageRecord->ImageSize))
-    {
-      return ImageRecord;
-    }
-  }
-
-  return NULL;
-}
-
 /**
   Remove Image record.
 
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
index 7cc829b17402..977239d08afc 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
@@ -32,6 +32,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/DxeServicesTableLib.h>
 #include <Library/DebugLib.h>
 #include <Library/UefiLib.h>
+#include <Library/ImagePropertiesRecordLib.h>
 
 #include <Guid/EventGroup.h>
 #include <Guid/MemoryAttributesTable.h>
@@ -66,29 +67,6 @@ extern LIST_ENTRY  mGcdMemorySpaceMap;
 
 STATIC LIST_ENTRY  mProtectedImageRecordList;
 
-/**
-  Sort code section in image record, based upon CodeSegmentBase from low to high.
-
-  @param  ImageRecord    image record to be sorted
-**/
-VOID
-SortImageRecordCodeSection (
-  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
-  );
-
-/**
-  Check if code section in image record is valid.
-
-  @param  ImageRecord    image record to be checked
-
-  @retval TRUE  image record is valid
-  @retval FALSE image record is invalid
-**/
-BOOLEAN
-IsImageRecordCodeSectionValid (
-  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
-  );
-
 /**
   Get the image type.
 
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
index df7c54ebb793..9fb3b922038f 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
@@ -7,3 +7,773 @@
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ImagePropertiesRecordLib.h>
+
+#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
+  ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
+
+#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
+  ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))
+
+/**
+  Converts a number of EFI_PAGEs to a size in bytes.
+
+  NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
+
+  @param  Pages     The number of EFI_PAGES.
+
+  @return  The number of bytes associated with the number of EFI_PAGEs specified
+           by Pages.
+**/
+STATIC
+UINT64
+EfiPagesToSize (
+  IN UINT64  Pages
+  )
+{
+  return LShiftU64 (Pages, EFI_PAGE_SHIFT);
+}
+
+/**
+  Converts a size, in bytes, to a number of EFI_PAGESs.
+
+  NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
+
+  @param  Size      A size in bytes.
+
+  @return  The number of EFI_PAGESs associated with the number of bytes specified
+           by Size.
+
+**/
+STATIC
+UINT64
+EfiSizeToPages (
+  IN UINT64  Size
+  )
+{
+  return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0);
+}
+
+/**
+  Sort memory map entries based upon PhysicalStart, from low to high.
+
+  @param  MemoryMap              A pointer to the buffer in which firmware places
+                                 the current memory map.
+  @param  MemoryMapSize          Size, in bytes, of the MemoryMap buffer.
+  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+**/
+STATIC
+VOID
+SortMemoryMap (
+  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
+  IN UINTN                      MemoryMapSize,
+  IN UINTN                      DescriptorSize
+  )
+{
+  EFI_MEMORY_DESCRIPTOR  *MemoryMapEntry;
+  EFI_MEMORY_DESCRIPTOR  *NextMemoryMapEntry;
+  EFI_MEMORY_DESCRIPTOR  *MemoryMapEnd;
+  EFI_MEMORY_DESCRIPTOR  TempMemoryMap;
+
+  MemoryMapEntry     = MemoryMap;
+  NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+  MemoryMapEnd       = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
+  while (MemoryMapEntry < MemoryMapEnd) {
+    while (NextMemoryMapEntry < MemoryMapEnd) {
+      if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {
+        CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
+        CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
+        CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof (EFI_MEMORY_DESCRIPTOR));
+      }
+
+      NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
+    }
+
+    MemoryMapEntry     = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+    NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+  }
+
+  return;
+}
+
+/**
+  Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
+
+  @param Buffer           Start Address
+  @param Length           Address length
+  @param ImageRecordList  Image record list
+
+  @return first image record covered by [buffer, length]
+**/
+STATIC
+IMAGE_PROPERTIES_RECORD *
+GetImageRecordByAddress (
+  IN EFI_PHYSICAL_ADDRESS  Buffer,
+  IN UINT64                Length,
+  IN LIST_ENTRY            *ImageRecordList
+  )
+{
+  IMAGE_PROPERTIES_RECORD  *ImageRecord;
+  LIST_ENTRY               *ImageRecordLink;
+
+  for (ImageRecordLink = ImageRecordList->ForwardLink;
+       ImageRecordLink != ImageRecordList;
+       ImageRecordLink = ImageRecordLink->ForwardLink)
+  {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    IMAGE_PROPERTIES_RECORD,
+                    Link,
+                    IMAGE_PROPERTIES_RECORD_SIGNATURE
+                    );
+
+    if ((Buffer <= ImageRecord->ImageBase) &&
+        (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize))
+    {
+      return ImageRecord;
+    }
+  }
+
+  return NULL;
+}
+
+/**
+  Set the memory map to new entries, according to one old entry,
+  based upon PE code section and data section in image record
+
+  @param  ImageRecord            An image record whose [ImageBase, ImageSize] covered
+                                 by old memory map entry.
+  @param  NewRecord              A pointer to several new memory map entries.
+                                 The caller gurantee the buffer size be 1 +
+                                 (SplitRecordCount * DescriptorSize) calculated
+                                 below.
+  @param  OldRecord              A pointer to one old memory map entry.
+  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+**/
+STATIC
+UINTN
+SetNewRecord (
+  IN IMAGE_PROPERTIES_RECORD    *ImageRecord,
+  IN OUT EFI_MEMORY_DESCRIPTOR  *NewRecord,
+  IN EFI_MEMORY_DESCRIPTOR      *OldRecord,
+  IN UINTN                      DescriptorSize
+  )
+{
+  EFI_MEMORY_DESCRIPTOR                 TempRecord;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
+  LIST_ENTRY                            *ImageRecordCodeSectionLink;
+  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
+  LIST_ENTRY                            *ImageRecordCodeSectionList;
+  UINTN                                 NewRecordCount;
+  UINT64                                PhysicalEnd;
+  UINT64                                ImageEnd;
+
+  CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));
+  PhysicalEnd    = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);
+  NewRecordCount = 0;
+
+  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
+
+  ImageRecordCodeSectionLink    = ImageRecordCodeSectionList->ForwardLink;
+  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
+  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
+    ImageRecordCodeSection = CR (
+                               ImageRecordCodeSectionLink,
+                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
+                               Link,
+                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
+                               );
+    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
+
+    if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {
+      //
+      // DATA
+      //
+      NewRecord->Type          = TempRecord.Type;
+      NewRecord->PhysicalStart = TempRecord.PhysicalStart;
+      NewRecord->VirtualStart  = 0;
+      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart);
+      NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
+      if (NewRecord->NumberOfPages != 0) {
+        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
+        NewRecordCount++;
+      }
+
+      //
+      // CODE
+      //
+      NewRecord->Type          = TempRecord.Type;
+      NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase;
+      NewRecord->VirtualStart  = 0;
+      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize);
+      NewRecord->Attribute     = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO;
+      if (NewRecord->NumberOfPages != 0) {
+        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
+        NewRecordCount++;
+      }
+
+      TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize));
+      TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - TempRecord.PhysicalStart);
+      if (TempRecord.NumberOfPages == 0) {
+        break;
+      }
+    }
+  }
+
+  ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
+
+  //
+  // Final DATA
+  //
+  if (TempRecord.PhysicalStart < ImageEnd) {
+    NewRecord->Type          = TempRecord.Type;
+    NewRecord->PhysicalStart = TempRecord.PhysicalStart;
+    NewRecord->VirtualStart  = 0;
+    NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart);
+    NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
+    NewRecordCount++;
+  }
+
+  return NewRecordCount;
+}
+
+/**
+  Return the max number of new splitted entries, according to one old entry,
+  based upon PE code section and data section.
+
+  @param  OldRecord              A pointer to one old memory map entry.
+  @param  ImageRecordList        A list of IMAGE_PROPERTIES_RECORD entries used when searching
+                                 for an image record contained by the memory range described in
+                                 the existing EFI memory map descriptor OldRecord
+
+  @retval  0 no entry need to be splitted.
+  @return  the max number of new splitted entries
+**/
+STATIC
+UINTN
+GetMaxSplitRecordCount (
+  IN EFI_MEMORY_DESCRIPTOR  *OldRecord,
+  IN LIST_ENTRY             *ImageRecordList
+  )
+{
+  IMAGE_PROPERTIES_RECORD  *ImageRecord;
+  UINTN                    SplitRecordCount;
+  UINT64                   PhysicalStart;
+  UINT64                   PhysicalEnd;
+
+  SplitRecordCount = 0;
+  PhysicalStart    = OldRecord->PhysicalStart;
+  PhysicalEnd      = OldRecord->PhysicalStart + EfiPagesToSize (OldRecord->NumberOfPages);
+
+  do {
+    ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
+    if (ImageRecord == NULL) {
+      break;
+    }
+
+    SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1);
+    PhysicalStart     = ImageRecord->ImageBase + ImageRecord->ImageSize;
+  } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
+
+  if (SplitRecordCount != 0) {
+    SplitRecordCount--;
+  }
+
+  return SplitRecordCount;
+}
+
+/**
+  Split the memory map to new entries, according to one old entry,
+  based upon PE code section and data section.
+
+  @param        OldRecord             A pointer to one old memory map entry.
+  @param        NewRecord             A pointer to several new memory map entries.
+                                      The caller gurantee the buffer size be 1 +
+                                      (SplitRecordCount * DescriptorSize) calculated
+                                      below.
+  @param        MaxSplitRecordCount   The max number of splitted entries
+  @param        DescriptorSize        Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param        ImageRecordList       A list of IMAGE_PROPERTIES_RECORD entries used when searching
+                                      for an image record contained by the memory range described in
+                                      the existing EFI memory map descriptor OldRecord
+
+  @retval  0 no entry is splitted.
+  @return  the real number of splitted record.
+**/
+STATIC
+UINTN
+SplitRecord (
+  IN EFI_MEMORY_DESCRIPTOR      *OldRecord,
+  IN OUT EFI_MEMORY_DESCRIPTOR  *NewRecord,
+  IN UINTN                      MaxSplitRecordCount,
+  IN UINTN                      DescriptorSize,
+  IN LIST_ENTRY                 *ImageRecordList
+  )
+{
+  EFI_MEMORY_DESCRIPTOR    TempRecord;
+  IMAGE_PROPERTIES_RECORD  *ImageRecord;
+  IMAGE_PROPERTIES_RECORD  *NewImageRecord;
+  UINT64                   PhysicalStart;
+  UINT64                   PhysicalEnd;
+  UINTN                    NewRecordCount;
+  UINTN                    TotalNewRecordCount;
+  BOOLEAN                  IsLastRecordData;
+
+  if (MaxSplitRecordCount == 0) {
+    CopyMem (NewRecord, OldRecord, DescriptorSize);
+    return 0;
+  }
+
+  TotalNewRecordCount = 0;
+
+  //
+  // Override previous record
+  //
+  CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));
+  PhysicalStart = TempRecord.PhysicalStart;
+  PhysicalEnd   = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);
+
+  ImageRecord = NULL;
+  do {
+    NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
+    if (NewImageRecord == NULL) {
+      //
+      // No more image covered by this range, stop
+      //
+      if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {
+        //
+        // If this is still address in this record, need record.
+        //
+        NewRecord        = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
+        IsLastRecordData = FALSE;
+        if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) {
+          IsLastRecordData = TRUE;
+        }
+
+        if (IsLastRecordData) {
+          //
+          // Last record is DATA, just merge it.
+          //
+          NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - NewRecord->PhysicalStart);
+        } else {
+          //
+          // Last record is CODE, create a new DATA entry.
+          //
+          NewRecord                = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
+          NewRecord->Type          = TempRecord.Type;
+          NewRecord->PhysicalStart = TempRecord.PhysicalStart;
+          NewRecord->VirtualStart  = 0;
+          NewRecord->NumberOfPages = TempRecord.NumberOfPages;
+          NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
+          TotalNewRecordCount++;
+        }
+      }
+
+      break;
+    }
+
+    ImageRecord = NewImageRecord;
+
+    //
+    // Set new record
+    //
+    NewRecordCount       = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);
+    TotalNewRecordCount += NewRecordCount;
+    NewRecord            = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);
+
+    //
+    // Update PhysicalStart, in order to exclude the image buffer already splitted.
+    //
+    PhysicalStart            = ImageRecord->ImageBase + ImageRecord->ImageSize;
+    TempRecord.PhysicalStart = PhysicalStart;
+    TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
+  } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
+
+  //
+  // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the
+  // code reaches here.
+  //
+  ASSERT (TotalNewRecordCount != 0);
+  return TotalNewRecordCount - 1;
+}
+
+/**
+  Split the original memory map, and add more entries to describe PE code section and data section.
+  This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
+  This function will merge entries with same attributes finally.
+
+  NOTE: It assumes PE code/data section are page aligned.
+  NOTE: It assumes enough entry is prepared for new memory map.
+
+  Split table:
+   +---------------+
+   | Record X      |
+   +---------------+
+   | Record RtCode |
+   +---------------+
+   | Record Y      |
+   +---------------+
+   ==>
+   +---------------+
+   | Record X      |
+   +---------------+ ----
+   | Record RtData |     |
+   +---------------+     |
+   | Record RtCode |     |-> PE/COFF1
+   +---------------+     |
+   | Record RtData |     |
+   +---------------+ ----
+   | Record RtData |     |
+   +---------------+     |
+   | Record RtCode |     |-> PE/COFF2
+   +---------------+     |
+   | Record RtData |     |
+   +---------------+ ----
+   | Record Y      |
+   +---------------+
+
+  @param  MemoryMapSize                   A pointer to the size, in bytes, of the
+                                          MemoryMap buffer. On input, this is the size of
+                                          old MemoryMap before split. The actual buffer
+                                          size of MemoryMap is MemoryMapSize +
+                                          (AdditionalRecordCount * DescriptorSize) calculated
+                                          below. On output, it is the size of new MemoryMap
+                                          after split.
+  @param  MemoryMap                       A pointer to the buffer in which firmware places
+                                          the current memory map.
+  @param  DescriptorSize                  Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param  ImageRecordList                 A list of IMAGE_PROPERTIES_RECORD entries used when searching
+                                          for an image record contained by the memory range described in
+                                          EFI memory map descriptors.
+  @param  NumberOfAdditionalDescriptors   The number of unused descriptors at the end of the input MemoryMap.
+**/
+VOID
+EFIAPI
+SplitTable (
+  IN OUT UINTN                  *MemoryMapSize,
+  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
+  IN     UINTN                  DescriptorSize,
+  IN     LIST_ENTRY             *ImageRecordList,
+  IN     UINTN                  NumberOfAdditionalDescriptors
+  )
+{
+  INTN   IndexOld;
+  INTN   IndexNew;
+  UINTN  MaxSplitRecordCount;
+  UINTN  RealSplitRecordCount;
+  UINTN  TotalSplitRecordCount;
+
+  TotalSplitRecordCount = 0;
+  //
+  // Let old record point to end of valid MemoryMap buffer.
+  //
+  IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1;
+  //
+  // Let new record point to end of full MemoryMap buffer.
+  //
+  IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + NumberOfAdditionalDescriptors;
+  for ( ; IndexOld >= 0; IndexOld--) {
+    MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), ImageRecordList);
+    //
+    // Split this MemoryMap record
+    //
+    IndexNew            -= MaxSplitRecordCount;
+    RealSplitRecordCount = SplitRecord (
+                             (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),
+                             (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
+                             MaxSplitRecordCount,
+                             DescriptorSize,
+                             ImageRecordList
+                             );
+    //
+    // Adjust IndexNew according to real split.
+    //
+    CopyMem (
+      ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),
+      ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
+      RealSplitRecordCount * DescriptorSize
+      );
+    IndexNew               = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;
+    TotalSplitRecordCount += RealSplitRecordCount;
+    IndexNew--;
+  }
+
+  //
+  // Move all records to the beginning.
+  //
+  CopyMem (
+    MemoryMap,
+    (UINT8 *)MemoryMap + (NumberOfAdditionalDescriptors - TotalSplitRecordCount) * DescriptorSize,
+    (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize
+    );
+
+  *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount;
+
+  //
+  // Sort from low to high (Just in case)
+  //
+  SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
+
+  return;
+}
+
+/**
+  Swap two code sections in image record.
+
+  @param  FirstImageRecordCodeSection    first code section in image record
+  @param  SecondImageRecordCodeSection   second code section in image record
+**/
+VOID
+EFIAPI
+SwapImageRecordCodeSection (
+  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *FirstImageRecordCodeSection,
+  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *SecondImageRecordCodeSection
+  )
+{
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  TempImageRecordCodeSection;
+
+  TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;
+  TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;
+
+  FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase;
+  FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize;
+
+  SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;
+  SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;
+}
+
+/**
+  Sort code section in image record, based upon CodeSegmentBase from low to high.
+
+  @param  ImageRecord    image record to be sorted
+**/
+VOID
+EFIAPI
+SortImageRecordCodeSection (
+  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
+  )
+{
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *NextImageRecordCodeSection;
+  LIST_ENTRY                            *ImageRecordCodeSectionLink;
+  LIST_ENTRY                            *NextImageRecordCodeSectionLink;
+  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
+  LIST_ENTRY                            *ImageRecordCodeSectionList;
+
+  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
+
+  ImageRecordCodeSectionLink     = ImageRecordCodeSectionList->ForwardLink;
+  NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
+  ImageRecordCodeSectionEndLink  = ImageRecordCodeSectionList;
+  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
+    ImageRecordCodeSection = CR (
+                               ImageRecordCodeSectionLink,
+                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
+                               Link,
+                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
+                               );
+    while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
+      NextImageRecordCodeSection = CR (
+                                     NextImageRecordCodeSectionLink,
+                                     IMAGE_PROPERTIES_RECORD_CODE_SECTION,
+                                     Link,
+                                     IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
+                                     );
+      if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {
+        SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);
+      }
+
+      NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;
+    }
+
+    ImageRecordCodeSectionLink     = ImageRecordCodeSectionLink->ForwardLink;
+    NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
+  }
+}
+
+/**
+  Check if code section in image record is valid.
+
+  @param  ImageRecord    image record to be checked
+
+  @retval TRUE  image record is valid
+  @retval FALSE image record is invalid
+**/
+BOOLEAN
+EFIAPI
+IsImageRecordCodeSectionValid (
+  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
+  )
+{
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *LastImageRecordCodeSection;
+  LIST_ENTRY                            *ImageRecordCodeSectionLink;
+  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
+  LIST_ENTRY                            *ImageRecordCodeSectionList;
+
+  DEBUG ((DEBUG_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));
+
+  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
+
+  ImageRecordCodeSectionLink    = ImageRecordCodeSectionList->ForwardLink;
+  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
+  LastImageRecordCodeSection    = NULL;
+  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
+    ImageRecordCodeSection = CR (
+                               ImageRecordCodeSectionLink,
+                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
+                               Link,
+                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
+                               );
+    if (ImageRecordCodeSection->CodeSegmentSize == 0) {
+      return FALSE;
+    }
+
+    if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {
+      return FALSE;
+    }
+
+    if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {
+      return FALSE;
+    }
+
+    if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
+      return FALSE;
+    }
+
+    if (LastImageRecordCodeSection != NULL) {
+      if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) {
+        return FALSE;
+      }
+    }
+
+    LastImageRecordCodeSection = ImageRecordCodeSection;
+    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
+  }
+
+  return TRUE;
+}
+
+/**
+  Swap two image records.
+
+  @param  FirstImageRecord   first image record.
+  @param  SecondImageRecord  second image record.
+**/
+VOID
+EFIAPI
+SwapImageRecord (
+  IN IMAGE_PROPERTIES_RECORD  *FirstImageRecord,
+  IN IMAGE_PROPERTIES_RECORD  *SecondImageRecord
+  )
+{
+  IMAGE_PROPERTIES_RECORD  TempImageRecord;
+
+  TempImageRecord.ImageBase        = FirstImageRecord->ImageBase;
+  TempImageRecord.ImageSize        = FirstImageRecord->ImageSize;
+  TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;
+
+  FirstImageRecord->ImageBase        = SecondImageRecord->ImageBase;
+  FirstImageRecord->ImageSize        = SecondImageRecord->ImageSize;
+  FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;
+
+  SecondImageRecord->ImageBase        = TempImageRecord.ImageBase;
+  SecondImageRecord->ImageSize        = TempImageRecord.ImageSize;
+  SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;
+
+  SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);
+}
+
+/**
+  Sort image record based upon the ImageBase from low to high.
+
+  @param ImageRecordList    Image record list to be sorted
+**/
+VOID
+EFIAPI
+SortImageRecord (
+  IN LIST_ENTRY  *ImageRecordList
+  )
+{
+  IMAGE_PROPERTIES_RECORD  *ImageRecord;
+  IMAGE_PROPERTIES_RECORD  *NextImageRecord;
+  LIST_ENTRY               *ImageRecordLink;
+  LIST_ENTRY               *NextImageRecordLink;
+  LIST_ENTRY               *ImageRecordEndLink;
+
+  ImageRecordLink     = ImageRecordList->ForwardLink;
+  NextImageRecordLink = ImageRecordLink->ForwardLink;
+  ImageRecordEndLink  = ImageRecordList;
+  while (ImageRecordLink != ImageRecordEndLink) {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    IMAGE_PROPERTIES_RECORD,
+                    Link,
+                    IMAGE_PROPERTIES_RECORD_SIGNATURE
+                    );
+    while (NextImageRecordLink != ImageRecordEndLink) {
+      NextImageRecord = CR (
+                          NextImageRecordLink,
+                          IMAGE_PROPERTIES_RECORD,
+                          Link,
+                          IMAGE_PROPERTIES_RECORD_SIGNATURE
+
+                          );
+      if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {
+        SwapImageRecord (ImageRecord, NextImageRecord);
+      }
+
+      NextImageRecordLink = NextImageRecordLink->ForwardLink;
+    }
+
+    ImageRecordLink     = ImageRecordLink->ForwardLink;
+    NextImageRecordLink = ImageRecordLink->ForwardLink;
+  }
+}
+
+/**
+  Find image record according to image base and size.
+
+  @param  ImageBase           Base of PE image
+  @param  ImageSize           Size of PE image
+  @param  ImageRecordList     Image record list to be searched
+
+  @return image record
+**/
+IMAGE_PROPERTIES_RECORD *
+EFIAPI
+FindImageRecord (
+  IN EFI_PHYSICAL_ADDRESS  ImageBase,
+  IN UINT64                ImageSize,
+  IN LIST_ENTRY            *ImageRecordList
+  )
+{
+  IMAGE_PROPERTIES_RECORD  *ImageRecord;
+  LIST_ENTRY               *ImageRecordLink;
+
+  for (ImageRecordLink = ImageRecordList->ForwardLink;
+       ImageRecordLink != ImageRecordList;
+       ImageRecordLink = ImageRecordLink->ForwardLink)
+  {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    IMAGE_PROPERTIES_RECORD,
+                    Link,
+                    IMAGE_PROPERTIES_RECORD_SIGNATURE
+                    );
+
+    if ((ImageBase == ImageRecord->ImageBase) &&
+        (ImageSize == ImageRecord->ImageSize))
+    {
+      return ImageRecord;
+    }
+  }
+
+  return NULL;
+}
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h
index 43daa037be44..86a7be2f5188 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.h
+++ b/MdeModulePkg/Core/Dxe/DxeMain.h
@@ -228,26 +228,6 @@ typedef struct {
 #define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
           CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)
 
-#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE  SIGNATURE_32 ('I','P','R','C')
-
-typedef struct {
-  UINT32                  Signature;
-  LIST_ENTRY              Link;
-  EFI_PHYSICAL_ADDRESS    CodeSegmentBase;
-  UINT64                  CodeSegmentSize;
-} IMAGE_PROPERTIES_RECORD_CODE_SECTION;
-
-#define IMAGE_PROPERTIES_RECORD_SIGNATURE  SIGNATURE_32 ('I','P','R','D')
-
-typedef struct {
-  UINT32                  Signature;
-  LIST_ENTRY              Link;
-  EFI_PHYSICAL_ADDRESS    ImageBase;
-  UINT64                  ImageSize;
-  UINTN                   CodeSegmentCount;
-  LIST_ENTRY              CodeSegmentList;
-} IMAGE_PROPERTIES_RECORD;
-
 //
 // DXE Core Global Variables
 //
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
index 16871f2021e5..090970aec6df 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.inf
+++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -94,6 +94,7 @@ [LibraryClasses]
   DebugAgentLib
   CpuExceptionHandlerLib
   PcdLib
+  ImagePropertiesRecordLib
 
 [Guids]
   gEfiEventMemoryMapChangeGuid                  ## PRODUCES             ## Event
diff --git a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
index 728008a2e5bb..9139c7b6c05d 100644
--- a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
+++ b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
@@ -11,4 +11,163 @@
 #ifndef IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_
 #define IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_
 
+#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE  SIGNATURE_32 ('I','P','R','C')
+
+typedef struct {
+  UINT32                  Signature;
+  LIST_ENTRY              Link;
+  EFI_PHYSICAL_ADDRESS    CodeSegmentBase;
+  UINT64                  CodeSegmentSize;
+} IMAGE_PROPERTIES_RECORD_CODE_SECTION;
+
+#define IMAGE_PROPERTIES_RECORD_SIGNATURE  SIGNATURE_32 ('I','P','R','D')
+
+typedef struct {
+  UINT32                  Signature;
+  LIST_ENTRY              Link;
+  EFI_PHYSICAL_ADDRESS    ImageBase;
+  UINT64                  ImageSize;
+  UINTN                   CodeSegmentCount;
+  LIST_ENTRY              CodeSegmentList;
+} IMAGE_PROPERTIES_RECORD;
+
+/**
+  Split the original memory map, and add more entries to describe PE code section and data section.
+  This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
+  This function will merge entries with same attributes finally.
+
+  NOTE: It assumes PE code/data section are page aligned.
+  NOTE: It assumes enough entry is prepared for new memory map.
+
+  Split table:
+   +---------------+
+   | Record X      |
+   +---------------+
+   | Record RtCode |
+   +---------------+
+   | Record Y      |
+   +---------------+
+   ==>
+   +---------------+
+   | Record X      |
+   +---------------+ ----
+   | Record RtData |     |
+   +---------------+     |
+   | Record RtCode |     |-> PE/COFF1
+   +---------------+     |
+   | Record RtData |     |
+   +---------------+ ----
+   | Record RtData |     |
+   +---------------+     |
+   | Record RtCode |     |-> PE/COFF2
+   +---------------+     |
+   | Record RtData |     |
+   +---------------+ ----
+   | Record Y      |
+   +---------------+
+
+  @param  MemoryMapSize                   A pointer to the size, in bytes, of the
+                                          MemoryMap buffer. On input, this is the size of
+                                          old MemoryMap before split. The actual buffer
+                                          size of MemoryMap is MemoryMapSize +
+                                          (AdditionalRecordCount * DescriptorSize) calculated
+                                          below. On output, it is the size of new MemoryMap
+                                          after split.
+  @param  MemoryMap                       A pointer to the buffer in which firmware places
+                                          the current memory map.
+  @param  DescriptorSize                  Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param  ImageRecordList                 A list of IMAGE_PROPERTIES_RECORD entries used when searching
+                                          for an image record contained by the memory range described in
+                                          EFI memory map descriptors.
+  @param  NumberOfAdditionalDescriptors   The number of unused descriptors at the end of the input MemoryMap.
+**/
+VOID
+EFIAPI
+SplitTable (
+  IN OUT UINTN                  *MemoryMapSize,
+  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
+  IN     UINTN                  DescriptorSize,
+  IN     LIST_ENTRY             *ImageRecordList,
+  IN     UINTN                  NumberOfAdditionalDescriptors
+  );
+
+/**
+  Sort code section in image record, based upon CodeSegmentBase from low to high.
+
+  @param  ImageRecord    image record to be sorted
+**/
+VOID
+EFIAPI
+SortImageRecordCodeSection (
+  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
+  );
+
+/**
+  Check if code section in image record is valid.
+
+  @param  ImageRecord    image record to be checked
+
+  @retval TRUE  image record is valid
+  @retval FALSE image record is invalid
+**/
+BOOLEAN
+EFIAPI
+IsImageRecordCodeSectionValid (
+  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
+  );
+
+/**
+  Sort image record based upon the ImageBase from low to high.
+
+  @param ImageRecordList    Image record list to be sorted
+**/
+VOID
+EFIAPI
+SortImageRecord (
+  IN LIST_ENTRY  *ImageRecordList
+  );
+
+/**
+  Swap two image records.
+
+  @param[in]  FirstImageRecord   The first image record.
+  @param[in]  SecondImageRecord  The second image record.
+**/
+VOID
+EFIAPI
+SwapImageRecord (
+  IN IMAGE_PROPERTIES_RECORD  *FirstImageRecord,
+  IN IMAGE_PROPERTIES_RECORD  *SecondImageRecord
+  );
+
+/**
+  Swap two code sections in a single IMAGE_PROPERTIES_RECORD.
+
+  @param[in]  FirstImageRecordCodeSection    The first code section
+  @param[in]  SecondImageRecordCodeSection   The second code section
+**/
+VOID
+EFIAPI
+SwapImageRecordCodeSection (
+  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *FirstImageRecordCodeSection,
+  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *SecondImageRecordCodeSection
+  );
+
+/**
+  Find image record according to image base and size.
+
+  @param  ImageBase           Base of PE image
+  @param  ImageSize           Size of PE image
+  @param  ImageRecordList     Image record list to be searched
+
+  @return image record
+**/
+IMAGE_PROPERTIES_RECORD *
+EFIAPI
+FindImageRecord (
+  IN EFI_PHYSICAL_ADDRESS  ImageBase,
+  IN UINT64                ImageSize,
+  IN LIST_ENTRY            *ImageRecordList
+  );
+
 #endif
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
index b7e493056889..4c1466fc3336 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
@@ -19,6 +19,10 @@ [Defines]
 [Sources.common]
   ImagePropertiesRecordLib.c
 
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
 
 [Packages]
   MdePkg/MdePkg.dec
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111744): https://edk2.groups.io/g/devel/message/111744
Mute This Topic: https://groups.io/mt/102834914/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 08/16] MdeModulePkg: Add ImagePropertiesRecordLib Host-Based Unit Test
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (6 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 07/16] MdeModulePkg: Move Some DXE MAT Logic to ImagePropertiesRecordLib Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 09/16] MdeModulePkg: Fix MAT Descriptor Count Calculation Taylor Beebe
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Liming Gao, Dandan Bi

Create a host-based unit test for the ImagePropertiesRecordLib
SplitTable() logic. This test has 4 cases which tests different
potential image and memory map layouts. 3/4 of these tests fail
with the logic in its current state to provide proof of the bugs
in the current MAT logic.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.c   | 938 ++++++++++++++++++++
 MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.inf |  35 +
 MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                                      |   5 +
 3 files changed, 978 insertions(+)

diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.c
new file mode 100644
index 000000000000..8b0a55685ce3
--- /dev/null
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.c
@@ -0,0 +1,938 @@
+/** @file
+  Unit tests the SplitTable() ImagePropertiesRecordLib Logic
+
+  Copyright (C) Microsoft Corporation.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/ImagePropertiesRecordLib.h>
+
+#define UNIT_TEST_APP_NAME     "Image Properties Record Lib Unit Test"
+#define UNIT_TEST_APP_VERSION  "1.0"
+
+#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
+  ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))
+
+// The starting memory map will contain 6 entries
+#define NUMBER_OF_MEMORY_MAP_DESCRIPTORS  6
+
+// Each memory map descriptor will be the sizeof(EFI_MEMORY_DESCRIPTOR) instead of a nonstandard size
+// to catch pointer math issues
+#define DESCRIPTOR_SIZE  sizeof(EFI_MEMORY_DESCRIPTOR)
+
+// Each memory map descriptor will describe 12 pages
+#define BASE_DESCRIPTOR_NUMBER_OF_PAGES  0x0C
+
+// The size, in bytes, of each memory map descriptor range
+#define BASE_DESCRIPTOR_ENTRY_SIZE  (EFI_PAGES_TO_SIZE(BASE_DESCRIPTOR_NUMBER_OF_PAGES))
+
+// MACRO to get the starting address of a descriptor's described range based on the index of that descriptor
+#define BASE_DESCRIPTOR_START_ADDRESS(DescriptorNumber)  (DescriptorNumber * BASE_DESCRIPTOR_ENTRY_SIZE)
+
+// Virtual start must be zero
+#define BASE_DESCRIPTOR_VIRTUAL_START  0x0
+
+// Size of the default memory map
+#define BASE_MEMORY_MAP_SIZE  (NUMBER_OF_MEMORY_MAP_DESCRIPTORS * DESCRIPTOR_SIZE)
+
+// Number of images in each test case
+#define NUMBER_OF_IMAGES_TO_SPLIT  3
+
+// Maximum number of descriptors required for each image (None->Data->Code->Data->Code->Data->None)
+#define MAX_DESCRIPTORS_PER_IMAGE  7
+
+// Number of unused additional descriptors in the starting memory map buffer which is used by the
+// SplitTable() logic
+#define NUMBER_OF_ADDITIONAL_DESCRIPTORS  (NUMBER_OF_IMAGES_TO_SPLIT * MAX_DESCRIPTORS_PER_IMAGE)
+
+// Size of the memory map with enough space for the starting descriptors and the split descriptors
+#define SPLIT_MEMORY_MAP_SIZE  (BASE_MEMORY_MAP_SIZE + (NUMBER_OF_ADDITIONAL_DESCRIPTORS * DESCRIPTOR_SIZE))
+
+typedef enum {
+  SectionTypeCode,
+  SectionTypeData,
+  SectionTypeNotFound
+} SECTION_TYPE;
+
+typedef struct {
+  EFI_MEMORY_DESCRIPTOR    *MemoryMap;
+  LIST_ENTRY               ImageList;
+} IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT;
+
+EFI_MEMORY_DESCRIPTOR  BaseMemoryMap[] = {
+  {
+    EfiConventionalMemory,             // Type
+    BASE_DESCRIPTOR_START_ADDRESS (0), // PhysicalStart
+    BASE_DESCRIPTOR_VIRTUAL_START,     // VirtualStart
+    BASE_DESCRIPTOR_NUMBER_OF_PAGES,   // Number of Pages
+    0                                  // Attribute
+  },
+  {
+    EfiConventionalMemory,             // Type
+    BASE_DESCRIPTOR_START_ADDRESS (1), // PhysicalStart
+    BASE_DESCRIPTOR_VIRTUAL_START,     // VirtualStart
+    BASE_DESCRIPTOR_NUMBER_OF_PAGES,   // Number of Pages
+    0                                  // Attribute
+  },
+  {
+    EfiConventionalMemory,             // Type
+    BASE_DESCRIPTOR_START_ADDRESS (2), // PhysicalStart
+    BASE_DESCRIPTOR_VIRTUAL_START,     // VirtualStart
+    BASE_DESCRIPTOR_NUMBER_OF_PAGES,   // Number of Pages
+    0                                  // Attribute
+  },
+  {
+    EfiConventionalMemory,             // Type
+    BASE_DESCRIPTOR_START_ADDRESS (3), // PhysicalStart
+    BASE_DESCRIPTOR_VIRTUAL_START,     // VirtualStart
+    BASE_DESCRIPTOR_NUMBER_OF_PAGES,   // Number of Pages
+    0                                  // Attribute
+  },
+  {
+    EfiConventionalMemory,             // Type
+    BASE_DESCRIPTOR_START_ADDRESS (4), // PhysicalStart
+    BASE_DESCRIPTOR_VIRTUAL_START,     // VirtualStart
+    BASE_DESCRIPTOR_NUMBER_OF_PAGES,   // Number of Pages
+    0                                  // Attribute
+  },
+  {
+    EfiConventionalMemory,             // Type
+    BASE_DESCRIPTOR_START_ADDRESS (5), // PhysicalStart
+    BASE_DESCRIPTOR_VIRTUAL_START,     // VirtualStart
+    BASE_DESCRIPTOR_NUMBER_OF_PAGES,   // Number of Pages
+    0                                  // Attribute
+  }
+};
+
+/**
+  Returns a bitmap where one bit is set for each section in the image list. For example, if
+  there are 3 images and each image 3 sections the returned bitmap will be 111111111.
+
+  @param[in]  ImageRecordList   A list of IMAGE_PROPERTIES_RECORD entries
+
+  @retval A bitmap such that the most significant bit is the number of sections
+          in all images and every bit between 0 -> MSB is set
+
+**/
+STATIC
+UINT64
+GetImageSectionBitmap (
+  IN LIST_ENTRY  *ImageRecordList
+  )
+{
+  IMAGE_PROPERTIES_RECORD               *ImageRecord;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
+  LIST_ENTRY                            *ImageRecordLink;
+  LIST_ENTRY                            *ImageRecordCodeSectionLink;
+  EFI_PHYSICAL_ADDRESS                  SectionBase;
+  UINT64                                ReturnBitmap;
+  UINT64                                Shift;
+
+  if (ImageRecordList == NULL) {
+    return 0;
+  }
+
+  ReturnBitmap = 0;
+  Shift        = 0;
+
+  // Walk through each image record
+  for (ImageRecordLink = ImageRecordList->ForwardLink;
+       ImageRecordLink != ImageRecordList;
+       ImageRecordLink = ImageRecordLink->ForwardLink)
+  {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    IMAGE_PROPERTIES_RECORD,
+                    Link,
+                    IMAGE_PROPERTIES_RECORD_SIGNATURE
+                    );
+
+    SectionBase = ImageRecord->ImageBase;
+
+    // Walk through each code entry
+    for (ImageRecordCodeSectionLink = ImageRecord->CodeSegmentList.ForwardLink;
+         ImageRecordCodeSectionLink != &ImageRecord->CodeSegmentList;
+         ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink)
+    {
+      ImageRecordCodeSection = CR (
+                                 ImageRecordCodeSectionLink,
+                                 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
+                                 Link,
+                                 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
+                                 );
+
+      // Check for data region before the code section base
+      if (SectionBase < ImageRecordCodeSection->CodeSegmentBase) {
+        ReturnBitmap |= LShiftU64 (1, Shift++);
+      }
+
+      // Code section
+      ReturnBitmap |= LShiftU64 (1, Shift++);
+      SectionBase   = ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize;
+    }
+
+    // Check for data region after the previous code section
+    if (SectionBase < (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
+      ReturnBitmap |= LShiftU64 (1, Shift++);
+    }
+  }
+
+  return ReturnBitmap;
+}
+
+/**
+  Searches the input image list for a section which exactly matches the memory range Buffer -> Buffer + Length.
+
+  @param[in] Buffer           Start Address to check
+  @param[in] Length           Length to check
+  @param[out] Type             The type of the section which corresponds with the memory
+                              range Buffer -> Buffer + Length (Code or Data) or SectionTypeNotFound
+                              if no image section matches the memory range
+  @param[in] ImageRecordList  A list of IMAGE_PROPERTIES_RECORD entries to check against
+                              the memory range Buffer -> Buffer + Length
+
+  @retval A bitmap with a single bit set (1 << Shift) where Shift corresponds with the number of sections inspected
+          in the image list before arriving at the section matching the memory range Buffer -> Buffer + Length
+**/
+STATIC
+UINT64
+MatchDescriptorToImageSection (
+  IN  EFI_PHYSICAL_ADDRESS  Buffer,
+  IN  UINT64                Length,
+  OUT SECTION_TYPE          *Type,
+  IN  LIST_ENTRY            *ImageRecordList
+  )
+{
+  IMAGE_PROPERTIES_RECORD               *ImageRecord;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
+  LIST_ENTRY                            *ImageRecordLink;
+  LIST_ENTRY                            *ImageRecordCodeSectionLink;
+  EFI_PHYSICAL_ADDRESS                  SectionBase;
+  UINT8                                 Shift;
+
+  Shift = 0;
+
+  if (ImageRecordList == NULL) {
+    return 1;
+  }
+
+  // Walk through each image record
+  for (ImageRecordLink = ImageRecordList->ForwardLink;
+       ImageRecordLink != ImageRecordList;
+       ImageRecordLink = ImageRecordLink->ForwardLink)
+  {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    IMAGE_PROPERTIES_RECORD,
+                    Link,
+                    IMAGE_PROPERTIES_RECORD_SIGNATURE
+                    );
+
+    SectionBase = ImageRecord->ImageBase;
+
+    // Walk through each code entry
+    for (ImageRecordCodeSectionLink = ImageRecord->CodeSegmentList.ForwardLink;
+         ImageRecordCodeSectionLink != &ImageRecord->CodeSegmentList;
+         ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink)
+    {
+      ImageRecordCodeSection = CR (
+                                 ImageRecordCodeSectionLink,
+                                 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
+                                 Link,
+                                 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
+                                 );
+
+      if (SectionBase < ImageRecordCodeSection->CodeSegmentBase) {
+        // Check the data region before the code section base
+        if ((Buffer == SectionBase) &&
+            (Length == ImageRecordCodeSection->CodeSegmentBase - SectionBase))
+        {
+          *Type = SectionTypeData;
+          return LShiftU64 (1, Shift);
+        }
+
+        Shift++;
+      }
+
+      // Check the code region
+      if ((Buffer == ImageRecordCodeSection->CodeSegmentBase) &&
+          (Length == ImageRecordCodeSection->CodeSegmentSize))
+      {
+        *Type = SectionTypeCode;
+        return LShiftU64 (1, Shift);
+      }
+
+      Shift++;
+      SectionBase = ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize;
+    }
+
+    // Check the data region after the code section
+    if (SectionBase < (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
+      if ((Buffer == SectionBase) &&
+          (Length == (ImageRecord->ImageBase + ImageRecord->ImageSize) - SectionBase))
+      {
+        *Type = SectionTypeData;
+        return LShiftU64 (1, Shift);
+      }
+
+      Shift++;
+    }
+  }
+
+  // No image sections match
+  *Type = SectionTypeNotFound;
+  return 0;
+}
+
+/**
+  Walks through the input memory map and checks that every memory descriptor with an attribute matches
+  an image in ImageRecordList.
+
+  @param[in]        MemoryMapSize                 The size, in bytes, of the memory map
+  @param[in]        MemoryMap                     A pointer to the buffer containing the memory map
+  @param[in]        ImageRecordList               A list of IMAGE_PROPERTIES_RECORD entries
+
+  @retval TRUE if all memory descriptors with attributes match an image section and have the correct attributes
+
+**/
+STATIC
+BOOLEAN
+IsMemoryMapValid (
+  IN UINTN                  MemoryMapSize,
+  IN EFI_MEMORY_DESCRIPTOR  *MemoryMap,
+  IN LIST_ENTRY             *ImageRecordList
+  )
+{
+  UINT64        ImageSectionsBitmap;
+  UINT64        ReturnSectionBitmask;
+  UINT64        NumberOfDescriptors;
+  UINT8         Index;
+  SECTION_TYPE  Type;
+
+  Index               = 0;
+  NumberOfDescriptors = MemoryMapSize / DESCRIPTOR_SIZE;
+
+  UT_ASSERT_EQUAL (MemoryMapSize % DESCRIPTOR_SIZE, 0);
+  UT_ASSERT_NOT_NULL (MemoryMap);
+  UT_ASSERT_NOT_NULL (ImageRecordList);
+
+  // The returned bitmap will have one bit is set for each section in the image list.
+  // If there are 3 images and 3 sections each image, the resulting bitmap will
+  // be 0000000000000000000000000000000000000000000000000000000111111111. Flipping that bitmap
+  // results in 1111111111111111111111111111111111111111111111111111111000000000. The return value
+  // of each iteration through MatchDescriptorToImageSection() is one set bit corrosponding to the number
+  // of sections before finding the section which matched the descriptor memory range which we
+  // OR with ImageSectionsBitmap. If, at the end of the loop, every bit in ImageSectionsBitmap is set,
+  // we must have matched every image in ImageRecordList with a descriptor in the memory map which has
+  // nonzero attributes.
+  ImageSectionsBitmap = ~GetImageSectionBitmap (ImageRecordList);
+
+  // For each descriptor in the memory map
+  for ( ; Index < NumberOfDescriptors; Index++) {
+    if (MemoryMap[Index].Attribute != 0) {
+      ReturnSectionBitmask = MatchDescriptorToImageSection (
+                               MemoryMap[Index].PhysicalStart,
+                               EFI_PAGES_TO_SIZE (MemoryMap[Index].NumberOfPages),
+                               &Type,
+                               ImageRecordList
+                               );
+
+      // Make sure the attributes of the descriptor match the returned section type.
+      // DATA sections should have execution protection and CODE sections should have
+      // write protection.
+      if ((Type == SectionTypeNotFound) ||
+          ((Type == SectionTypeData) && (MemoryMap[Index].Attribute == EFI_MEMORY_RP)) ||
+          ((Type == SectionTypeCode) && (MemoryMap[Index].Attribute == EFI_MEMORY_XP)))
+      {
+        return FALSE;
+      }
+
+      // If the bit associated with image found has already been set, then there must be a duplicate
+      // in the memory map meaning it is invalid.
+      UT_ASSERT_EQUAL (ImageSectionsBitmap & ReturnSectionBitmask, 0);
+
+      ImageSectionsBitmap |= ReturnSectionBitmask;
+    }
+  }
+
+  // If every bit in ImageSectionsBitmap is set, the return value will be TRUE
+  return !(~ImageSectionsBitmap);
+}
+
+/**
+  Separate the image sections in the memory map and run a check to ensure the output is valid.
+
+  @param[in]  Context   Context containing the memory map and image record pointers
+
+  @retval TRUE if the memory map is split correctly
+**/
+STATIC
+BOOLEAN
+SeparateAndCheck (
+  IN IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT  *Context
+  )
+{
+  UINTN  MemoryMapSize;
+
+  MemoryMapSize = BASE_MEMORY_MAP_SIZE;
+
+  // Separate the memory map so each image section has its own descriptor
+  SplitTable (
+    &MemoryMapSize,
+    Context->MemoryMap,
+    DESCRIPTOR_SIZE,
+    &Context->ImageList,
+    NUMBER_OF_ADDITIONAL_DESCRIPTORS
+    );
+
+  // Ensure the updated memory map is valid
+  return IsMemoryMapValid (MemoryMapSize, Context->MemoryMap, &Context->ImageList);
+}
+
+/**
+  Test the case where the image range contains multiple code sections and does not perfectly align with
+  the existing memory descriptor.
+
+  @param[in]  Context   Context containing the memory map and image record pointers
+
+  @retval  UNIT_TEST_PASSED             The Unit test has completed and the test
+                                        case was successful.
+  @retval  UNIT_TEST_ERROR_TEST_FAILED  A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MaxOutAdditionalDescriptors (
+  IN UNIT_TEST_CONTEXT  Context
+  )
+{
+  IMAGE_PROPERTIES_RECORD                    *Image1;
+  IMAGE_PROPERTIES_RECORD                    *Image2;
+  IMAGE_PROPERTIES_RECORD                    *Image3;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage1;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage2;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage3;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *AddCodeSectionInImage1;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *AddCodeSectionInImage2;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *AddCodeSectionInImage3;
+  IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT  *TestContext;
+
+  TestContext = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)Context;
+
+  Image1 = CR (TestContext->ImageList.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+  Image2 = CR (Image1->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+  Image3 = CR (Image2->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+
+  CodeSectionInImage1 = CR (Image1->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+  CodeSectionInImage2 = CR (Image2->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+  CodeSectionInImage3 = CR (Image3->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+
+  ///////////////
+  // Descriptor 1
+  ///////////////
+  // |         |      |      |      |      |      |             |
+  // | 4K PAGE | DATA | CODE | DATA | CODE | DATA | 4K PAGE * 5 |
+  // |         |      |      |      |      |      |             |
+
+  Image1->ImageBase                    = BASE_DESCRIPTOR_START_ADDRESS (1) + EFI_PAGE_SIZE;
+  Image1->ImageSize                    = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE - EFI_PAGE_SIZE;
+  Image1->CodeSegmentCount             = 2;
+  CodeSectionInImage1->CodeSegmentBase = Image1->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage1->CodeSegmentSize = EFI_PAGE_SIZE;
+  TestContext->MemoryMap[1].Type       = EfiBootServicesCode;
+
+  AddCodeSectionInImage1                  = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
+  AddCodeSectionInImage1->Signature       = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
+  AddCodeSectionInImage1->CodeSegmentBase = CodeSectionInImage1->CodeSegmentBase + CodeSectionInImage1->CodeSegmentSize + EFI_PAGE_SIZE;
+  AddCodeSectionInImage1->CodeSegmentSize = EFI_PAGE_SIZE;
+
+  InsertTailList (&Image1->CodeSegmentList, &AddCodeSectionInImage1->Link);
+
+  ///////////////
+  // Descriptor 2
+  ///////////////
+  // |         |      |      |      |      |      |             |
+  // | 4K PAGE | DATA | CODE | DATA | CODE | DATA | 4K PAGE * 5 |
+  // |         |      |      |      |      |      |             |
+
+  Image2->ImageBase                    = BASE_DESCRIPTOR_START_ADDRESS (2) + EFI_PAGE_SIZE;
+  Image2->ImageSize                    = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE - EFI_PAGE_SIZE;
+  Image2->CodeSegmentCount             = 2;
+  CodeSectionInImage2->CodeSegmentBase = Image2->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage2->CodeSegmentSize = EFI_PAGE_SIZE;
+  TestContext->MemoryMap[2].Type       = EfiLoaderCode;
+
+  AddCodeSectionInImage2                  = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
+  AddCodeSectionInImage2->Signature       = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
+  AddCodeSectionInImage2->CodeSegmentBase = CodeSectionInImage2->CodeSegmentBase + CodeSectionInImage2->CodeSegmentSize + EFI_PAGE_SIZE;
+  AddCodeSectionInImage2->CodeSegmentSize = EFI_PAGE_SIZE;
+
+  InsertTailList (&Image2->CodeSegmentList, &AddCodeSectionInImage2->Link);
+
+  ///////////////
+  // Descriptor 3
+  ///////////////
+  // |         |      |      |      |      |      |             |
+  // | 4K PAGE | DATA | CODE | DATA | CODE | DATA | 4K PAGE * 5 |
+  // |         |      |      |      |      |      |             |
+
+  Image3->ImageBase                    = BASE_DESCRIPTOR_START_ADDRESS (3) + EFI_PAGE_SIZE;
+  Image3->ImageSize                    = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE - EFI_PAGE_SIZE;
+  Image3->CodeSegmentCount             = 2;
+  CodeSectionInImage3->CodeSegmentBase = Image3->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage3->CodeSegmentSize = EFI_PAGE_SIZE;
+  TestContext->MemoryMap[3].Type       = EfiRuntimeServicesCode;
+
+  AddCodeSectionInImage3                  = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
+  AddCodeSectionInImage3->Signature       = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
+  AddCodeSectionInImage3->CodeSegmentBase = CodeSectionInImage3->CodeSegmentBase + CodeSectionInImage3->CodeSegmentSize + EFI_PAGE_SIZE;
+  AddCodeSectionInImage3->CodeSegmentSize = EFI_PAGE_SIZE;
+
+  InsertTailList (&Image3->CodeSegmentList, &AddCodeSectionInImage3->Link);
+
+  UT_ASSERT_TRUE (SeparateAndCheck (TestContext));
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Test the case where multiple image ranges lie within an existing memory descriptor.
+
+  @param[in]  Context   Context containing the memory map and image record pointers
+
+  @retval  UNIT_TEST_PASSED             The Unit test has completed and the test
+                                        case was successful.
+  @retval  UNIT_TEST_ERROR_TEST_FAILED  A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MultipleImagesInOneDescriptor (
+  IN UNIT_TEST_CONTEXT  Context
+  )
+{
+  IMAGE_PROPERTIES_RECORD                    *Image1;
+  IMAGE_PROPERTIES_RECORD                    *Image2;
+  IMAGE_PROPERTIES_RECORD                    *Image3;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage1;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage2;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage3;
+  IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT  *TestContext;
+
+  TestContext = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)Context;
+
+  Image1 = CR (TestContext->ImageList.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+  Image2 = CR (Image1->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+  Image3 = CR (Image2->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+
+  CodeSectionInImage1 = CR (Image1->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+  CodeSectionInImage2 = CR (Image2->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+  CodeSectionInImage3 = CR (Image3->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+
+  ///////////////
+  // Descriptor 1
+  ///////////////
+  // |         |      |      |      |         |      |      |      |      |      |      |         |
+  // | 4K PAGE | DATA | CODE | DATA | 4K PAGE | DATA | CODE | DATA | DATA | CODE | DATA | 4K PAGE |
+  // |         |      |      |      |         |      |      |      |      |      |      |         |
+
+  Image1->ImageBase                    = BASE_DESCRIPTOR_START_ADDRESS (1) + EFI_PAGE_SIZE;
+  Image1->ImageSize                    = EFI_PAGES_TO_SIZE (3);
+  Image1->CodeSegmentCount             = 1;
+  CodeSectionInImage1->CodeSegmentBase = Image1->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage1->CodeSegmentSize = EFI_PAGE_SIZE;
+  TestContext->MemoryMap[1].Type       = EfiBootServicesCode;
+
+  Image2->ImageBase                    = Image1->ImageBase + Image1->ImageSize + EFI_PAGE_SIZE;
+  Image2->ImageSize                    = EFI_PAGES_TO_SIZE (3);
+  Image2->CodeSegmentCount             = 1;
+  CodeSectionInImage2->CodeSegmentBase = Image2->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage2->CodeSegmentSize = EFI_PAGE_SIZE;
+
+  Image3->ImageBase                    = Image2->ImageBase + Image2->ImageSize;
+  Image3->ImageSize                    = EFI_PAGES_TO_SIZE (3);
+  Image3->CodeSegmentCount             = 1;
+  CodeSectionInImage3->CodeSegmentBase = Image3->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage3->CodeSegmentSize = EFI_PAGE_SIZE;
+
+  UT_ASSERT_TRUE (SeparateAndCheck (TestContext));
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Test the case where all image ranges do not fit perfectly within an existing memory descriptor.
+
+  @param[in]  Context   Context containing the memory map and image record pointers
+
+  @retval  UNIT_TEST_PASSED             The Unit test has completed and the test
+                                        case was successful.
+  @retval  UNIT_TEST_ERROR_TEST_FAILED  A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+ImagesDontFitDescriptors (
+  IN UNIT_TEST_CONTEXT  Context
+  )
+{
+  IMAGE_PROPERTIES_RECORD                    *Image1;
+  IMAGE_PROPERTIES_RECORD                    *Image2;
+  IMAGE_PROPERTIES_RECORD                    *Image3;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage1;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage2;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage3;
+  IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT  *TestContext;
+
+  TestContext = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)Context;
+
+  Image1 = CR (TestContext->ImageList.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+  Image2 = CR (Image1->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+  Image3 = CR (Image2->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+
+  CodeSectionInImage1 = CR (Image1->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+  CodeSectionInImage2 = CR (Image2->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+  CodeSectionInImage3 = CR (Image3->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+
+  ///////////////
+  // Descriptor 1
+  ///////////////
+  // |         |      |          |          |
+  // | 4K PAGE | DATA | CODE * 2 | DATA * 8 |
+  // |         |      |          |          |
+
+  Image1->ImageBase                    = BASE_DESCRIPTOR_START_ADDRESS (1) + EFI_PAGE_SIZE;
+  Image1->ImageSize                    = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE;
+  Image1->CodeSegmentCount             = 1;
+  CodeSectionInImage1->CodeSegmentBase = Image1->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage1->CodeSegmentSize = EFI_PAGES_TO_SIZE (2);
+  TestContext->MemoryMap[1].Type       = EfiBootServicesCode;
+
+  ///////////////
+  // Descriptor 3
+  ///////////////
+  // |      |          |          |         |
+  // | DATA | CODE * 3 | DATA * 7 | 4K PAGE |
+  // |      |          |          |         |
+
+  Image2->ImageBase                    = BASE_DESCRIPTOR_START_ADDRESS (3);
+  Image2->ImageSize                    = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE;
+  Image2->CodeSegmentCount             = 1;
+  CodeSectionInImage2->CodeSegmentBase = Image2->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage2->CodeSegmentSize = EFI_PAGES_TO_SIZE (3);
+  TestContext->MemoryMap[3].Type       = EfiLoaderCode;
+
+  ///////////////
+  // Descriptor 4
+  ///////////////
+  // |         |      |          |          |         |
+  // | 4K PAGE | DATA | CODE * 2 | DATA * 7 | 4K PAGE |
+  // |         |      |          |          |         |
+
+  Image3->ImageBase                    = BASE_DESCRIPTOR_START_ADDRESS (4) + EFI_PAGE_SIZE;
+  Image3->ImageSize                    = BASE_DESCRIPTOR_ENTRY_SIZE - EFI_PAGE_SIZE - EFI_PAGE_SIZE;
+  Image3->CodeSegmentCount             = 1;
+  CodeSectionInImage3->CodeSegmentBase = Image3->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage3->CodeSegmentSize = EFI_PAGES_TO_SIZE (2);
+  TestContext->MemoryMap[4].Type       = EfiRuntimeServicesCode;
+
+  UT_ASSERT_TRUE (SeparateAndCheck (TestContext));
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Test the case where all image ranges fit perfectly within an existing memory descriptor.
+
+  @param[in]  Context   Context containing the memory map and image record pointers
+
+  @retval  UNIT_TEST_PASSED             The Unit test has completed and the test
+                                        case was successful.
+  @retval  UNIT_TEST_ERROR_TEST_FAILED  A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+ImagesFitDescriptors (
+  IN UNIT_TEST_CONTEXT  Context
+  )
+{
+  IMAGE_PROPERTIES_RECORD                    *Image1;
+  IMAGE_PROPERTIES_RECORD                    *Image2;
+  IMAGE_PROPERTIES_RECORD                    *Image3;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage1;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage2;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *CodeSectionInImage3;
+  IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT  *TestContext;
+
+  TestContext = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)Context;
+
+  Image1 = CR (TestContext->ImageList.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+  Image2 = CR (Image1->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+  Image3 = CR (Image2->Link.ForwardLink, IMAGE_PROPERTIES_RECORD, Link, IMAGE_PROPERTIES_RECORD_SIGNATURE);
+
+  CodeSectionInImage1 = CR (Image1->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+  CodeSectionInImage2 = CR (Image2->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+  CodeSectionInImage3 = CR (Image3->CodeSegmentList.ForwardLink, IMAGE_PROPERTIES_RECORD_CODE_SECTION, Link, IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE);
+
+  ///////////////
+  // Descriptor 1
+  ///////////////
+  // |      |          |          |
+  // | DATA | CODE * 3 | DATA * 8 |
+  // |      |          |          |
+
+  Image1->ImageBase                    = BASE_DESCRIPTOR_START_ADDRESS (1);
+  Image1->ImageSize                    = BASE_DESCRIPTOR_ENTRY_SIZE;
+  Image1->CodeSegmentCount             = 1;
+  CodeSectionInImage1->CodeSegmentBase = Image1->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage1->CodeSegmentSize = EFI_PAGES_TO_SIZE (3);
+  TestContext->MemoryMap[1].Type       = EfiBootServicesCode;
+
+  ///////////////
+  // Descriptor 2
+  ///////////////
+  // |      |          |          |
+  // | DATA | CODE * 4 | DATA * 7 |
+  // |      |          |          |
+
+  Image2->ImageBase                    = BASE_DESCRIPTOR_START_ADDRESS (2);
+  Image2->ImageSize                    = BASE_DESCRIPTOR_ENTRY_SIZE;
+  Image2->CodeSegmentCount             = 1;
+  CodeSectionInImage2->CodeSegmentBase = Image2->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage2->CodeSegmentSize = EFI_PAGES_TO_SIZE (4);
+  TestContext->MemoryMap[2].Type       = EfiLoaderCode;
+
+  ///////////////
+  // Descriptor 3
+  ///////////////
+  // |      |          |          |
+  // | DATA | CODE * 3 | DATA * 8 |
+  // |      |          |          |
+
+  Image3->ImageBase                    = BASE_DESCRIPTOR_START_ADDRESS (3);
+  Image3->ImageSize                    = BASE_DESCRIPTOR_ENTRY_SIZE;
+  Image3->CodeSegmentCount             = 1;
+  CodeSectionInImage3->CodeSegmentBase = Image3->ImageBase + EFI_PAGE_SIZE;
+  CodeSectionInImage3->CodeSegmentSize = EFI_PAGES_TO_SIZE (3);
+  TestContext->MemoryMap[3].Type       = EfiRuntimeServicesCode;
+
+  UT_ASSERT_TRUE (SeparateAndCheck (TestContext));
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Free all allocated memory.
+
+  @param[in]  Context   Context containing the memory map and image record pointers
+**/
+VOID
+EFIAPI
+TestCleanup (
+  IN UNIT_TEST_CONTEXT  Context
+  )
+{
+  IMAGE_PROPERTIES_RECORD                    *ImageRecord;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION       *ImageRecordCodeSection;
+  LIST_ENTRY                                 *ImageRecordLink;
+  LIST_ENTRY                                 *CodeSegmentListHead;
+  IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT  *TestContext;
+
+  TestContext     = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)Context;
+  ImageRecordLink = &TestContext->ImageList;
+
+  while (!IsListEmpty (ImageRecordLink)) {
+    ImageRecord = CR (
+                    ImageRecordLink->ForwardLink,
+                    IMAGE_PROPERTIES_RECORD,
+                    Link,
+                    IMAGE_PROPERTIES_RECORD_SIGNATURE
+                    );
+
+    CodeSegmentListHead = &ImageRecord->CodeSegmentList;
+    while (!IsListEmpty (CodeSegmentListHead)) {
+      ImageRecordCodeSection = CR (
+                                 CodeSegmentListHead->ForwardLink,
+                                 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
+                                 Link,
+                                 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
+                                 );
+      RemoveEntryList (&ImageRecordCodeSection->Link);
+      FreePool (ImageRecordCodeSection);
+    }
+
+    RemoveEntryList (&ImageRecord->Link);
+    FreePool (ImageRecord);
+  }
+
+  if (TestContext->MemoryMap != NULL) {
+    FreePool (TestContext->MemoryMap);
+  }
+}
+
+/**
+  Create a generic image list with the proper signatures which will be customized for each test
+  and allocate the default memory map.
+
+  @param[out]  TestContext   Context which will be passed to the test cases
+**/
+STATIC
+VOID
+CreateBaseContextEntry (
+  OUT IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT  *TestContext
+  )
+{
+  IMAGE_PROPERTIES_RECORD               *Image1;
+  IMAGE_PROPERTIES_RECORD               *Image2;
+  IMAGE_PROPERTIES_RECORD               *Image3;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *CodeSectionInImage1;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *CodeSectionInImage2;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *CodeSectionInImage3;
+
+  InitializeListHead (&TestContext->ImageList);
+
+  Image1              = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD));
+  CodeSectionInImage1 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
+
+  Image1->Signature              = IMAGE_PROPERTIES_RECORD_SIGNATURE;
+  CodeSectionInImage1->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
+  InitializeListHead (&Image1->CodeSegmentList);
+
+  InsertTailList (&TestContext->ImageList, &Image1->Link);
+  InsertTailList (&Image1->CodeSegmentList, &CodeSectionInImage1->Link);
+
+  Image2              = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD));
+  CodeSectionInImage2 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
+
+  Image2->Signature              = IMAGE_PROPERTIES_RECORD_SIGNATURE;
+  CodeSectionInImage2->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
+  InitializeListHead (&Image2->CodeSegmentList);
+
+  InsertTailList (&TestContext->ImageList, &Image2->Link);
+  InsertTailList (&Image2->CodeSegmentList, &CodeSectionInImage2->Link);
+
+  Image3              = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD));
+  CodeSectionInImage3 = AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_CODE_SECTION));
+
+  Image3->Signature              = IMAGE_PROPERTIES_RECORD_SIGNATURE;
+  CodeSectionInImage3->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
+  InitializeListHead (&Image3->CodeSegmentList);
+
+  InsertTailList (&TestContext->ImageList, &Image3->Link);
+  InsertTailList (&Image3->CodeSegmentList, &CodeSectionInImage3->Link);
+
+  TestContext->MemoryMap = AllocateZeroPool (SPLIT_MEMORY_MAP_SIZE);
+  CopyMem (TestContext->MemoryMap, &BaseMemoryMap, BASE_MEMORY_MAP_SIZE);
+
+  return;
+}
+
+/**
+  Initialze the unit test framework, suite, and unit tests.
+
+  @retval  EFI_SUCCESS           All test cases were dispatched.
+  @retval  EFI_OUT_OF_RESOURCES  There are not enough resources available to
+                                 initialize the unit tests.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+UnitTestingEntry (
+  VOID
+  )
+{
+  EFI_STATUS                                 Status;
+  UNIT_TEST_FRAMEWORK_HANDLE                 Framework;
+  UNIT_TEST_SUITE_HANDLE                     ImagePropertiesRecordTests;
+  IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT  *Context1;
+  IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT  *Context2;
+  IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT  *Context3;
+  IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT  *Context4;
+
+  DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION));
+
+  Framework = NULL;
+
+  Context1 = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT));
+  Context2 = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT));
+  Context3 = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT));
+  Context4 = (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT *)AllocateZeroPool (sizeof (IMAGE_PROPERTIES_RECORD_HOST_TEST_CONTEXT));
+
+  CreateBaseContextEntry (Context1);
+  CreateBaseContextEntry (Context2);
+  CreateBaseContextEntry (Context3);
+  CreateBaseContextEntry (Context4);
+
+  //
+  // Start setting up the test framework for running the tests.
+  //
+  Status = InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+    goto EXIT;
+  }
+
+  //
+  // Populate the Unit Test Suite.
+  //
+  Status = CreateUnitTestSuite (&ImagePropertiesRecordTests, Framework, "Image Properties Record Tests", "ImagePropertiesRecordLib.SplitTable", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Image Properties Record Tests\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  //
+  // --------------Suite-----------Description--------------Name----------Function--------Pre---Post-------------------Context-----------
+  //
+  AddTestCase (ImagePropertiesRecordTests, "All images fit perfectly into existing descriptors", "ImagesFitDescriptors", ImagesFitDescriptors, NULL, TestCleanup, Context1);
+  AddTestCase (ImagePropertiesRecordTests, "All images don't fit perfectly into existing descriptors", "ImagesDontFitDescriptors", ImagesDontFitDescriptors, NULL, TestCleanup, Context2);
+  AddTestCase (ImagePropertiesRecordTests, "All Images are contined In single descriptor", "MultipleImagesInOneDescriptor", MultipleImagesInOneDescriptor, NULL, TestCleanup, Context3);
+  AddTestCase (ImagePropertiesRecordTests, "Multiple code sections each image", "MaxOutAdditionalDescriptors", MaxOutAdditionalDescriptors, NULL, TestCleanup, Context4);
+
+  //
+  // Execute the tests.
+  //
+  Status = RunAllTestSuites (Framework);
+
+EXIT:
+  if (Framework) {
+    FreeUnitTestFramework (Framework);
+  }
+
+  return Status;
+}
+
+///
+/// Avoid ECC error for function name that starts with lower case letter
+///
+#define ImagePropertiesRecordLibUnitTestMain  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
+ImagePropertiesRecordLibUnitTestMain (
+  IN INT32  Argc,
+  IN CHAR8  *Argv[]
+  )
+{
+  return UnitTestingEntry ();
+}
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.inf b/MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.inf
new file mode 100644
index 000000000000..cbc64a14bde7
--- /dev/null
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.inf
@@ -0,0 +1,35 @@
+## @file
+# Unit tests the SplitTable() ImagePropertiesRecordLib Logic
+#
+# Copyright (C) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010006
+  BASE_NAME                      = ImagePropertiesRecordLibUnitTestHost
+  FILE_GUID                      = 45B39FAA-E25D-4724-A6F4-93C0C8588A80
+  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 AARCH64
+#
+
+[Sources]
+  ImagePropertiesRecordLibUnitTestHost.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  UnitTestLib
+  ImagePropertiesRecordLib
diff --git a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
index 8fb982a2703d..2b8cbb867a73 100644
--- a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
+++ b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
@@ -54,6 +54,11 @@ [Components]
       DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
   }
 
+  MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.inf {
+    <LibraryClasses>
+      ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
+  }
+
   #
   # Build HOST_APPLICATION Libraries
   #
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111745): https://edk2.groups.io/g/devel/message/111745
Mute This Topic: https://groups.io/mt/102834915/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 09/16] MdeModulePkg: Fix MAT Descriptor Count Calculation
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (7 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 08/16] MdeModulePkg: Add ImagePropertiesRecordLib Host-Based Unit Test Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 10/16] MdeModulePkg: Fix MAT SplitRecord() Logic Taylor Beebe
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Liming Gao, Dandan Bi

|4K PAGE|DATA|CODE|DATA|CODE|DATA|4K PAGE|
Say the above memory region is currently one memory map descriptor.
The above image memory layout example contains two code sections
oriented in a way that maximizes the number of descriptors which
would be required to describe each section.

NOTE: It's unlikely that a data section would ever be between
two code sections, but it's still handled by the below formula
for correctness.

There are two code sections (let's say CodeSegmentMax == 2),
three data sections, and two unrelated memory regions flanking the
image. The number of required descriptors to describe this layout
will be 2 * 2 + 3 == 7. This patch updates the calculations to account
for the worst-case scenario.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c                       | 2 +-
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
index 51630f504ea1..af6c26244cc0 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
@@ -517,7 +517,7 @@ CoreGetMemoryMapWithSeparatedImageSection (
 
   CoreAcquiremMemoryAttributesTableLock ();
 
-  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;
+  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 3) * mImagePropertiesPrivateData.ImageRecordCount;
 
   OldMemoryMapSize = *MemoryMapSize;
   Status           = CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
index 9fb3b922038f..7c0ecd07c1bb 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
@@ -277,7 +277,7 @@ GetMaxSplitRecordCount (
       break;
     }
 
-    SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1);
+    SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 3);
     PhysicalStart     = ImageRecord->ImageBase + ImageRecord->ImageSize;
   } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
 
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111746): https://edk2.groups.io/g/devel/message/111746
Mute This Topic: https://groups.io/mt/102834916/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 10/16] MdeModulePkg: Fix MAT SplitRecord() Logic
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (8 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 09/16] MdeModulePkg: Fix MAT Descriptor Count Calculation Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2024-04-12  5:14   ` [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows Huang, Yanbo
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 11/16] MdeModulePkg: Fix MAT SplitTable() Logic Taylor Beebe
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Liming Gao, Dandan Bi

SplitRecord() does not handle the case where a memory descriptor
describes an image region plus extra pages before or after the
image region. This patch fixes this case by carving off the
unrelated regions into their own descriptors.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c | 56 ++++++++++----------
 1 file changed, 27 insertions(+), 29 deletions(-)

diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
index 7c0ecd07c1bb..9d4082280bf5 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
@@ -323,7 +323,6 @@ SplitRecord (
   UINT64                   PhysicalEnd;
   UINTN                    NewRecordCount;
   UINTN                    TotalNewRecordCount;
-  BOOLEAN                  IsLastRecordData;
 
   if (MaxSplitRecordCount == 0) {
     CopyMem (NewRecord, OldRecord, DescriptorSize);
@@ -344,35 +343,16 @@ SplitRecord (
     NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
     if (NewImageRecord == NULL) {
       //
-      // No more image covered by this range, stop
+      // No more images cover this range, check if we've reached the end of the old descriptor. If not,
+      // add the remaining range to the new descriptor list.
       //
-      if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {
-        //
-        // If this is still address in this record, need record.
-        //
-        NewRecord        = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-        IsLastRecordData = FALSE;
-        if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) {
-          IsLastRecordData = TRUE;
-        }
-
-        if (IsLastRecordData) {
-          //
-          // Last record is DATA, just merge it.
-          //
-          NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - NewRecord->PhysicalStart);
-        } else {
-          //
-          // Last record is CODE, create a new DATA entry.
-          //
-          NewRecord                = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-          NewRecord->Type          = TempRecord.Type;
-          NewRecord->PhysicalStart = TempRecord.PhysicalStart;
-          NewRecord->VirtualStart  = 0;
-          NewRecord->NumberOfPages = TempRecord.NumberOfPages;
-          NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
-          TotalNewRecordCount++;
-        }
+      if (PhysicalEnd > PhysicalStart) {
+        NewRecord->Type          = TempRecord.Type;
+        NewRecord->PhysicalStart = PhysicalStart;
+        NewRecord->VirtualStart  = 0;
+        NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
+        NewRecord->Attribute     = TempRecord.Attribute;
+        TotalNewRecordCount++;
       }
 
       break;
@@ -380,6 +360,24 @@ SplitRecord (
 
     ImageRecord = NewImageRecord;
 
+    //
+    // Update PhysicalStart to exclude the portion before the image buffer
+    //
+    if (TempRecord.PhysicalStart < ImageRecord->ImageBase) {
+      NewRecord->Type          = TempRecord.Type;
+      NewRecord->PhysicalStart = TempRecord.PhysicalStart;
+      NewRecord->VirtualStart  = 0;
+      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecord->ImageBase - TempRecord.PhysicalStart);
+      NewRecord->Attribute     = TempRecord.Attribute;
+      TotalNewRecordCount++;
+
+      PhysicalStart            = ImageRecord->ImageBase;
+      TempRecord.PhysicalStart = PhysicalStart;
+      TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
+
+      NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + DescriptorSize);
+    }
+
     //
     // Set new record
     //
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111747): https://edk2.groups.io/g/devel/message/111747
Mute This Topic: https://groups.io/mt/102834917/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 11/16] MdeModulePkg: Fix MAT SplitTable() Logic
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (9 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 10/16] MdeModulePkg: Fix MAT SplitRecord() Logic Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 12/16] MdeModulePkg: Add NULL checks and Return Status to ImagePropertiesRecordLib Taylor Beebe
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Liming Gao, Dandan Bi

SplitTable() does not properly handle the case where there is
an odd number of code regions within a loaded image. When there are
an odd number of code regions, at least one image region descriptor
is overwritten with uninitialized memory which has caused crashes
in the right conditions.

This failure cases is documented extensively in the following bugzilla:
https://bugzilla.tianocore.org/show_bug.cgi?id=4492

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c | 40 ++++++++++----------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
index 9d4082280bf5..379eb0c6cccd 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
@@ -463,11 +463,12 @@ SplitTable (
 {
   INTN   IndexOld;
   INTN   IndexNew;
+  INTN   IndexNewStarting;
   UINTN  MaxSplitRecordCount;
   UINTN  RealSplitRecordCount;
-  UINTN  TotalSplitRecordCount;
+  UINTN  TotalSkippedRecords;
 
-  TotalSplitRecordCount = 0;
+  TotalSkippedRecords = 0;
   //
   // Let old record point to end of valid MemoryMap buffer.
   //
@@ -475,7 +476,8 @@ SplitTable (
   //
   // Let new record point to end of full MemoryMap buffer.
   //
-  IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + NumberOfAdditionalDescriptors;
+  IndexNew         = ((*MemoryMapSize) / DescriptorSize) - 1 + NumberOfAdditionalDescriptors;
+  IndexNewStarting = IndexNew;
   for ( ; IndexOld >= 0; IndexOld--) {
     MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), ImageRecordList);
     //
@@ -489,16 +491,14 @@ SplitTable (
                              DescriptorSize,
                              ImageRecordList
                              );
-    //
-    // Adjust IndexNew according to real split.
-    //
-    CopyMem (
-      ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),
-      ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
-      RealSplitRecordCount * DescriptorSize
-      );
-    IndexNew               = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;
-    TotalSplitRecordCount += RealSplitRecordCount;
+
+    // If we didn't utilize all the extra allocated descriptor slots, set the physical address of the unused slots
+    // to MAX_ADDRESS so they are moved to the bottom of the list when sorting.
+    for ( ; RealSplitRecordCount < MaxSplitRecordCount; RealSplitRecordCount++) {
+      ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + ((IndexNew + RealSplitRecordCount + 1) * DescriptorSize)))->PhysicalStart = MAX_ADDRESS;
+      TotalSkippedRecords++;
+    }
+
     IndexNew--;
   }
 
@@ -507,16 +507,16 @@ SplitTable (
   //
   CopyMem (
     MemoryMap,
-    (UINT8 *)MemoryMap + (NumberOfAdditionalDescriptors - TotalSplitRecordCount) * DescriptorSize,
-    (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize
+    (UINT8 *)MemoryMap + ((IndexNew + 1) * DescriptorSize),
+    (IndexNewStarting - IndexNew) * DescriptorSize
     );
 
-  *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount;
+  //
+  // Sort from low to high to filter out the MAX_ADDRESS records.
+  //
+  SortMemoryMap (MemoryMap, (IndexNewStarting - IndexNew) * DescriptorSize, DescriptorSize);
 
-  //
-  // Sort from low to high (Just in case)
-  //
-  SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
+  *MemoryMapSize = (IndexNewStarting - IndexNew - TotalSkippedRecords) * DescriptorSize;
 
   return;
 }
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111748): https://edk2.groups.io/g/devel/message/111748
Mute This Topic: https://groups.io/mt/102834918/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 12/16] MdeModulePkg: Add NULL checks and Return Status to ImagePropertiesRecordLib
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (10 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 11/16] MdeModulePkg: Fix MAT SplitTable() Logic Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 13/16] UefiCpuPkg: Use Attribute From SMM MemoryAttributesTable if Nonzero Taylor Beebe
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Liming Gao, Dandan Bi

Update function headers to clarify the contract of each function and
improve readability. Add NULL checks to all functions that take a
pointer as an argument. Add return status to functions that
may need to return early due to invalid input.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c | 290 ++++++++++++--------
 MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h                  | 137 ++++-----
 2 files changed, 246 insertions(+), 181 deletions(-)

diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
index 379eb0c6cccd..c9378679e7bb 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
@@ -22,14 +22,13 @@
   ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))
 
 /**
-  Converts a number of EFI_PAGEs to a size in bytes.
+  Converts a number of pages to a size in bytes.
 
   NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
 
-  @param  Pages     The number of EFI_PAGES.
+  @param[in]  Pages     The number of EFI_PAGES.
 
-  @return  The number of bytes associated with the number of EFI_PAGEs specified
-           by Pages.
+  @retval  The number of bytes associated with the input number of pages.
 **/
 STATIC
 UINT64
@@ -45,10 +44,9 @@ EfiPagesToSize (
 
   NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
 
-  @param  Size      A size in bytes.
+  @param[in]  Size      A size in bytes.
 
-  @return  The number of EFI_PAGESs associated with the number of bytes specified
-           by Size.
+  @retval  The number of pages associated with the input number of bytes.
 
 **/
 STATIC
@@ -61,12 +59,12 @@ EfiSizeToPages (
 }
 
 /**
-  Sort memory map entries based upon PhysicalStart, from low to high.
+  Sort memory map entries based upon PhysicalStart from low to high.
 
-  @param  MemoryMap              A pointer to the buffer in which firmware places
-                                 the current memory map.
-  @param  MemoryMapSize          Size, in bytes, of the MemoryMap buffer.
-  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param[in, out] MemoryMap       A pointer to the buffer in which firmware places
+                                  the current memory map.
+  @param[in]      MemoryMapSize   Size, in bytes, of the MemoryMap buffer.
+  @param[in]      DescriptorSize  Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
 **/
 STATIC
 VOID
@@ -105,11 +103,12 @@ SortMemoryMap (
 /**
   Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
 
-  @param Buffer           Start Address
-  @param Length           Address length
-  @param ImageRecordList  Image record list
+  @param[in] Buffer           Starting Address
+  @param[in] Length           Length to check
+  @param[in] ImageRecordList  A list of IMAGE_PROPERTIES_RECORD entries to check against
+                              the memory range Buffer -> Buffer + Length
 
-  @return first image record covered by [buffer, length]
+  @retval The first image record covered by [Buffer, Length]
 **/
 STATIC
 IMAGE_PROPERTIES_RECORD *
@@ -144,17 +143,19 @@ GetImageRecordByAddress (
 }
 
 /**
-  Set the memory map to new entries, according to one old entry,
-  based upon PE code section and data section in image record
+  Break up the input OldRecord into multiple new records based on the code
+  and data sections in the input ImageRecord.
 
-  @param  ImageRecord            An image record whose [ImageBase, ImageSize] covered
-                                 by old memory map entry.
-  @param  NewRecord              A pointer to several new memory map entries.
-                                 The caller gurantee the buffer size be 1 +
-                                 (SplitRecordCount * DescriptorSize) calculated
-                                 below.
-  @param  OldRecord              A pointer to one old memory map entry.
-  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param[in]        ImageRecord       An IMAGE_PROPERTIES_RECORD whose ImageBase and
+                                      ImageSize is covered by by OldRecord.
+  @param[in, out]   NewRecord         A pointer to several new memory map entries.
+                                      The caller gurantee the buffer size be 1 +
+                                      (SplitRecordCount * DescriptorSize) calculated
+                                      below.
+  @param[in]        OldRecord         A pointer to one old memory map entry.
+  @param[in]        DescriptorSize    The size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+
+  @retval The number of new descriptors created.
 **/
 STATIC
 UINTN
@@ -244,16 +245,16 @@ SetNewRecord (
 }
 
 /**
-  Return the max number of new splitted entries, according to one old entry,
-  based upon PE code section and data section.
+  Return the maximum number of new entries required to describe the code and data sections
+  of all images covered by the input OldRecord.
 
-  @param  OldRecord              A pointer to one old memory map entry.
-  @param  ImageRecordList        A list of IMAGE_PROPERTIES_RECORD entries used when searching
-                                 for an image record contained by the memory range described in
-                                 the existing EFI memory map descriptor OldRecord
+  @param[in]  OldRecord         A pointer to one old memory map entry.
+  @param[in]  ImageRecordList   A list of IMAGE_PROPERTIES_RECORD entries used when searching
+                                for an image record contained by the memory range described by
+                                OldRecord
 
-  @retval  0 no entry need to be splitted.
-  @return  the max number of new splitted entries
+  @retval  The maximum number of new descriptors required to describe the code and data sections
+           of all images covered by OldRecord.
 **/
 STATIC
 UINTN
@@ -289,22 +290,20 @@ GetMaxSplitRecordCount (
 }
 
 /**
-  Split the memory map to new entries, according to one old entry,
-  based upon PE code section and data section.
+  Split the memory map into new entries based upon the PE code and data sections
+  in ImageRecordList covered by the input OldRecord.
 
-  @param        OldRecord             A pointer to one old memory map entry.
-  @param        NewRecord             A pointer to several new memory map entries.
-                                      The caller gurantee the buffer size be 1 +
-                                      (SplitRecordCount * DescriptorSize) calculated
-                                      below.
-  @param        MaxSplitRecordCount   The max number of splitted entries
-  @param        DescriptorSize        Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-  @param        ImageRecordList       A list of IMAGE_PROPERTIES_RECORD entries used when searching
-                                      for an image record contained by the memory range described in
-                                      the existing EFI memory map descriptor OldRecord
+  @param[in]        OldRecord             A pointer to one old memory map entry.
+  @param[in, out]   NewRecord             A pointer to several new memory map entries.
+                                          The caller gurantee the buffer size be
+                                          (SplitRecordCount * DescriptorSize).
+  @param[in]        MaxSplitRecordCount   The maximum number of entries post-split.
+  @param[in]        DescriptorSize        The size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param[in]        ImageRecordList       A list of IMAGE_PROPERTIES_RECORD entries used when searching
+                                          for an image record contained by the memory range described in
+                                          the existing EFI memory map descriptor OldRecord
 
-  @retval  0 no entry is splitted.
-  @return  the real number of splitted record.
+  @retval  The number of split entries.
 **/
 STATIC
 UINTN
@@ -402,56 +401,47 @@ SplitRecord (
 }
 
 /**
-  Split the original memory map, and add more entries to describe PE code section and data section.
-  This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
-  This function will merge entries with same attributes finally.
+  Split the original memory map and add more entries to describe PE code
+  and data sections for each image in the input ImageRecordList.
 
-  NOTE: It assumes PE code/data section are page aligned.
-  NOTE: It assumes enough entry is prepared for new memory map.
+  NOTE: This function assumes PE code/data section are page aligned.
+  NOTE: This function assumes there are enough entries for the new memory map.
 
-  Split table:
-   +---------------+
-   | Record X      |
-   +---------------+
-   | Record RtCode |
-   +---------------+
-   | Record Y      |
-   +---------------+
-   ==>
-   +---------------+
-   | Record X      |
-   +---------------+ ----
-   | Record RtData |     |
-   +---------------+     |
-   | Record RtCode |     |-> PE/COFF1
-   +---------------+     |
-   | Record RtData |     |
-   +---------------+ ----
-   | Record RtData |     |
-   +---------------+     |
-   | Record RtCode |     |-> PE/COFF2
-   +---------------+     |
-   | Record RtData |     |
-   +---------------+ ----
-   | Record Y      |
-   +---------------+
+  |         |      |      |      |      |      |         |
+  | 4K PAGE | DATA | CODE | DATA | CODE | DATA | 4K PAGE |
+  |         |      |      |      |      |      |         |
+  Assume the above memory region is the result of one split memory map descriptor. It's unlikely
+  that a linker will orient an image this way, but the caller must assume the worst case scenario.
+  This image layout example contains code sections oriented in a way that maximizes the number of
+  descriptors which would be required to describe each section. To ensure we have enough space
+  for every descriptor of the broken up memory map, the caller must assume that every image will
+  have the maximum number of code sections oriented in a way which maximizes the number of data
+  sections with unrelated memory regions flanking each image within a single descriptor.
 
-  @param  MemoryMapSize                   A pointer to the size, in bytes, of the
-                                          MemoryMap buffer. On input, this is the size of
-                                          old MemoryMap before split. The actual buffer
-                                          size of MemoryMap is MemoryMapSize +
-                                          (AdditionalRecordCount * DescriptorSize) calculated
-                                          below. On output, it is the size of new MemoryMap
-                                          after split.
-  @param  MemoryMap                       A pointer to the buffer in which firmware places
-                                          the current memory map.
-  @param  DescriptorSize                  Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-  @param  ImageRecordList                 A list of IMAGE_PROPERTIES_RECORD entries used when searching
-                                          for an image record contained by the memory range described in
-                                          EFI memory map descriptors.
-  @param  NumberOfAdditionalDescriptors   The number of unused descriptors at the end of the input MemoryMap.
+  Given an image record list, the caller should use the following formula when allocating extra descriptors:
+  NumberOfAdditionalDescriptors = (MemoryMapSize / DescriptorSize) +
+                                    ((2 * <Most Code Segments in a Single Image> + 3) * <Number of Images>)
+
+  @param[in, out] MemoryMapSize                   IN:   The size, in bytes, of the old memory map before the split.
+                                                  OUT:  The size, in bytes, of the used descriptors of the split
+                                                        memory map
+  @param[in, out] MemoryMap                       IN:   A pointer to the buffer containing the current memory map.
+                                                        This buffer must have enough space to accomodate the "worst case"
+                                                        scenario where every image in ImageRecordList needs a new descriptor
+                                                        to describe its code and data sections.
+                                                  OUT:  A pointer to the updated memory map with separated image section
+                                                        descriptors.
+  @param[in]      DescriptorSize                  The size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param[in]      ImageRecordList                 A list of IMAGE_PROPERTIES_RECORD entries used when searching
+                                                  for an image record contained by the memory range described in
+                                                  EFI memory map descriptors.
+  @param[in]      NumberOfAdditionalDescriptors   The number of unused descriptors at the end of the input MemoryMap.
+                                                  The formula in the description should be used to calculate this value.
+
+  @retval EFI_SUCCESS                             The memory map was successfully split.
+  @retval EFI_INVALID_PARAMETER                   MemoryMapSize, MemoryMap, or ImageRecordList was NULL.
 **/
-VOID
+EFI_STATUS
 EFIAPI
 SplitTable (
   IN OUT UINTN                  *MemoryMapSize,
@@ -468,6 +458,10 @@ SplitTable (
   UINTN  RealSplitRecordCount;
   UINTN  TotalSkippedRecords;
 
+  if ((MemoryMapSize == NULL) || (MemoryMap == NULL) || (ImageRecordList == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
   TotalSkippedRecords = 0;
   //
   // Let old record point to end of valid MemoryMap buffer.
@@ -518,16 +512,19 @@ SplitTable (
 
   *MemoryMapSize = (IndexNewStarting - IndexNew - TotalSkippedRecords) * DescriptorSize;
 
-  return;
+  return EFI_SUCCESS;
 }
 
 /**
-  Swap two code sections in image record.
+  Swap two code sections in a single IMAGE_PROPERTIES_RECORD.
 
-  @param  FirstImageRecordCodeSection    first code section in image record
-  @param  SecondImageRecordCodeSection   second code section in image record
+  @param[in]  FirstImageRecordCodeSection    The first code section
+  @param[in]  SecondImageRecordCodeSection   The second code section
+
+  @retval EFI_SUCCESS                        The code sections were swapped successfully
+  @retval EFI_INVALID_PARAMETER              FirstImageRecordCodeSection or SecondImageRecordCodeSection is NULL
 **/
-VOID
+EFI_STATUS
 EFIAPI
 SwapImageRecordCodeSection (
   IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *FirstImageRecordCodeSection,
@@ -536,6 +533,10 @@ SwapImageRecordCodeSection (
 {
   IMAGE_PROPERTIES_RECORD_CODE_SECTION  TempImageRecordCodeSection;
 
+  if ((FirstImageRecordCodeSection == NULL) || (SecondImageRecordCodeSection == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
   TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;
   TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;
 
@@ -544,19 +545,26 @@ SwapImageRecordCodeSection (
 
   SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;
   SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;
+
+  return EFI_SUCCESS;
 }
 
 /**
-  Sort code section in image record, based upon CodeSegmentBase from low to high.
+  Sort the code sections in the input ImageRecord based upon CodeSegmentBase from low to high.
 
-  @param  ImageRecord    image record to be sorted
+  @param[in]  ImageRecord         IMAGE_PROPERTIES_RECORD to be sorted
+
+  @retval EFI_SUCCESS             The code sections in the input ImageRecord were sorted successfully
+  @retval EFI_ABORTED             An error occurred while sorting the code sections in the input ImageRecord
+  @retval EFI_INVALID_PARAMETER   ImageRecord is NULL
 **/
-VOID
+EFI_STATUS
 EFIAPI
 SortImageRecordCodeSection (
   IN IMAGE_PROPERTIES_RECORD  *ImageRecord
   )
 {
+  EFI_STATUS                            Status;
   IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
   IMAGE_PROPERTIES_RECORD_CODE_SECTION  *NextImageRecordCodeSection;
   LIST_ENTRY                            *ImageRecordCodeSectionLink;
@@ -564,6 +572,10 @@ SortImageRecordCodeSection (
   LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
   LIST_ENTRY                            *ImageRecordCodeSectionList;
 
+  if (ImageRecord == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
   ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
 
   ImageRecordCodeSectionLink     = ImageRecordCodeSectionList->ForwardLink;
@@ -584,7 +596,11 @@ SortImageRecordCodeSection (
                                      IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
                                      );
       if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {
-        SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);
+        Status = SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);
+        if (EFI_ERROR (Status)) {
+          ASSERT_EFI_ERROR (Status);
+          return EFI_ABORTED;
+        }
       }
 
       NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;
@@ -593,15 +609,20 @@ SortImageRecordCodeSection (
     ImageRecordCodeSectionLink     = ImageRecordCodeSectionLink->ForwardLink;
     NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
   }
+
+  return EFI_SUCCESS;
 }
 
 /**
-  Check if code section in image record is valid.
+  Check if the code sections in the input ImageRecord are valid.
+  The code sections are valid if they don't overlap, are contained
+  within the the ImageRecord's ImageBase and ImageSize, and are
+  contained within the MAX_ADDRESS.
 
-  @param  ImageRecord    image record to be checked
+  @param[in]  ImageRecord    IMAGE_PROPERTIES_RECORD to be checked
 
-  @retval TRUE  image record is valid
-  @retval FALSE image record is invalid
+  @retval TRUE  The code sections in the input ImageRecord are valid
+  @retval FALSE The code sections in the input ImageRecord are invalid
 **/
 BOOLEAN
 EFIAPI
@@ -615,6 +636,10 @@ IsImageRecordCodeSectionValid (
   LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
   LIST_ENTRY                            *ImageRecordCodeSectionList;
 
+  if (ImageRecord == NULL) {
+    return FALSE;
+  }
+
   DEBUG ((DEBUG_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));
 
   ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
@@ -661,10 +686,13 @@ IsImageRecordCodeSectionValid (
 /**
   Swap two image records.
 
-  @param  FirstImageRecord   first image record.
-  @param  SecondImageRecord  second image record.
+  @param[in]  FirstImageRecord   The first image record.
+  @param[in]  SecondImageRecord  The second image record.
+
+  @retval EFI_SUCCESS            The image records were swapped successfully
+  @retval EFI_INVALID_PARAMETER  FirstImageRecord or SecondImageRecord is NULL
 **/
-VOID
+EFI_STATUS
 EFIAPI
 SwapImageRecord (
   IN IMAGE_PROPERTIES_RECORD  *FirstImageRecord,
@@ -673,6 +701,10 @@ SwapImageRecord (
 {
   IMAGE_PROPERTIES_RECORD  TempImageRecord;
 
+  if ((FirstImageRecord == NULL) || (SecondImageRecord == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
   TempImageRecord.ImageBase        = FirstImageRecord->ImageBase;
   TempImageRecord.ImageSize        = FirstImageRecord->ImageSize;
   TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;
@@ -686,14 +718,19 @@ SwapImageRecord (
   SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;
 
   SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);
+  return EFI_SUCCESS;
 }
 
 /**
-  Sort image record based upon the ImageBase from low to high.
+  Sort the input ImageRecordList based upon the ImageBase from low to high.
 
-  @param ImageRecordList    Image record list to be sorted
+  @param[in] ImageRecordList    Image record list to be sorted
+
+  @retval EFI_SUCCESS           The image record list was sorted successfully
+  @retval EFI_ABORTED           An error occurred while sorting the image record list
+  @retval EFI_INVALID_PARAMETER ImageRecordList is NULL
 **/
-VOID
+EFI_STATUS
 EFIAPI
 SortImageRecord (
   IN LIST_ENTRY  *ImageRecordList
@@ -704,6 +741,11 @@ SortImageRecord (
   LIST_ENTRY               *ImageRecordLink;
   LIST_ENTRY               *NextImageRecordLink;
   LIST_ENTRY               *ImageRecordEndLink;
+  EFI_STATUS               Status;
+
+  if (ImageRecordList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
 
   ImageRecordLink     = ImageRecordList->ForwardLink;
   NextImageRecordLink = ImageRecordLink->ForwardLink;
@@ -724,7 +766,11 @@ SortImageRecord (
 
                           );
       if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {
-        SwapImageRecord (ImageRecord, NextImageRecord);
+        Status = SwapImageRecord (ImageRecord, NextImageRecord);
+        if (EFI_ERROR (Status)) {
+          ASSERT_EFI_ERROR (Status);
+          return EFI_ABORTED;
+        }
       }
 
       NextImageRecordLink = NextImageRecordLink->ForwardLink;
@@ -733,16 +779,20 @@ SortImageRecord (
     ImageRecordLink     = ImageRecordLink->ForwardLink;
     NextImageRecordLink = ImageRecordLink->ForwardLink;
   }
+
+  return EFI_SUCCESS;
 }
 
 /**
   Find image record according to image base and size.
 
-  @param  ImageBase           Base of PE image
-  @param  ImageSize           Size of PE image
-  @param  ImageRecordList     Image record list to be searched
+  @param[in]  ImageBase           Base of PE image
+  @param[in]  ImageSize           Size of PE image
+  @param[in]  ImageRecordList     Image record list to be searched
 
-  @return image record
+  @retval    NULL             No IMAGE_PROPERTIES_RECORD matches ImageBase
+                              and ImageSize in the input ImageRecordList
+  @retval    Other            The found IMAGE_PROPERTIES_RECORD
 **/
 IMAGE_PROPERTIES_RECORD *
 EFIAPI
@@ -755,6 +805,10 @@ FindImageRecord (
   IMAGE_PROPERTIES_RECORD  *ImageRecord;
   LIST_ENTRY               *ImageRecordLink;
 
+  if (ImageRecordList == NULL) {
+    return NULL;
+  }
+
   for (ImageRecordLink = ImageRecordList->ForwardLink;
        ImageRecordLink != ImageRecordList;
        ImageRecordLink = ImageRecordLink->ForwardLink)
diff --git a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
index 9139c7b6c05d..b6365662646a 100644
--- a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
+++ b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
@@ -32,56 +32,47 @@ typedef struct {
 } IMAGE_PROPERTIES_RECORD;
 
 /**
-  Split the original memory map, and add more entries to describe PE code section and data section.
-  This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
-  This function will merge entries with same attributes finally.
+  Split the original memory map and add more entries to describe PE code
+  and data sections for each image in the input ImageRecordList.
 
-  NOTE: It assumes PE code/data section are page aligned.
-  NOTE: It assumes enough entry is prepared for new memory map.
+  NOTE: This function assumes PE code/data section are page aligned.
+  NOTE: This function assumes there are enough entries for the new memory map.
 
-  Split table:
-   +---------------+
-   | Record X      |
-   +---------------+
-   | Record RtCode |
-   +---------------+
-   | Record Y      |
-   +---------------+
-   ==>
-   +---------------+
-   | Record X      |
-   +---------------+ ----
-   | Record RtData |     |
-   +---------------+     |
-   | Record RtCode |     |-> PE/COFF1
-   +---------------+     |
-   | Record RtData |     |
-   +---------------+ ----
-   | Record RtData |     |
-   +---------------+     |
-   | Record RtCode |     |-> PE/COFF2
-   +---------------+     |
-   | Record RtData |     |
-   +---------------+ ----
-   | Record Y      |
-   +---------------+
+  |         |      |      |      |      |      |         |
+  | 4K PAGE | DATA | CODE | DATA | CODE | DATA | 4K PAGE |
+  |         |      |      |      |      |      |         |
+  Assume the above memory region is the result of one split memory map descriptor. It's unlikely
+  that a linker will orient an image this way, but the caller must assume the worst case scenario.
+  This image layout example contains code sections oriented in a way that maximizes the number of
+  descriptors which would be required to describe each section. To ensure we have enough space
+  for every descriptor of the broken up memory map, the caller must assume that every image will
+  have the maximum number of code sections oriented in a way which maximizes the number of data
+  sections with unrelated memory regions flanking each image within a single descriptor.
 
-  @param  MemoryMapSize                   A pointer to the size, in bytes, of the
-                                          MemoryMap buffer. On input, this is the size of
-                                          old MemoryMap before split. The actual buffer
-                                          size of MemoryMap is MemoryMapSize +
-                                          (AdditionalRecordCount * DescriptorSize) calculated
-                                          below. On output, it is the size of new MemoryMap
-                                          after split.
-  @param  MemoryMap                       A pointer to the buffer in which firmware places
-                                          the current memory map.
-  @param  DescriptorSize                  Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-  @param  ImageRecordList                 A list of IMAGE_PROPERTIES_RECORD entries used when searching
-                                          for an image record contained by the memory range described in
-                                          EFI memory map descriptors.
-  @param  NumberOfAdditionalDescriptors   The number of unused descriptors at the end of the input MemoryMap.
+  Given an image record list, the caller should use the following formula when allocating extra descriptors:
+  NumberOfAdditionalDescriptors = (MemoryMapSize / DescriptorSize) +
+                                    ((2 * <Most Code Segments in a Single Image> + 3) * <Number of Images>)
+
+  @param[in, out] MemoryMapSize                   IN:   The size, in bytes, of the old memory map before the split.
+                                                  OUT:  The size, in bytes, of the used descriptors of the split
+                                                        memory map
+  @param[in, out] MemoryMap                       IN:   A pointer to the buffer containing the current memory map.
+                                                        This buffer must have enough space to accomodate the "worst case"
+                                                        scenario where every image in ImageRecordList needs a new descriptor
+                                                        to describe its code and data sections.
+                                                  OUT:  A pointer to the updated memory map with separated image section
+                                                        descriptors.
+  @param[in]      DescriptorSize                  The size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+  @param[in]      ImageRecordList                 A list of IMAGE_PROPERTIES_RECORD entries used when searching
+                                                  for an image record contained by the memory range described in
+                                                  EFI memory map descriptors.
+  @param[in]      NumberOfAdditionalDescriptors   The number of unused descriptors at the end of the input MemoryMap.
+                                                  The formula in the description should be used to calculate this value.
+
+  @retval EFI_SUCCESS                             The memory map was successfully split.
+  @retval EFI_INVALID_PARAMETER                   MemoryMapSize, MemoryMap, or ImageRecordList was NULL.
 **/
-VOID
+EFI_STATUS
 EFIAPI
 SplitTable (
   IN OUT UINTN                  *MemoryMapSize,
@@ -92,23 +83,30 @@ SplitTable (
   );
 
 /**
-  Sort code section in image record, based upon CodeSegmentBase from low to high.
+  Sort the code sections in the input ImageRecord based upon CodeSegmentBase from low to high.
 
-  @param  ImageRecord    image record to be sorted
+  @param[in]  ImageRecord         IMAGE_PROPERTIES_RECORD to be sorted
+
+  @retval EFI_SUCCESS             The code sections in the input ImageRecord were sorted successfully
+  @retval EFI_ABORTED             An error occurred while sorting the code sections in the input ImageRecord
+  @retval EFI_INVALID_PARAMETER   ImageRecord is NULL
 **/
-VOID
+EFI_STATUS
 EFIAPI
 SortImageRecordCodeSection (
   IN IMAGE_PROPERTIES_RECORD  *ImageRecord
   );
 
 /**
-  Check if code section in image record is valid.
+  Check if the code sections in the input ImageRecord are valid.
+  The code sections are valid if they don't overlap, are contained
+  within the the ImageRecord's ImageBase and ImageSize, and are
+  contained within the MAX_ADDRESS.
 
-  @param  ImageRecord    image record to be checked
+  @param[in]  ImageRecord    IMAGE_PROPERTIES_RECORD to be checked
 
-  @retval TRUE  image record is valid
-  @retval FALSE image record is invalid
+  @retval TRUE  The code sections in the input ImageRecord are valid
+  @retval FALSE The code sections in the input ImageRecord are invalid
 **/
 BOOLEAN
 EFIAPI
@@ -117,11 +115,15 @@ IsImageRecordCodeSectionValid (
   );
 
 /**
-  Sort image record based upon the ImageBase from low to high.
+  Sort the input ImageRecordList based upon the ImageBase from low to high.
 
-  @param ImageRecordList    Image record list to be sorted
+  @param[in] ImageRecordList    Image record list to be sorted
+
+  @retval EFI_SUCCESS           The image record list was sorted successfully
+  @retval EFI_ABORTED           An error occurred while sorting the image record list
+  @retval EFI_INVALID_PARAMETER ImageRecordList is NULL
 **/
-VOID
+EFI_STATUS
 EFIAPI
 SortImageRecord (
   IN LIST_ENTRY  *ImageRecordList
@@ -132,8 +134,11 @@ SortImageRecord (
 
   @param[in]  FirstImageRecord   The first image record.
   @param[in]  SecondImageRecord  The second image record.
+
+  @retval EFI_SUCCESS            The image records were swapped successfully
+  @retval EFI_INVALID_PARAMETER  FirstImageRecord or SecondImageRecord is NULL
 **/
-VOID
+EFI_STATUS
 EFIAPI
 SwapImageRecord (
   IN IMAGE_PROPERTIES_RECORD  *FirstImageRecord,
@@ -145,8 +150,11 @@ SwapImageRecord (
 
   @param[in]  FirstImageRecordCodeSection    The first code section
   @param[in]  SecondImageRecordCodeSection   The second code section
+
+  @retval EFI_SUCCESS                        The code sections were swapped successfully
+  @retval EFI_INVALID_PARAMETER              FirstImageRecordCodeSection or SecondImageRecordCodeSection is NULL
 **/
-VOID
+EFI_STATUS
 EFIAPI
 SwapImageRecordCodeSection (
   IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *FirstImageRecordCodeSection,
@@ -154,13 +162,16 @@ SwapImageRecordCodeSection (
   );
 
 /**
-  Find image record according to image base and size.
+  Find image properties record according to image base and size in the
+  input ImageRecordList.
 
-  @param  ImageBase           Base of PE image
-  @param  ImageSize           Size of PE image
-  @param  ImageRecordList     Image record list to be searched
+  @param[in]  ImageBase           Base of PE image
+  @param[in]  ImageSize           Size of PE image
+  @param[in]  ImageRecordList     Image record list to be searched
 
-  @return image record
+  @retval    NULL             No IMAGE_PROPERTIES_RECORD matches ImageBase
+                              and ImageSize in the input ImageRecordList
+  @retval    Other            The found IMAGE_PROPERTIES_RECORD
 **/
 IMAGE_PROPERTIES_RECORD *
 EFIAPI
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111749): https://edk2.groups.io/g/devel/message/111749
Mute This Topic: https://groups.io/mt/102834920/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 13/16] UefiCpuPkg: Use Attribute From SMM MemoryAttributesTable if Nonzero
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (11 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 12/16] MdeModulePkg: Add NULL checks and Return Status to ImagePropertiesRecordLib Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 14/16] MdeModulePkg: Transition SMM MAT Logic to Use ImagePropertiesRecordLib Taylor Beebe
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Eric Dong, Ray Ni, Rahul Kumar, Gerd Hoffmann, Laszlo Ersek

PiSmmCore fetches the EFI memory map and calls SplitTable() to
split each loaded image section into its own descriptor with
EFI_MEMORY_XP marking data sections and EFI_MEMORY_RO marking
code sections.

The SMM MAT logic is almost identical to the DXE MAT logic but goes
a step further and also updates the memory map descriptors which describe
image code and data sections to be of type EfiRuntimeServicesCode and
EfiRuntimeServicesData respectively. The consolidated MAT logic
(present in the new ImagePropertiesRecordLib) more closely follows
the DXE MAT logic which identifies image code sections by the presence
of the attribute EFI_MEMORY_RO in the descriptor and image data
sections by the presence of the attribute EFI_MEMORY_XP. Because of
the flow choice of the consolidated MAT logic, the SMM MAT logic should
just use the attributes from the table returned by SplitTable().

Additionally, the function EnforceMemoryMapAttribute() in the SMM MAT
logic will ensure that the CODE and DATA memory types have the desired
attributes so bisecting this patch series at this commit will still
function as before.

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
index 3d445df213ab..15f998e501a2 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
@@ -1047,14 +1047,17 @@ SetMemMapAttributes (
   MemoryMap = MemoryMapStart;
   for (Index = 0; Index < MemoryMapEntryCount; Index++) {
     DEBUG ((DEBUG_VERBOSE, "SetAttribute: Memory Entry - 0x%lx, 0x%x\n", MemoryMap->PhysicalStart, MemoryMap->NumberOfPages));
-    if (MemoryMap->Type == EfiRuntimeServicesCode) {
-      MemoryAttribute = EFI_MEMORY_RO;
-    } else {
-      ASSERT ((MemoryMap->Type == EfiRuntimeServicesData) || (MemoryMap->Type == EfiConventionalMemory));
-      //
-      // Set other type memory as NX.
-      //
-      MemoryAttribute = EFI_MEMORY_XP;
+    MemoryAttribute = MemoryMap->Attribute & EFI_MEMORY_ACCESS_MASK;
+    if (MemoryAttribute == 0) {
+      if (MemoryMap->Type == EfiRuntimeServicesCode) {
+        MemoryAttribute = EFI_MEMORY_RO;
+      } else {
+        ASSERT ((MemoryMap->Type == EfiRuntimeServicesData) || (MemoryMap->Type == EfiConventionalMemory));
+        //
+        // Set other type memory as NX.
+        //
+        MemoryAttribute = EFI_MEMORY_XP;
+      }
     }
 
     //
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111750): https://edk2.groups.io/g/devel/message/111750
Mute This Topic: https://groups.io/mt/102834921/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 14/16] MdeModulePkg: Transition SMM MAT Logic to Use ImagePropertiesRecordLib
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (12 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 13/16] UefiCpuPkg: Use Attribute From SMM MemoryAttributesTable if Nonzero Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 15/16] MdeModulePkg: Add Logic to Create/Delete Image Properties Records Taylor Beebe
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Liming Gao, Dandan Bi, Jiaxin Wu, Ray Ni

Now that the bugs are fixed in the MAT logic, we can remove the
duplicate logic from PiSmmCore/MemoryAttributesTable.c and use
ImagePropertiesRecordLib instead.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c                      | 785 +-------------------
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c |  29 +
 MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf                                |   1 +
 MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h                  |  11 +
 4 files changed, 58 insertions(+), 768 deletions(-)

diff --git a/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c b/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
index 394fdae50741..2e4aaddef4e5 100644
--- a/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
@@ -14,6 +14,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/SmmServicesTableLib.h>
 #include <Library/DebugLib.h>
 #include <Library/PcdLib.h>
+#include <Library/ImagePropertiesRecordLib.h>
 
 #include <Library/PeCoffLib.h>
 #include <Library/PeCoffGetEntryPointLib.h>
@@ -25,26 +26,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
   ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
 
-#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE  SIGNATURE_32 ('I','P','R','C')
-
-typedef struct {
-  UINT32                  Signature;
-  LIST_ENTRY              Link;
-  EFI_PHYSICAL_ADDRESS    CodeSegmentBase;
-  UINT64                  CodeSegmentSize;
-} IMAGE_PROPERTIES_RECORD_CODE_SECTION;
-
-#define IMAGE_PROPERTIES_RECORD_SIGNATURE  SIGNATURE_32 ('I','P','R','D')
-
-typedef struct {
-  UINT32                  Signature;
-  LIST_ENTRY              Link;
-  EFI_PHYSICAL_ADDRESS    ImageBase;
-  UINT64                  ImageSize;
-  UINTN                   CodeSegmentCount;
-  LIST_ENTRY              CodeSegmentList;
-} IMAGE_PROPERTIES_RECORD;
-
 #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('I','P','P','D')
 
 typedef struct {
@@ -69,87 +50,6 @@ UINT64  mMemoryProtectionAttribute = EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTEC
 // Below functions are for MemoryMap
 //
 
-/**
-  Converts a number of EFI_PAGEs to a size in bytes.
-
-  NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
-
-  @param[in]  Pages     The number of EFI_PAGES.
-
-  @return  The number of bytes associated with the number of EFI_PAGEs specified
-           by Pages.
-**/
-STATIC
-UINT64
-EfiPagesToSize (
-  IN UINT64  Pages
-  )
-{
-  return LShiftU64 (Pages, EFI_PAGE_SHIFT);
-}
-
-/**
-  Converts a size, in bytes, to a number of EFI_PAGESs.
-
-  NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
-
-  @param[in]  Size      A size in bytes.
-
-  @return  The number of EFI_PAGESs associated with the number of bytes specified
-           by Size.
-
-**/
-STATIC
-UINT64
-EfiSizeToPages (
-  IN UINT64  Size
-  )
-{
-  return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0);
-}
-
-/**
-  Sort memory map entries based upon PhysicalStart, from low to high.
-
-  @param[in,out]  MemoryMap         A pointer to the buffer in which firmware places
-                                    the current memory map.
-  @param[in]      MemoryMapSize     Size, in bytes, of the MemoryMap buffer.
-  @param[in]      DescriptorSize    Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-**/
-STATIC
-VOID
-SortMemoryMap (
-  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
-  IN UINTN                      MemoryMapSize,
-  IN UINTN                      DescriptorSize
-  )
-{
-  EFI_MEMORY_DESCRIPTOR  *MemoryMapEntry;
-  EFI_MEMORY_DESCRIPTOR  *NextMemoryMapEntry;
-  EFI_MEMORY_DESCRIPTOR  *MemoryMapEnd;
-  EFI_MEMORY_DESCRIPTOR  TempMemoryMap;
-
-  MemoryMapEntry     = MemoryMap;
-  NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
-  MemoryMapEnd       = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
-  while (MemoryMapEntry < MemoryMapEnd) {
-    while (NextMemoryMapEntry < MemoryMapEnd) {
-      if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {
-        CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
-        CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
-        CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof (EFI_MEMORY_DESCRIPTOR));
-      }
-
-      NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
-    }
-
-    MemoryMapEntry     = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
-    NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
-  }
-
-  return;
-}
-
 /**
   Merge continuous memory map entries whose have same attributes.
 
@@ -183,7 +83,7 @@ MergeMemoryMap (
     NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
 
     do {
-      MemoryBlockLength = (UINT64)(EfiPagesToSize (MemoryMapEntry->NumberOfPages));
+      MemoryBlockLength = LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT);
       if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
           (MemoryMapEntry->Type == NextMemoryMapEntry->Type) &&
           (MemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&
@@ -254,423 +154,6 @@ EnforceMemoryMapAttribute (
   return;
 }
 
-/**
-  Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
-
-  @param[in] Buffer  Start Address
-  @param[in] Length  Address length
-
-  @return first image record covered by [buffer, length]
-**/
-STATIC
-IMAGE_PROPERTIES_RECORD *
-GetImageRecordByAddress (
-  IN EFI_PHYSICAL_ADDRESS  Buffer,
-  IN UINT64                Length
-  )
-{
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  LIST_ENTRY               *ImageRecordLink;
-  LIST_ENTRY               *ImageRecordList;
-
-  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
-
-  for (ImageRecordLink = ImageRecordList->ForwardLink;
-       ImageRecordLink != ImageRecordList;
-       ImageRecordLink = ImageRecordLink->ForwardLink)
-  {
-    ImageRecord = CR (
-                    ImageRecordLink,
-                    IMAGE_PROPERTIES_RECORD,
-                    Link,
-                    IMAGE_PROPERTIES_RECORD_SIGNATURE
-                    );
-
-    if ((Buffer <= ImageRecord->ImageBase) &&
-        (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize))
-    {
-      return ImageRecord;
-    }
-  }
-
-  return NULL;
-}
-
-/**
-  Set the memory map to new entries, according to one old entry,
-  based upon PE code section and data section in image record
-
-  @param[in]       ImageRecord            An image record whose [ImageBase, ImageSize] covered
-                                          by old memory map entry.
-  @param[in, out]  NewRecord              A pointer to several new memory map entries.
-                                          The caller guarantee the buffer size be 1 +
-                                          (SplitRecordCount * DescriptorSize) calculated
-                                          below.
-  @param[in]       OldRecord              A pointer to one old memory map entry.
-  @param[in]       DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-**/
-STATIC
-UINTN
-SetNewRecord (
-  IN IMAGE_PROPERTIES_RECORD    *ImageRecord,
-  IN OUT EFI_MEMORY_DESCRIPTOR  *NewRecord,
-  IN EFI_MEMORY_DESCRIPTOR      *OldRecord,
-  IN UINTN                      DescriptorSize
-  )
-{
-  EFI_MEMORY_DESCRIPTOR                 TempRecord;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-  LIST_ENTRY                            *ImageRecordCodeSectionLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionList;
-  UINTN                                 NewRecordCount;
-  UINT64                                PhysicalEnd;
-  UINT64                                ImageEnd;
-
-  CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));
-  PhysicalEnd    = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);
-  NewRecordCount = 0;
-
-  //
-  // Always create a new entry for non-PE image record
-  //
-  if (ImageRecord->ImageBase > TempRecord.PhysicalStart) {
-    NewRecord->Type          = TempRecord.Type;
-    NewRecord->PhysicalStart = TempRecord.PhysicalStart;
-    NewRecord->VirtualStart  = 0;
-    NewRecord->NumberOfPages = EfiSizeToPages (ImageRecord->ImageBase - TempRecord.PhysicalStart);
-    NewRecord->Attribute     = TempRecord.Attribute;
-    NewRecord                = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-    NewRecordCount++;
-    TempRecord.PhysicalStart = ImageRecord->ImageBase;
-    TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - TempRecord.PhysicalStart);
-  }
-
-  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
-
-  ImageRecordCodeSectionLink    = ImageRecordCodeSectionList->ForwardLink;
-  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
-  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-    ImageRecordCodeSection = CR (
-                               ImageRecordCodeSectionLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-
-    if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {
-      //
-      // DATA
-      //
-      NewRecord->Type          = EfiRuntimeServicesData;
-      NewRecord->PhysicalStart = TempRecord.PhysicalStart;
-      NewRecord->VirtualStart  = 0;
-      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart);
-      NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
-      if (NewRecord->NumberOfPages != 0) {
-        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-        NewRecordCount++;
-      }
-
-      //
-      // CODE
-      //
-      NewRecord->Type          = EfiRuntimeServicesCode;
-      NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase;
-      NewRecord->VirtualStart  = 0;
-      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize);
-      NewRecord->Attribute     = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO;
-      if (NewRecord->NumberOfPages != 0) {
-        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-        NewRecordCount++;
-      }
-
-      TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize));
-      TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - TempRecord.PhysicalStart);
-      if (TempRecord.NumberOfPages == 0) {
-        break;
-      }
-    }
-  }
-
-  ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
-
-  //
-  // Final DATA
-  //
-  if (TempRecord.PhysicalStart < ImageEnd) {
-    NewRecord->Type          = EfiRuntimeServicesData;
-    NewRecord->PhysicalStart = TempRecord.PhysicalStart;
-    NewRecord->VirtualStart  = 0;
-    NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart);
-    NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
-    NewRecordCount++;
-  }
-
-  return NewRecordCount;
-}
-
-/**
-  Return the max number of new splitted entries, according to one old entry,
-  based upon PE code section and data section.
-
-  @param[in]  OldRecord              A pointer to one old memory map entry.
-
-  @retval  0 no entry need to be splitted.
-  @return  the max number of new splitted entries
-**/
-STATIC
-UINTN
-GetMaxSplitRecordCount (
-  IN EFI_MEMORY_DESCRIPTOR  *OldRecord
-  )
-{
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  UINTN                    SplitRecordCount;
-  UINT64                   PhysicalStart;
-  UINT64                   PhysicalEnd;
-
-  SplitRecordCount = 0;
-  PhysicalStart    = OldRecord->PhysicalStart;
-  PhysicalEnd      = OldRecord->PhysicalStart + EfiPagesToSize (OldRecord->NumberOfPages);
-
-  do {
-    ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
-    if (ImageRecord == NULL) {
-      break;
-    }
-
-    SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 2);
-    PhysicalStart     = ImageRecord->ImageBase + ImageRecord->ImageSize;
-  } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
-
-  return SplitRecordCount;
-}
-
-/**
-  Split the memory map to new entries, according to one old entry,
-  based upon PE code section and data section.
-
-  @param[in]       OldRecord              A pointer to one old memory map entry.
-  @param[in, out]  NewRecord              A pointer to several new memory map entries.
-                                          The caller guarantee the buffer size be 1 +
-                                          (SplitRecordCount * DescriptorSize) calculated
-                                          below.
-  @param[in]       MaxSplitRecordCount    The max number of splitted entries
-  @param[in]       DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-
-  @retval  0 no entry is splitted.
-  @return  the real number of splitted record.
-**/
-STATIC
-UINTN
-SplitRecord (
-  IN EFI_MEMORY_DESCRIPTOR      *OldRecord,
-  IN OUT EFI_MEMORY_DESCRIPTOR  *NewRecord,
-  IN UINTN                      MaxSplitRecordCount,
-  IN UINTN                      DescriptorSize
-  )
-{
-  EFI_MEMORY_DESCRIPTOR    TempRecord;
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  IMAGE_PROPERTIES_RECORD  *NewImageRecord;
-  UINT64                   PhysicalStart;
-  UINT64                   PhysicalEnd;
-  UINTN                    NewRecordCount;
-  UINTN                    TotalNewRecordCount;
-
-  if (MaxSplitRecordCount == 0) {
-    CopyMem (NewRecord, OldRecord, DescriptorSize);
-    return 0;
-  }
-
-  TotalNewRecordCount = 0;
-
-  //
-  // Override previous record
-  //
-  CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));
-  PhysicalStart = TempRecord.PhysicalStart;
-  PhysicalEnd   = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);
-
-  ImageRecord = NULL;
-  do {
-    NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
-    if (NewImageRecord == NULL) {
-      //
-      // No more image covered by this range, stop
-      //
-      if (PhysicalEnd > PhysicalStart) {
-        //
-        // Always create a new entry for non-PE image record
-        //
-        NewRecord->Type          = TempRecord.Type;
-        NewRecord->PhysicalStart = TempRecord.PhysicalStart;
-        NewRecord->VirtualStart  = 0;
-        NewRecord->NumberOfPages = TempRecord.NumberOfPages;
-        NewRecord->Attribute     = TempRecord.Attribute;
-        TotalNewRecordCount++;
-      }
-
-      break;
-    }
-
-    ImageRecord = NewImageRecord;
-
-    //
-    // Set new record
-    //
-    NewRecordCount       = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);
-    TotalNewRecordCount += NewRecordCount;
-    NewRecord            = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);
-
-    //
-    // Update PhysicalStart, in order to exclude the image buffer already splitted.
-    //
-    PhysicalStart            = ImageRecord->ImageBase + ImageRecord->ImageSize;
-    TempRecord.PhysicalStart = PhysicalStart;
-    TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
-  } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
-
-  return TotalNewRecordCount - 1;
-}
-
-/**
-  Split the original memory map, and add more entries to describe PE code section and data section.
-  This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
-  This function will merge entries with same attributes finally.
-
-  NOTE: It assumes PE code/data section are page aligned.
-  NOTE: It assumes enough entry is prepared for new memory map.
-
-  Split table:
-   +---------------+
-   | Record X      |
-   +---------------+
-   | Record RtCode |
-   +---------------+
-   | Record Y      |
-   +---------------+
-   ==>
-   +---------------+
-   | Record X      |
-   +---------------+
-   | Record RtCode |
-   +---------------+ ----
-   | Record RtData |     |
-   +---------------+     |
-   | Record RtCode |     |-> PE/COFF1
-   +---------------+     |
-   | Record RtData |     |
-   +---------------+ ----
-   | Record RtCode |
-   +---------------+ ----
-   | Record RtData |     |
-   +---------------+     |
-   | Record RtCode |     |-> PE/COFF2
-   +---------------+     |
-   | Record RtData |     |
-   +---------------+ ----
-   | Record RtCode |
-   +---------------+
-   | Record Y      |
-   +---------------+
-
-  @param[in, out]  MemoryMapSize          A pointer to the size, in bytes, of the
-                                          MemoryMap buffer. On input, this is the size of
-                                          old MemoryMap before split. The actual buffer
-                                          size of MemoryMap is MemoryMapSize +
-                                          (AdditionalRecordCount * DescriptorSize) calculated
-                                          below. On output, it is the size of new MemoryMap
-                                          after split.
-  @param[in, out]  MemoryMap              A pointer to the buffer in which firmware places
-                                          the current memory map.
-  @param[in]       DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-**/
-STATIC
-VOID
-SplitTable (
-  IN OUT UINTN                  *MemoryMapSize,
-  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
-  IN UINTN                      DescriptorSize
-  )
-{
-  INTN   IndexOld;
-  INTN   IndexNew;
-  UINTN  MaxSplitRecordCount;
-  UINTN  RealSplitRecordCount;
-  UINTN  TotalSplitRecordCount;
-  UINTN  AdditionalRecordCount;
-
-  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 2) * mImagePropertiesPrivateData.ImageRecordCount;
-
-  TotalSplitRecordCount = 0;
-  //
-  // Let old record point to end of valid MemoryMap buffer.
-  //
-  IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1;
-  //
-  // Let new record point to end of full MemoryMap buffer.
-  //
-  IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + AdditionalRecordCount;
-  for ( ; IndexOld >= 0; IndexOld--) {
-    MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize));
-    //
-    // Split this MemoryMap record
-    //
-    IndexNew            -= MaxSplitRecordCount;
-    RealSplitRecordCount = SplitRecord (
-                             (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),
-                             (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
-                             MaxSplitRecordCount,
-                             DescriptorSize
-                             );
-    //
-    // Adjust IndexNew according to real split.
-    //
-    if (MaxSplitRecordCount != RealSplitRecordCount) {
-      CopyMem (
-        ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),
-        ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
-        (RealSplitRecordCount + 1) * DescriptorSize
-        );
-    }
-
-    IndexNew               = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;
-    TotalSplitRecordCount += RealSplitRecordCount;
-    IndexNew--;
-  }
-
-  //
-  // Move all records to the beginning.
-  //
-  CopyMem (
-    MemoryMap,
-    (UINT8 *)MemoryMap + (AdditionalRecordCount - TotalSplitRecordCount) * DescriptorSize,
-    (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize
-    );
-
-  *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount;
-
-  //
-  // Sort from low to high (Just in case)
-  //
-  SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
-
-  //
-  // Set RuntimeData to XP
-  //
-  EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, DescriptorSize);
-
-  //
-  // Merge same type to save entry size
-  //
-  MergeMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize);
-
-  return;
-}
-
 /**
   This function for GetMemoryMap() with memory attributes table.
 
@@ -729,7 +212,7 @@ SmmCoreGetMemoryMapMemoryAttributesTable (
     return EFI_INVALID_PARAMETER;
   }
 
-  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 2) * mImagePropertiesPrivateData.ImageRecordCount;
+  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 3) * mImagePropertiesPrivateData.ImageRecordCount;
 
   OldMemoryMapSize = *MemoryMapSize;
   Status           = SmmCoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
@@ -747,7 +230,17 @@ SmmCoreGetMemoryMapMemoryAttributesTable (
       // Split PE code/data
       //
       ASSERT (MemoryMap != NULL);
-      SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize);
+      SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize, &mImagePropertiesPrivateData.ImageRecordList, AdditionalRecordCount);
+
+      //
+      // Set RuntimeData to XP
+      //
+      EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, *DescriptorSize);
+
+      //
+      // Merge same type to save entry size
+      //
+      MergeMemoryMap (MemoryMap, MemoryMapSize, *DescriptorSize);
     }
   }
 
@@ -777,250 +270,6 @@ SetMemoryAttributesTableSectionAlignment (
   }
 }
 
-/**
-  Swap two code sections in image record.
-
-  @param[in]  FirstImageRecordCodeSection    first code section in image record
-  @param[in]  SecondImageRecordCodeSection   second code section in image record
-**/
-STATIC
-VOID
-SwapImageRecordCodeSection (
-  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *FirstImageRecordCodeSection,
-  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *SecondImageRecordCodeSection
-  )
-{
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  TempImageRecordCodeSection;
-
-  TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;
-  TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;
-
-  FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase;
-  FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize;
-
-  SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;
-  SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;
-}
-
-/**
-  Sort code section in image record, based upon CodeSegmentBase from low to high.
-
-  @param[in]  ImageRecord    image record to be sorted
-**/
-STATIC
-VOID
-SortImageRecordCodeSection (
-  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
-  )
-{
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *NextImageRecordCodeSection;
-  LIST_ENTRY                            *ImageRecordCodeSectionLink;
-  LIST_ENTRY                            *NextImageRecordCodeSectionLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionList;
-
-  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
-
-  ImageRecordCodeSectionLink     = ImageRecordCodeSectionList->ForwardLink;
-  NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-  ImageRecordCodeSectionEndLink  = ImageRecordCodeSectionList;
-  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-    ImageRecordCodeSection = CR (
-                               ImageRecordCodeSectionLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-      NextImageRecordCodeSection = CR (
-                                     NextImageRecordCodeSectionLink,
-                                     IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                                     Link,
-                                     IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                                     );
-      if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {
-        SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);
-      }
-
-      NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;
-    }
-
-    ImageRecordCodeSectionLink     = ImageRecordCodeSectionLink->ForwardLink;
-    NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-  }
-}
-
-/**
-  Check if code section in image record is valid.
-
-  @param[in]  ImageRecord    image record to be checked
-
-  @retval TRUE  image record is valid
-  @retval FALSE image record is invalid
-**/
-STATIC
-BOOLEAN
-IsImageRecordCodeSectionValid (
-  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
-  )
-{
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *LastImageRecordCodeSection;
-  LIST_ENTRY                            *ImageRecordCodeSectionLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
-  LIST_ENTRY                            *ImageRecordCodeSectionList;
-
-  DEBUG ((DEBUG_VERBOSE, "SMM ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));
-
-  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
-
-  ImageRecordCodeSectionLink    = ImageRecordCodeSectionList->ForwardLink;
-  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
-  LastImageRecordCodeSection    = NULL;
-  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
-    ImageRecordCodeSection = CR (
-                               ImageRecordCodeSectionLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    if (ImageRecordCodeSection->CodeSegmentSize == 0) {
-      return FALSE;
-    }
-
-    if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {
-      return FALSE;
-    }
-
-    if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {
-      return FALSE;
-    }
-
-    if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
-      return FALSE;
-    }
-
-    if (LastImageRecordCodeSection != NULL) {
-      if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) {
-        return FALSE;
-      }
-    }
-
-    LastImageRecordCodeSection = ImageRecordCodeSection;
-    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-  }
-
-  return TRUE;
-}
-
-/**
-  Swap two image records.
-
-  @param[in]  FirstImageRecord   first image record.
-  @param[in]  SecondImageRecord  second image record.
-**/
-STATIC
-VOID
-SwapImageRecord (
-  IN IMAGE_PROPERTIES_RECORD  *FirstImageRecord,
-  IN IMAGE_PROPERTIES_RECORD  *SecondImageRecord
-  )
-{
-  IMAGE_PROPERTIES_RECORD  TempImageRecord;
-
-  TempImageRecord.ImageBase        = FirstImageRecord->ImageBase;
-  TempImageRecord.ImageSize        = FirstImageRecord->ImageSize;
-  TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;
-
-  FirstImageRecord->ImageBase        = SecondImageRecord->ImageBase;
-  FirstImageRecord->ImageSize        = SecondImageRecord->ImageSize;
-  FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;
-
-  SecondImageRecord->ImageBase        = TempImageRecord.ImageBase;
-  SecondImageRecord->ImageSize        = TempImageRecord.ImageSize;
-  SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;
-
-  SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);
-}
-
-/**
-  Sort image record based upon the ImageBase from low to high.
-**/
-STATIC
-VOID
-SortImageRecord (
-  VOID
-  )
-{
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  IMAGE_PROPERTIES_RECORD  *NextImageRecord;
-  LIST_ENTRY               *ImageRecordLink;
-  LIST_ENTRY               *NextImageRecordLink;
-  LIST_ENTRY               *ImageRecordEndLink;
-  LIST_ENTRY               *ImageRecordList;
-
-  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
-
-  ImageRecordLink     = ImageRecordList->ForwardLink;
-  NextImageRecordLink = ImageRecordLink->ForwardLink;
-  ImageRecordEndLink  = ImageRecordList;
-  while (ImageRecordLink != ImageRecordEndLink) {
-    ImageRecord = CR (
-                    ImageRecordLink,
-                    IMAGE_PROPERTIES_RECORD,
-                    Link,
-                    IMAGE_PROPERTIES_RECORD_SIGNATURE
-                    );
-    while (NextImageRecordLink != ImageRecordEndLink) {
-      NextImageRecord = CR (
-                          NextImageRecordLink,
-                          IMAGE_PROPERTIES_RECORD,
-                          Link,
-                          IMAGE_PROPERTIES_RECORD_SIGNATURE
-                          );
-      if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {
-        SwapImageRecord (ImageRecord, NextImageRecord);
-      }
-
-      NextImageRecordLink = NextImageRecordLink->ForwardLink;
-    }
-
-    ImageRecordLink     = ImageRecordLink->ForwardLink;
-    NextImageRecordLink = ImageRecordLink->ForwardLink;
-  }
-}
-
-/**
-  Dump image record.
-**/
-STATIC
-VOID
-DumpImageRecord (
-  VOID
-  )
-{
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  LIST_ENTRY               *ImageRecordLink;
-  LIST_ENTRY               *ImageRecordList;
-  UINTN                    Index;
-
-  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
-
-  for (ImageRecordLink = ImageRecordList->ForwardLink, Index = 0;
-       ImageRecordLink != ImageRecordList;
-       ImageRecordLink = ImageRecordLink->ForwardLink, Index++)
-  {
-    ImageRecord = CR (
-                    ImageRecordLink,
-                    IMAGE_PROPERTIES_RECORD,
-                    Link,
-                    IMAGE_PROPERTIES_RECORD_SIGNATURE
-                    );
-    DEBUG ((DEBUG_VERBOSE, "SMM  Image[%d]: 0x%016lx - 0x%016lx\n", Index, ImageRecord->ImageBase, ImageRecord->ImageSize));
-  }
-}
-
 /**
   Insert image record.
 
@@ -1059,7 +308,7 @@ SmmInsertImageRecord (
   // Step 1: record whole region
   //
   ImageRecord->ImageBase = DriverEntry->ImageBuffer;
-  ImageRecord->ImageSize = EfiPagesToSize (DriverEntry->NumberOfPage);
+  ImageRecord->ImageSize = LShiftU64 (DriverEntry->NumberOfPage, EFI_PAGE_SHIFT);
 
   ImageAddress = (VOID *)(UINTN)DriverEntry->ImageBuffer;
 
@@ -1193,7 +442,7 @@ SmmInsertImageRecord (
     mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;
   }
 
-  SortImageRecord ();
+  SortImageRecord (&mImagePropertiesPrivateData.ImageRecordList);
 
 Finish:
   return;
@@ -1361,7 +610,7 @@ SmmInstallMemoryAttributesTable (
 
   DEBUG ((DEBUG_VERBOSE, "SMM Total Image Count - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
   DEBUG ((DEBUG_VERBOSE, "SMM Dump ImageRecord:\n"));
-  DumpImageRecord ();
+  DumpImageRecord (&mImagePropertiesPrivateData.ImageRecordList);
 
   PublishMemoryAttributesTable ();
 
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
index c9378679e7bb..9b296aa45762 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
@@ -783,6 +783,35 @@ SortImageRecord (
   return EFI_SUCCESS;
 }
 
+/**
+  Dump image record.
+
+  @param[in]  ImageRecordList  A list of IMAGE_PROPERTIES_RECORD entries
+**/
+VOID
+EFIAPI
+DumpImageRecord (
+  IN LIST_ENTRY  *ImageRecordList
+  )
+{
+  IMAGE_PROPERTIES_RECORD  *ImageRecord;
+  LIST_ENTRY               *ImageRecordLink;
+  UINTN                    Index;
+
+  for (ImageRecordLink = ImageRecordList->ForwardLink, Index = 0;
+       ImageRecordLink != ImageRecordList;
+       ImageRecordLink = ImageRecordLink->ForwardLink, Index++)
+  {
+    ImageRecord = CR (
+                    ImageRecordLink,
+                    IMAGE_PROPERTIES_RECORD,
+                    Link,
+                    IMAGE_PROPERTIES_RECORD_SIGNATURE
+                    );
+    DEBUG ((DEBUG_VERBOSE, "Image[%d]: 0x%016lx - 0x%016lx\n", Index, ImageRecord->ImageBase, ImageRecord->ImageSize));
+  }
+}
+
 /**
   Find image record according to image base and size.
 
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
index 3df44b38f13c..75a5934f0c1d 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
@@ -61,6 +61,7 @@ [LibraryClasses]
   HobLib
   SmmMemLib
   SafeIntLib
+  ImagePropertiesRecordLib
 
 [Protocols]
   gEfiDxeSmmReadyToLockProtocolGuid             ## UNDEFINED # SmiHandlerRegister
diff --git a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
index b6365662646a..e3f569ab03d1 100644
--- a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
+++ b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
@@ -181,4 +181,15 @@ FindImageRecord (
   IN LIST_ENTRY            *ImageRecordList
   );
 
+/**
+  Dump image record.
+
+  @param[in]  ImageRecordList  A list of IMAGE_PROPERTIES_RECORD entries
+**/
+VOID
+EFIAPI
+DumpImageRecord (
+  IN LIST_ENTRY  *ImageRecordList
+  );
+
 #endif
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111751): https://edk2.groups.io/g/devel/message/111751
Mute This Topic: https://groups.io/mt/102834923/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 15/16] MdeModulePkg: Add Logic to Create/Delete Image Properties Records
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (13 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 14/16] MdeModulePkg: Transition SMM MAT Logic to Use ImagePropertiesRecordLib Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 16/16] MdeModulePkg: Update DumpImageRecord() in ImagePropertiesRecordLib Taylor Beebe
  2023-11-27 18:40 ` [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Ard Biesheuvel
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Liming Gao, Dandan Bi, Jiaxin Wu, Ray Ni

Add logic to create and delete image properties records. Where
applicable, redirect existing code to use the new library.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c                         | 184 +++----------------
 MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c                        | 166 +++--------------
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c   | 186 ++++++++++++++++++++
 MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h                    |  39 ++++
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf |   1 +
 5 files changed, 281 insertions(+), 295 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
index af6c26244cc0..993db281062a 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
@@ -557,25 +557,6 @@ CoreGetMemoryMapWithSeparatedImageSection (
 // Below functions are for ImageRecord
 //
 
-/**
-  Set MemoryAttributesTable according to PE/COFF image section alignment.
-
-  @param  SectionAlignment    PE/COFF section alignment
-**/
-STATIC
-VOID
-SetMemoryAttributesTableSectionAlignment (
-  IN UINT32  SectionAlignment
-  )
-{
-  if (((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) &&
-      mMemoryAttributesTableEnable)
-  {
-    DEBUG ((DEBUG_VERBOSE, "SetMemoryAttributesTableSectionAlignment - Clear\n"));
-    mMemoryAttributesTableEnable = FALSE;
-  }
-}
-
 /**
   Insert image record.
 
@@ -586,20 +567,12 @@ InsertImageRecord (
   IN EFI_RUNTIME_IMAGE_ENTRY  *RuntimeImage
   )
 {
-  VOID                                  *ImageAddress;
-  EFI_IMAGE_DOS_HEADER                  *DosHdr;
-  UINT32                                PeCoffHeaderOffset;
-  UINT32                                SectionAlignment;
-  EFI_IMAGE_SECTION_HEADER              *Section;
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
-  UINT8                                 *Name;
-  UINTN                                 Index;
-  IMAGE_PROPERTIES_RECORD               *ImageRecord;
-  CHAR8                                 *PdbPointer;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
+  EFI_STATUS               Status;
+  IMAGE_PROPERTIES_RECORD  *ImageRecord;
+  CHAR8                    *PdbPointer;
+  UINT32                   RequiredAlignment;
 
   DEBUG ((DEBUG_VERBOSE, "InsertImageRecord - 0x%x\n", RuntimeImage));
-  DEBUG ((DEBUG_VERBOSE, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));
 
   if (mMemoryAttributesTableEndOfDxe) {
     DEBUG ((DEBUG_INFO, "Do not insert runtime image record after EndOfDxe\n"));
@@ -611,139 +584,48 @@ InsertImageRecord (
     return;
   }
 
-  ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;
+  InitializeListHead (&ImageRecord->Link);
+  InitializeListHead (&ImageRecord->CodeSegmentList);
 
-  DEBUG ((DEBUG_VERBOSE, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
-
-  //
-  // Step 1: record whole region
-  //
-  ImageRecord->ImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase;
-  ImageRecord->ImageSize = RuntimeImage->ImageSize;
-
-  ImageAddress = RuntimeImage->ImageBase;
-
-  PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
+  PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)RuntimeImage->ImageBase);
   if (PdbPointer != NULL) {
     DEBUG ((DEBUG_VERBOSE, "  Image - %a\n", PdbPointer));
   }
 
-  //
-  // Check PE/COFF image
-  //
-  DosHdr             = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;
-  PeCoffHeaderOffset = 0;
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    PeCoffHeaderOffset = DosHdr->e_lfanew;
-  }
-
-  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);
-  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
-    DEBUG ((DEBUG_VERBOSE, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature));
-    // It might be image in SMM.
-    goto Finish;
-  }
-
-  //
-  // Get SectionAlignment
-  //
-  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
-  } else {
-    SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
-  }
-
-  SetMemoryAttributesTableSectionAlignment (SectionAlignment);
-  if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
-    DEBUG ((
-      DEBUG_WARN,
-      "!!!!!!!!  InsertImageRecord - Section Alignment(0x%x) is not %dK  !!!!!!!!\n",
-      SectionAlignment,
-      RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10
-      ));
-    PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
-    if (PdbPointer != NULL) {
-      DEBUG ((DEBUG_WARN, "!!!!!!!!  Image - %a  !!!!!!!!\n", PdbPointer));
+  RequiredAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+  Status            = CreateImagePropertiesRecord (
+                        RuntimeImage->ImageBase,
+                        RuntimeImage->ImageSize,
+                        &RequiredAlignment,
+                        ImageRecord
+                        );
+
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_ABORTED) {
+      mMemoryAttributesTableEnable = FALSE;
     }
 
+    Status = EFI_ABORTED;
     goto Finish;
   }
 
-  Section = (EFI_IMAGE_SECTION_HEADER *)(
-                                         (UINT8 *)(UINTN)ImageAddress +
-                                         PeCoffHeaderOffset +
-                                         sizeof (UINT32) +
-                                         sizeof (EFI_IMAGE_FILE_HEADER) +
-                                         Hdr.Pe32->FileHeader.SizeOfOptionalHeader
-                                         );
-  ImageRecord->CodeSegmentCount = 0;
-  InitializeListHead (&ImageRecord->CodeSegmentList);
-  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
-    Name = Section[Index].Name;
-    DEBUG ((
-      DEBUG_VERBOSE,
-      "  Section - '%c%c%c%c%c%c%c%c'\n",
-      Name[0],
-      Name[1],
-      Name[2],
-      Name[3],
-      Name[4],
-      Name[5],
-      Name[6],
-      Name[7]
-      ));
-
-    if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {
-      DEBUG ((DEBUG_VERBOSE, "  VirtualSize          - 0x%08x\n", Section[Index].Misc.VirtualSize));
-      DEBUG ((DEBUG_VERBOSE, "  VirtualAddress       - 0x%08x\n", Section[Index].VirtualAddress));
-      DEBUG ((DEBUG_VERBOSE, "  SizeOfRawData        - 0x%08x\n", Section[Index].SizeOfRawData));
-      DEBUG ((DEBUG_VERBOSE, "  PointerToRawData     - 0x%08x\n", Section[Index].PointerToRawData));
-      DEBUG ((DEBUG_VERBOSE, "  PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));
-      DEBUG ((DEBUG_VERBOSE, "  PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));
-      DEBUG ((DEBUG_VERBOSE, "  NumberOfRelocations  - 0x%08x\n", Section[Index].NumberOfRelocations));
-      DEBUG ((DEBUG_VERBOSE, "  NumberOfLinenumbers  - 0x%08x\n", Section[Index].NumberOfLinenumbers));
-      DEBUG ((DEBUG_VERBOSE, "  Characteristics      - 0x%08x\n", Section[Index].Characteristics));
-
-      //
-      // Step 2: record code section
-      //
-      ImageRecordCodeSection = AllocatePool (sizeof (*ImageRecordCodeSection));
-      if (ImageRecordCodeSection == NULL) {
-        return;
-      }
-
-      ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
-
-      ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress;
-      ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData;
-
-      DEBUG ((DEBUG_VERBOSE, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize));
-
-      InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);
-      ImageRecord->CodeSegmentCount++;
-    }
-  }
-
   if (ImageRecord->CodeSegmentCount == 0) {
-    SetMemoryAttributesTableSectionAlignment (1);
+    mMemoryAttributesTableEnable = FALSE;
     DEBUG ((DEBUG_ERROR, "!!!!!!!!  InsertImageRecord - CodeSegmentCount is 0  !!!!!!!!\n"));
-    PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
     if (PdbPointer != NULL) {
       DEBUG ((DEBUG_ERROR, "!!!!!!!!  Image - %a  !!!!!!!!\n", PdbPointer));
     }
 
+    Status = EFI_ABORTED;
     goto Finish;
   }
 
-  //
-  // Final
-  //
-  SortImageRecordCodeSection (ImageRecord);
   //
   // Check overlap all section in ImageBase/Size
   //
   if (!IsImageRecordCodeSectionValid (ImageRecord)) {
     DEBUG ((DEBUG_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));
+    Status = EFI_ABORTED;
     goto Finish;
   }
 
@@ -757,6 +639,10 @@ InsertImageRecord (
   SortImageRecord (&mImagePropertiesPrivateData.ImageRecordList);
 
 Finish:
+  if (EFI_ERROR (Status) && (ImageRecord != NULL)) {
+    DeleteImagePropertiesRecord (ImageRecord);
+  }
+
   return;
 }
 
@@ -770,9 +656,7 @@ RemoveImageRecord (
   IN EFI_RUNTIME_IMAGE_ENTRY  *RuntimeImage
   )
 {
-  IMAGE_PROPERTIES_RECORD               *ImageRecord;
-  LIST_ENTRY                            *CodeSegmentListHead;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
+  IMAGE_PROPERTIES_RECORD  *ImageRecord;
 
   DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%x\n", RuntimeImage));
   DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));
@@ -788,19 +672,7 @@ RemoveImageRecord (
     return;
   }
 
-  CodeSegmentListHead = &ImageRecord->CodeSegmentList;
-  while (!IsListEmpty (CodeSegmentListHead)) {
-    ImageRecordCodeSection = CR (
-                               CodeSegmentListHead->ForwardLink,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
-                               Link,
-                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
-                               );
-    RemoveEntryList (&ImageRecordCodeSection->Link);
-    FreePool (ImageRecordCodeSection);
-  }
+  DeleteImagePropertiesRecord (ImageRecord);
 
-  RemoveEntryList (&ImageRecord->Link);
-  FreePool (ImageRecord);
   mImagePropertiesPrivateData.ImageRecordCount--;
 }
diff --git a/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c b/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
index 2e4aaddef4e5..03de9b2c5fff 100644
--- a/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
@@ -251,25 +251,6 @@ SmmCoreGetMemoryMapMemoryAttributesTable (
 // Below functions are for ImageRecord
 //
 
-/**
-  Set MemoryProtectionAttribute according to PE/COFF image section alignment.
-
-  @param[in]  SectionAlignment    PE/COFF section alignment
-**/
-STATIC
-VOID
-SetMemoryAttributesTableSectionAlignment (
-  IN UINT32  SectionAlignment
-  )
-{
-  if (((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) &&
-      ((mMemoryProtectionAttribute & EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) != 0))
-  {
-    DEBUG ((DEBUG_VERBOSE, "SMM SetMemoryAttributesTableSectionAlignment - Clear\n"));
-    mMemoryProtectionAttribute &= ~((UINT64)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA);
-  }
-}
-
 /**
   Insert image record.
 
@@ -280,158 +261,61 @@ SmmInsertImageRecord (
   IN EFI_SMM_DRIVER_ENTRY  *DriverEntry
   )
 {
-  VOID                                  *ImageAddress;
-  EFI_IMAGE_DOS_HEADER                  *DosHdr;
-  UINT32                                PeCoffHeaderOffset;
-  UINT32                                SectionAlignment;
-  EFI_IMAGE_SECTION_HEADER              *Section;
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
-  UINT8                                 *Name;
-  UINTN                                 Index;
-  IMAGE_PROPERTIES_RECORD               *ImageRecord;
-  CHAR8                                 *PdbPointer;
-  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
+  EFI_STATUS               Status;
+  IMAGE_PROPERTIES_RECORD  *ImageRecord;
+  CHAR8                    *PdbPointer;
+  UINT32                   RequiredAlignment;
 
   DEBUG ((DEBUG_VERBOSE, "SMM InsertImageRecord - 0x%x\n", DriverEntry));
-  DEBUG ((DEBUG_VERBOSE, "SMM InsertImageRecord - 0x%016lx - 0x%08x\n", DriverEntry->ImageBuffer, DriverEntry->NumberOfPage));
 
   ImageRecord = AllocatePool (sizeof (*ImageRecord));
   if (ImageRecord == NULL) {
     return;
   }
 
-  ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;
+  InitializeListHead (&ImageRecord->Link);
+  InitializeListHead (&ImageRecord->CodeSegmentList);
 
-  DEBUG ((DEBUG_VERBOSE, "SMM ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
-
-  //
-  // Step 1: record whole region
-  //
-  ImageRecord->ImageBase = DriverEntry->ImageBuffer;
-  ImageRecord->ImageSize = LShiftU64 (DriverEntry->NumberOfPage, EFI_PAGE_SHIFT);
-
-  ImageAddress = (VOID *)(UINTN)DriverEntry->ImageBuffer;
-
-  PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
+  PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)DriverEntry->ImageBuffer);
   if (PdbPointer != NULL) {
     DEBUG ((DEBUG_VERBOSE, "SMM   Image - %a\n", PdbPointer));
   }
 
-  //
-  // Check PE/COFF image
-  //
-  DosHdr             = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;
-  PeCoffHeaderOffset = 0;
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
-    PeCoffHeaderOffset = DosHdr->e_lfanew;
-  }
-
-  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);
-  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
-    DEBUG ((DEBUG_VERBOSE, "SMM Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature));
-    goto Finish;
-  }
-
-  //
-  // Get SectionAlignment
-  //
-  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-    SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
-  } else {
-    SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
-  }
-
-  SetMemoryAttributesTableSectionAlignment (SectionAlignment);
-  if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
-    DEBUG ((
-      DEBUG_WARN,
-      "SMM !!!!!!!!  InsertImageRecord - Section Alignment(0x%x) is not %dK  !!!!!!!!\n",
-      SectionAlignment,
-      RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10
-      ));
-    PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
-    if (PdbPointer != NULL) {
-      DEBUG ((DEBUG_WARN, "SMM !!!!!!!!  Image - %a  !!!!!!!!\n", PdbPointer));
+  RequiredAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+  Status            = CreateImagePropertiesRecord (
+                        (VOID *)(UINTN)DriverEntry->ImageBuffer,
+                        LShiftU64 (DriverEntry->NumberOfPage, EFI_PAGE_SHIFT),
+                        &RequiredAlignment,
+                        ImageRecord
+                        );
+
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_ABORTED) {
+      mMemoryProtectionAttribute &=
+        ~((UINT64)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA);
     }
 
     goto Finish;
   }
 
-  Section = (EFI_IMAGE_SECTION_HEADER *)(
-                                         (UINT8 *)(UINTN)ImageAddress +
-                                         PeCoffHeaderOffset +
-                                         sizeof (UINT32) +
-                                         sizeof (EFI_IMAGE_FILE_HEADER) +
-                                         Hdr.Pe32->FileHeader.SizeOfOptionalHeader
-                                         );
-  ImageRecord->CodeSegmentCount = 0;
-  InitializeListHead (&ImageRecord->CodeSegmentList);
-  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
-    Name = Section[Index].Name;
-    DEBUG ((
-      DEBUG_VERBOSE,
-      "SMM   Section - '%c%c%c%c%c%c%c%c'\n",
-      Name[0],
-      Name[1],
-      Name[2],
-      Name[3],
-      Name[4],
-      Name[5],
-      Name[6],
-      Name[7]
-      ));
-
-    if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {
-      DEBUG ((DEBUG_VERBOSE, "SMM   VirtualSize          - 0x%08x\n", Section[Index].Misc.VirtualSize));
-      DEBUG ((DEBUG_VERBOSE, "SMM   VirtualAddress       - 0x%08x\n", Section[Index].VirtualAddress));
-      DEBUG ((DEBUG_VERBOSE, "SMM   SizeOfRawData        - 0x%08x\n", Section[Index].SizeOfRawData));
-      DEBUG ((DEBUG_VERBOSE, "SMM   PointerToRawData     - 0x%08x\n", Section[Index].PointerToRawData));
-      DEBUG ((DEBUG_VERBOSE, "SMM   PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));
-      DEBUG ((DEBUG_VERBOSE, "SMM   PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));
-      DEBUG ((DEBUG_VERBOSE, "SMM   NumberOfRelocations  - 0x%08x\n", Section[Index].NumberOfRelocations));
-      DEBUG ((DEBUG_VERBOSE, "SMM   NumberOfLinenumbers  - 0x%08x\n", Section[Index].NumberOfLinenumbers));
-      DEBUG ((DEBUG_VERBOSE, "SMM   Characteristics      - 0x%08x\n", Section[Index].Characteristics));
-
-      //
-      // Step 2: record code section
-      //
-      ImageRecordCodeSection = AllocatePool (sizeof (*ImageRecordCodeSection));
-      if (ImageRecordCodeSection == NULL) {
-        return;
-      }
-
-      ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
-
-      ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress;
-      ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData;
-
-      DEBUG ((DEBUG_VERBOSE, "SMM ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize));
-
-      InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);
-      ImageRecord->CodeSegmentCount++;
-    }
-  }
-
   if (ImageRecord->CodeSegmentCount == 0) {
-    SetMemoryAttributesTableSectionAlignment (1);
+    mMemoryProtectionAttribute &=
+      ~((UINT64)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA);
     DEBUG ((DEBUG_ERROR, "SMM !!!!!!!!  InsertImageRecord - CodeSegmentCount is 0  !!!!!!!!\n"));
-    PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
     if (PdbPointer != NULL) {
       DEBUG ((DEBUG_ERROR, "SMM !!!!!!!!  Image - %a  !!!!!!!!\n", PdbPointer));
     }
 
+    Status = EFI_ABORTED;
     goto Finish;
   }
 
-  //
-  // Final
-  //
-  SortImageRecordCodeSection (ImageRecord);
   //
   // Check overlap all section in ImageBase/Size
   //
   if (!IsImageRecordCodeSectionValid (ImageRecord)) {
     DEBUG ((DEBUG_ERROR, "SMM IsImageRecordCodeSectionValid - FAIL\n"));
+    Status = EFI_ABORTED;
     goto Finish;
   }
 
@@ -445,6 +329,10 @@ SmmInsertImageRecord (
   SortImageRecord (&mImagePropertiesPrivateData.ImageRecordList);
 
 Finish:
+  if (EFI_ERROR (Status) && (ImageRecord != NULL)) {
+    DeleteImagePropertiesRecord (ImageRecord);
+  }
+
   return;
 }
 
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
index 9b296aa45762..6c5eb1dc3185 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
@@ -13,6 +13,7 @@
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
 #include <Library/ImagePropertiesRecordLib.h>
 
 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
@@ -858,3 +859,188 @@ FindImageRecord (
 
   return NULL;
 }
+
+/**
+  Creates an IMAGE_PROPERTIES_RECORD from a loaded PE image. The PE/COFF header will be found
+  and parsed to determine the number of code segments and their base addresses and sizes.
+
+  @param[in]      ImageBase               Base of the PE image
+  @param[in]      ImageSize               Size of the PE image
+  @param[in]      RequiredAlignment       If non-NULL, the alignment specified in the PE/COFF header
+                                          will be compared against this value.
+  @param[out]     ImageRecord             On out, a populated image properties record
+
+  @retval     EFI_INVALID_PARAMETER   This function ImageBase or ImageRecord was NULL, or the
+                                      image located at ImageBase was not a valid PE/COFF image
+  @retval     EFI_OUT_OF_RESOURCES    Failure to Allocate()
+  @retval     EFI_ABORTED             The input Alignment was non-NULL and did not match the
+                                      alignment specified in the PE/COFF header
+  @retval     EFI_SUCCESS             The image properties record was successfully created
+**/
+EFI_STATUS
+EFIAPI
+CreateImagePropertiesRecord (
+  IN  CONST   VOID                     *ImageBase,
+  IN  CONST   UINT64                   ImageSize,
+  IN  CONST   UINT32                   *RequiredAlignment OPTIONAL,
+  OUT         IMAGE_PROPERTIES_RECORD  *ImageRecord
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_IMAGE_DOS_HEADER                  *DosHdr;
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
+  EFI_IMAGE_SECTION_HEADER              *Section;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
+  UINTN                                 Index;
+  UINT8                                 *Name;
+  UINT32                                SectionAlignment;
+  UINT32                                PeCoffHeaderOffset;
+
+  if ((ImageRecord == NULL) || (ImageBase == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((
+    DEBUG_VERBOSE,
+    "Creating Image Properties Record: 0x%016lx - 0x%016lx\n",
+    (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBase,
+    ImageSize
+    ));
+
+  //
+  // Step 1: record whole region
+  //
+  Status                        = EFI_SUCCESS;
+  ImageRecord->Signature        = IMAGE_PROPERTIES_RECORD_SIGNATURE;
+  ImageRecord->ImageBase        = (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBase;
+  ImageRecord->ImageSize        = ImageSize;
+  ImageRecord->CodeSegmentCount = 0;
+  InitializeListHead (&ImageRecord->Link);
+  InitializeListHead (&ImageRecord->CodeSegmentList);
+
+  // Check PE/COFF image
+  DosHdr             = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageBase;
+  PeCoffHeaderOffset = 0;
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+    PeCoffHeaderOffset = DosHdr->e_lfanew;
+  }
+
+  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageBase + PeCoffHeaderOffset);
+  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
+    DEBUG ((DEBUG_VERBOSE, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Get SectionAlignment
+  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+    SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
+  } else {
+    SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
+  }
+
+  // Check RequiredAlignment
+  if ((RequiredAlignment != NULL) && ((SectionAlignment & (*RequiredAlignment - 1)) != 0)) {
+    DEBUG ((
+      DEBUG_WARN,
+      "!!!!!!!!  Image Section Alignment(0x%x) does not match Required Alignment (0x%x)  !!!!!!!!\n",
+      SectionAlignment,
+      *RequiredAlignment
+      ));
+
+    return EFI_ABORTED;
+  }
+
+  Section = (EFI_IMAGE_SECTION_HEADER *)(
+                                         (UINT8 *)(UINTN)ImageBase +
+                                         PeCoffHeaderOffset +
+                                         sizeof (UINT32) +
+                                         sizeof (EFI_IMAGE_FILE_HEADER) +
+                                         Hdr.Pe32->FileHeader.SizeOfOptionalHeader
+                                         );
+  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
+    Name = Section[Index].Name;
+    DEBUG ((
+      DEBUG_VERBOSE,
+      "  Section - '%c%c%c%c%c%c%c%c'\n",
+      Name[0],
+      Name[1],
+      Name[2],
+      Name[3],
+      Name[4],
+      Name[5],
+      Name[6],
+      Name[7]
+      ));
+
+    if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {
+      DEBUG ((DEBUG_VERBOSE, "  VirtualSize          - 0x%08x\n", Section[Index].Misc.VirtualSize));
+      DEBUG ((DEBUG_VERBOSE, "  VirtualAddress       - 0x%08x\n", Section[Index].VirtualAddress));
+      DEBUG ((DEBUG_VERBOSE, "  SizeOfRawData        - 0x%08x\n", Section[Index].SizeOfRawData));
+      DEBUG ((DEBUG_VERBOSE, "  PointerToRawData     - 0x%08x\n", Section[Index].PointerToRawData));
+      DEBUG ((DEBUG_VERBOSE, "  PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));
+      DEBUG ((DEBUG_VERBOSE, "  PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));
+      DEBUG ((DEBUG_VERBOSE, "  NumberOfRelocations  - 0x%08x\n", Section[Index].NumberOfRelocations));
+      DEBUG ((DEBUG_VERBOSE, "  NumberOfLinenumbers  - 0x%08x\n", Section[Index].NumberOfLinenumbers));
+      DEBUG ((DEBUG_VERBOSE, "  Characteristics      - 0x%08x\n", Section[Index].Characteristics));
+
+      // Record code section(s)
+      ImageRecordCodeSection = AllocatePool (sizeof (*ImageRecordCodeSection));
+      if (ImageRecordCodeSection == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
+
+      ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageBase + Section[Index].VirtualAddress;
+      ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData;
+
+      InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);
+      ImageRecord->CodeSegmentCount++;
+    }
+  }
+
+  if (ImageRecord->CodeSegmentCount > 0) {
+    SortImageRecordCodeSection (ImageRecord);
+  }
+
+  return Status;
+}
+
+/**
+  Deleted an image properties record. The function will also call
+  RemoveEntryList() on each code segment and the input ImageRecord before
+  freeing each pool.
+
+  @param[in]      ImageRecord             The IMAGE_PROPERTIES_RECORD to delete
+**/
+VOID
+EFIAPI
+DeleteImagePropertiesRecord (
+  IN  IMAGE_PROPERTIES_RECORD  *ImageRecord
+  )
+{
+  LIST_ENTRY                            *CodeSegmentListHead;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
+
+  if (ImageRecord == NULL) {
+    return;
+  }
+
+  CodeSegmentListHead = &ImageRecord->CodeSegmentList;
+  while (!IsListEmpty (CodeSegmentListHead)) {
+    ImageRecordCodeSection = CR (
+                               CodeSegmentListHead->ForwardLink,
+                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
+                               Link,
+                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
+                               );
+    RemoveEntryList (&ImageRecordCodeSection->Link);
+    FreePool (ImageRecordCodeSection);
+  }
+
+  if (!IsListEmpty (&ImageRecord->Link)) {
+    RemoveEntryList (&ImageRecord->Link);
+  }
+
+  FreePool (ImageRecord);
+}
diff --git a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
index e3f569ab03d1..5090a521536b 100644
--- a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
+++ b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
@@ -192,4 +192,43 @@ DumpImageRecord (
   IN LIST_ENTRY  *ImageRecordList
   );
 
+/**
+  Creates an IMAGE_PROPERTIES_RECORD from a loaded PE image. The PE/COFF header will be found
+  and parsed to determine the number of code segments and their base addresses and sizes.
+
+  @param[in]      ImageBase               Base of the PE image
+  @param[in]      ImageSize               Size of the PE image
+  @param[in]      RequiredAlignment       If non-NULL, the alignment specified in the PE/COFF header
+                                          will be compared against this value.
+  @param[out]     ImageRecord             On out, a populated image properties record
+
+  @retval     EFI_INVALID_PARAMETER   This function ImageBase or ImageRecord was NULL, or the
+                                      image located at ImageBase was not a valid PE/COFF image
+  @retval     EFI_OUT_OF_RESOURCES    Failure to Allocate()
+  @retval     EFI_ABORTED             The input Alignment was non-NULL and did not match the
+                                      alignment specified in the PE/COFF header
+  @retval     EFI_SUCCESS             The image properties record was successfully created
+**/
+EFI_STATUS
+EFIAPI
+CreateImagePropertiesRecord (
+  IN  CONST   VOID                     *ImageBase,
+  IN  CONST   UINT64                   ImageSize,
+  IN  CONST   UINT32                   *Alignment OPTIONAL,
+  OUT         IMAGE_PROPERTIES_RECORD  *ImageRecord
+  );
+
+/**
+  Deleted an image properties record. The function will also call
+  RemoveEntryList() on each code segment and the input ImageRecord before
+  freeing each pool.
+
+  @param[in]      ImageRecord             The IMAGE_PROPERTIES_RECORD to delete
+**/
+VOID
+EFIAPI
+DeleteImagePropertiesRecord (
+  IN  IMAGE_PROPERTIES_RECORD  *ImageRecord
+  );
+
 #endif
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
index 4c1466fc3336..cfe0c04b3b05 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
@@ -23,6 +23,7 @@ [LibraryClasses]
   BaseLib
   BaseMemoryLib
   DebugLib
+  MemoryAllocationLib
 
 [Packages]
   MdePkg/MdePkg.dec
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111752): https://edk2.groups.io/g/devel/message/111752
Mute This Topic: https://groups.io/mt/102834924/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel] [PATCH v5 16/16] MdeModulePkg: Update DumpImageRecord() in ImagePropertiesRecordLib
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (14 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 15/16] MdeModulePkg: Add Logic to Create/Delete Image Properties Records Taylor Beebe
@ 2023-11-27 18:18 ` Taylor Beebe
  2023-11-27 18:40 ` [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Ard Biesheuvel
  16 siblings, 0 replies; 33+ messages in thread
From: Taylor Beebe @ 2023-11-27 18:18 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Liming Gao, Dandan Bi, Jiaxin Wu, Ray Ni

Update DumpImageRecord() to be DumpImageRecords(), and improve
the debug output. The function will output at DEBUG_INFO instead,
and the function will be run in DXE and SMM
MAT logic when the MAT is installed at EndOfDxe on DEBUG builds.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c                         |   9 ++
 MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c                        |  11 +-
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c   | 134 +++++++++++++++++---
 MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h                    |   6 +-
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf |   1 +
 MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                 |   1 +
 6 files changed, 138 insertions(+), 24 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
index 993db281062a..e9343a2c4ef1 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
@@ -284,6 +284,15 @@ InstallMemoryAttributesTableOnEndOfDxe (
 {
   mMemoryAttributesTableEndOfDxe = TRUE;
   InstallMemoryAttributesTable ();
+
+  DEBUG_CODE_BEGIN ();
+  if ( mImagePropertiesPrivateData.ImageRecordCount > 0) {
+    DEBUG ((DEBUG_INFO, "DXE - Total Runtime Image Count: 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
+    DEBUG ((DEBUG_INFO, "DXE - Dump Runtime Image Records:\n"));
+    DumpImageRecords (&mImagePropertiesPrivateData.ImageRecordList);
+  }
+
+  DEBUG_CODE_END ();
 }
 
 /**
diff --git a/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c b/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
index 03de9b2c5fff..28fe74ecc421 100644
--- a/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
@@ -496,9 +496,14 @@ SmmInstallMemoryAttributesTable (
     return EFI_SUCCESS;
   }
 
-  DEBUG ((DEBUG_VERBOSE, "SMM Total Image Count - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
-  DEBUG ((DEBUG_VERBOSE, "SMM Dump ImageRecord:\n"));
-  DumpImageRecord (&mImagePropertiesPrivateData.ImageRecordList);
+  DEBUG_CODE_BEGIN ();
+  if ( mImagePropertiesPrivateData.ImageRecordCount > 0) {
+    DEBUG ((DEBUG_INFO, "SMM - Total Runtime Image Count - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
+    DEBUG ((DEBUG_INFO, "SMM - Dump Runtime Image Records:\n"));
+    DumpImageRecords (&mImagePropertiesPrivateData.ImageRecordList);
+  }
+
+  DEBUG_CODE_END ();
 
   PublishMemoryAttributesTable ();
 
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
index 6c5eb1dc3185..e53ce086c54c 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
@@ -14,6 +14,7 @@
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
 #include <Library/MemoryAllocationLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/ImagePropertiesRecordLib.h>
 
 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
@@ -785,31 +786,128 @@ SortImageRecord (
 }
 
 /**
-  Dump image record.
+  Extract the .efi filename out of the input PDB.
 
-  @param[in]  ImageRecordList  A list of IMAGE_PROPERTIES_RECORD entries
+  @param[in]      PdbPointer      Pointer to the PDB file path.
+  @param[out]     EfiFileName     Pointer to the .efi filename.
+  @param[in]      EfiFileNameSize Size of the .efi filename buffer.
+**/
+STATIC
+VOID
+GetFilename (
+  IN CHAR8   *PdbPointer,
+  OUT CHAR8  *EfiFileName,
+  IN UINTN   EfiFileNameSize
+  )
+{
+  UINTN  Index;
+  UINTN  StartIndex;
+
+  if ((PdbPointer == NULL) || (EfiFileNameSize < 5)) {
+    return;
+  }
+
+  // Print Module Name by Pdb file path.
+  StartIndex = 0;
+  for (Index = 0; PdbPointer[Index] != 0; Index++) {
+    if ((PdbPointer[Index] == '\\') || (PdbPointer[Index] == '/')) {
+      StartIndex = Index + 1;
+    }
+  }
+
+  // Copy the PDB file name to EfiFileName and replace .pdb with .efi
+  for (Index = 0; Index < EfiFileNameSize - 4; Index++) {
+    EfiFileName[Index] = PdbPointer[Index + StartIndex];
+    if (EfiFileName[Index] == 0) {
+      EfiFileName[Index] = '.';
+    }
+
+    if (EfiFileName[Index] == '.') {
+      EfiFileName[Index + 1] = 'e';
+      EfiFileName[Index + 2] = 'f';
+      EfiFileName[Index + 3] = 'i';
+      EfiFileName[Index + 4] = 0;
+      break;
+    }
+  }
+
+  if (Index == sizeof (EfiFileName) - 4) {
+    EfiFileName[Index] = 0;
+  }
+}
+
+/**
+  Debug dumps the input list of IMAGE_PROPERTIES_RECORD structs.
+
+  @param[in]  ImageRecordList   Head of the IMAGE_PROPERTIES_RECORD list
 **/
 VOID
 EFIAPI
-DumpImageRecord (
+DumpImageRecords (
   IN LIST_ENTRY  *ImageRecordList
   )
 {
-  IMAGE_PROPERTIES_RECORD  *ImageRecord;
-  LIST_ENTRY               *ImageRecordLink;
-  UINTN                    Index;
-
-  for (ImageRecordLink = ImageRecordList->ForwardLink, Index = 0;
-       ImageRecordLink != ImageRecordList;
-       ImageRecordLink = ImageRecordLink->ForwardLink, Index++)
-  {
-    ImageRecord = CR (
-                    ImageRecordLink,
-                    IMAGE_PROPERTIES_RECORD,
-                    Link,
-                    IMAGE_PROPERTIES_RECORD_SIGNATURE
-                    );
-    DEBUG ((DEBUG_VERBOSE, "Image[%d]: 0x%016lx - 0x%016lx\n", Index, ImageRecord->ImageBase, ImageRecord->ImageSize));
+  LIST_ENTRY                            *ImageRecordLink;
+  IMAGE_PROPERTIES_RECORD               *CurrentImageRecord;
+  LIST_ENTRY                            *CodeSectionLink;
+  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *CurrentCodeSection;
+  CHAR8                                 *PdbPointer;
+  CHAR8                                 EfiFileName[256];
+
+  if (ImageRecordList == NULL) {
+    return;
+  }
+
+  ImageRecordLink = ImageRecordList->ForwardLink;
+
+  while (ImageRecordLink != ImageRecordList) {
+    CurrentImageRecord = CR (
+                           ImageRecordLink,
+                           IMAGE_PROPERTIES_RECORD,
+                           Link,
+                           IMAGE_PROPERTIES_RECORD_SIGNATURE
+                           );
+
+    PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)CurrentImageRecord->ImageBase);
+    if (PdbPointer != NULL) {
+      GetFilename (PdbPointer, EfiFileName, sizeof (EfiFileName));
+      DEBUG ((
+        DEBUG_INFO,
+        "%a: 0x%llx - 0x%llx\n",
+        EfiFileName,
+        CurrentImageRecord->ImageBase,
+        CurrentImageRecord->ImageBase + CurrentImageRecord->ImageSize
+        ));
+    } else {
+      DEBUG ((
+        DEBUG_INFO,
+        "Unknown Image: 0x%llx - 0x%llx\n",
+        CurrentImageRecord->ImageBase,
+        CurrentImageRecord->ImageBase + CurrentImageRecord->ImageSize
+        ));
+    }
+
+    CodeSectionLink = CurrentImageRecord->CodeSegmentList.ForwardLink;
+
+    while (CodeSectionLink != &CurrentImageRecord->CodeSegmentList) {
+      CurrentCodeSection = CR (
+                             CodeSectionLink,
+                             IMAGE_PROPERTIES_RECORD_CODE_SECTION,
+                             Link,
+                             IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
+                             );
+
+      DEBUG ((
+        DEBUG_INFO,
+        "  Code Section: 0x%llx - 0x%llx\n",
+        CurrentCodeSection->CodeSegmentBase,
+        CurrentCodeSection->CodeSegmentBase + CurrentCodeSection->CodeSegmentSize
+        ));
+
+      CodeSectionLink = CodeSectionLink->ForwardLink;
+    }
+
+    ImageRecordLink = ImageRecordLink->ForwardLink;
   }
 }
 
diff --git a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
index 5090a521536b..87c94c723752 100644
--- a/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
+++ b/MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
@@ -182,13 +182,13 @@ FindImageRecord (
   );
 
 /**
-  Dump image record.
+  Debug dumps the input list of IMAGE_PROPERTIES_RECORD structs.
 
-  @param[in]  ImageRecordList  A list of IMAGE_PROPERTIES_RECORD entries
+  @param[in]  ImageRecordList   Head of the IMAGE_PROPERTIES_RECORD list
 **/
 VOID
 EFIAPI
-DumpImageRecord (
+DumpImageRecords (
   IN LIST_ENTRY  *ImageRecordList
   );
 
diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
index cfe0c04b3b05..1f82cc3e469c 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
@@ -24,6 +24,7 @@ [LibraryClasses]
   BaseMemoryLib
   DebugLib
   MemoryAllocationLib
+  PeCoffGetEntryPointLib
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
index 2b8cbb867a73..198cdd814fb9 100644
--- a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
+++ b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
@@ -57,6 +57,7 @@ [Components]
   MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.inf {
     <LibraryClasses>
       ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
+      PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
   }
 
   #
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111753): https://edk2.groups.io/g/devel/message/111753
Mute This Topic: https://groups.io/mt/102834925/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​
  2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
                   ` (15 preceding siblings ...)
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 16/16] MdeModulePkg: Update DumpImageRecord() in ImagePropertiesRecordLib Taylor Beebe
@ 2023-11-27 18:40 ` Ard Biesheuvel
  2023-11-28 10:22   ` Ni, Ray
  16 siblings, 1 reply; 33+ messages in thread
From: Ard Biesheuvel @ 2023-11-27 18:40 UTC (permalink / raw)
  To: Taylor Beebe
  Cc: devel, Andrew Fish, Ard Biesheuvel, Dandan Bi, Eric Dong,
	Gerd Hoffmann, Guo Dong, Gua Guo, James Lu, Jian J Wang,
	Jiewen Yao, Jordan Justen, Leif Lindholm, Liming Gao, Rahul Kumar,
	Ray Ni, Sami Mujawar, Sean Rhodes, Lazlo Ersek

On Mon, 27 Nov 2023 at 19:18, Taylor Beebe <taylor.d.beebe@gmail.com> wrote:
>
> v5:
> This version is purely an update of commit messages and orientation.
> No code changes were made.
> - Split patch 9 into 3 separate patches so each fix is in its own
>   commit.
> - Updated the commit comment of patch 11 to add context.
>

Thanks for sticking with this.

For the series,

Reviewed-by: Ard Biesheuvel <ardb@kernel.org>



> v4:
> - Expose additional functions in the Library API
> - Add NULL checks to library functions and return a
>   status where applicable.
>
> v3:
> - Refactor patch series so the transition of logic from the DXE
>   MAT logic to the new library is more clear.
> - Update function headers to improve clarity and follow EDK2
>   standards.
> - Add Create and Delete functions for Image Properties Records
>   and redirect some of the SMM and DXE MAT code to use these
>   functions.
> - Update/Add DumpImageRecords() to print the image name and code
>   sections of each runtime image which will be put in the MAT.
>   The DXE and SMM MAT logic will now invoke the DumpImageRecords()
>   on DEBUG builds at the EndOfDxe event to install the MAT.
>
> v2:
> - A one-line change in patch 3 was moved to patch 9 for correctness.
>
> Reference: https://github.com/tianocore/edk2/pull/4590
> Bugzilla: https://bugzilla.tianocore.org/show_bug.cgi?id=4492
>
> The UEFI and SMM MAT logic contains duplicate logic for manipulating image
> properties records which is used to track runtime images.
> This patch series adds a new library, ImagePropertiesRecordLib,
> which consolidates this logic and fixes the bugs which currently exist in
> the MAT logic.
>
> The first patch adds the ImagePropertiesRecordLib implementation which
> is a copy of the UEFI MAT logic with minor modifications to remove the
> reliance on globabl variables and make the code unit testable.
>
> The second patch adds a unit test for the ImagePropertiesRecordLib. The
> logic tests various potential layouts of the EFI memory map and runtime
> images. 3/4 of these tests will fail which demonstrates the MAT logic
> bugs.
>
> The third patch fixes the logic in the ImagePropertiesRecordLib so
> that all of the unit tests pass and the MAT logic can be fixed by
> using the library.
>
> The remaining patches add library instances to DSC files and remove
> the image properties record logic from the SMM and UEFI MAT logic.
>
> Cc: Andrew Fish <afish@apple.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Dandan Bi <dandan.bi@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Cc: Guo Dong <guo.dong@intel.com>
> Cc: Gua Guo <gua.guo@intel.com>
> Cc: James Lu <james.lu@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Leif Lindholm <quic_llindhol@quicinc.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Rahul Kumar <rahul1.kumar@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Sami Mujawar <sami.mujawar@arm.com>
> Cc: Sean Rhodes <sean@starlabs.systems>
> Cc: Lazlo Ersek <lersek@redhat.com>
>
> Taylor Beebe (16):
>   MdeModulePkg: Add ImagePropertiesRecordLib
>   ArmVirtPkg: Add ImagePropertiesRecordLib Instance
>   EmulatorPkg: Add ImagePropertiesRecordLib Instance
>   OvmfPkg: Add ImagePropertiesRecordLib Instance
>   UefiPayloadPkg: Add ImagePropertiesRecordLib Instance
>   MdeModulePkg: Update MemoryAttributesTable.c to Reduce Global Variable
>     Use
>   MdeModulePkg: Move Some DXE MAT Logic to ImagePropertiesRecordLib
>   MdeModulePkg: Add ImagePropertiesRecordLib Host-Based Unit Test
>   MdeModulePkg: Fix MAT Descriptor Count Calculation
>   MdeModulePkg: Fix MAT SplitRecord() Logic
>   MdeModulePkg: Fix MAT SplitTable() Logic
>   MdeModulePkg: Add NULL checks and Return Status to
>     ImagePropertiesRecordLib
>   UefiCpuPkg: Use Attribute From SMM MemoryAttributesTable if Nonzero
>   MdeModulePkg: Transition SMM MAT Logic to Use ImagePropertiesRecordLib
>   MdeModulePkg: Add Logic to Create/Delete Image Properties Records
>   MdeModulePkg: Update DumpImageRecord() in ImagePropertiesRecordLib
>
>  MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c                                              |  967 +----------------
>  MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c                                                   |   24 +-
>  MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c                                             |  958 +---------------
>  MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c                        | 1144 ++++++++++++++++++++
>  MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.c   |  938 ++++++++++++++++
>  UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c                                              |   19 +-
>  ArmVirtPkg/ArmVirt.dsc.inc                                                                      |    1 +
>  EmulatorPkg/EmulatorPkg.dsc                                                                     |    1 +
>  MdeModulePkg/Core/Dxe/DxeMain.h                                                                 |   20 -
>  MdeModulePkg/Core/Dxe/DxeMain.inf                                                               |    1 +
>  MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf                                                       |    1 +
>  MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h                                         |  234 ++++
>  MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf                      |   31 +
>  MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.inf |   35 +
>  MdeModulePkg/MdeModulePkg.dec                                                                   |    5 +
>  MdeModulePkg/MdeModulePkg.dsc                                                                   |    2 +
>  MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                                      |    6 +
>  OvmfPkg/AmdSev/AmdSevX64.dsc                                                                    |    1 +
>  OvmfPkg/Bhyve/BhyveX64.dsc                                                                      |    1 +
>  OvmfPkg/CloudHv/CloudHvX64.dsc                                                                  |    1 +
>  OvmfPkg/IntelTdx/IntelTdxX64.dsc                                                                |    1 +
>  OvmfPkg/Microvm/MicrovmX64.dsc                                                                  |    1 +
>  OvmfPkg/OvmfPkgIa32.dsc                                                                         |    1 +
>  OvmfPkg/OvmfPkgIa32X64.dsc                                                                      |    1 +
>  OvmfPkg/OvmfPkgX64.dsc                                                                          |    1 +
>  OvmfPkg/OvmfXen.dsc                                                                             |    1 +
>  OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc                                                             |    1 +
>  UefiPayloadPkg/UefiPayloadPkg.dsc                                                               |    1 +
>  28 files changed, 2524 insertions(+), 1874 deletions(-)
>  create mode 100644 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
>  create mode 100644 MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.c
>  create mode 100644 MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
>  create mode 100644 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
>  create mode 100644 MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImagePropertiesRecordLibUnitTestHost.inf
>
> --
> 2.42.0.windows.2
>


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111755): https://edk2.groups.io/g/devel/message/111755
Mute This Topic: https://groups.io/mt/102834905/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​
  2023-11-27 18:40 ` [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Ard Biesheuvel
@ 2023-11-28 10:22   ` Ni, Ray
  0 siblings, 0 replies; 33+ messages in thread
From: Ni, Ray @ 2023-11-28 10:22 UTC (permalink / raw)
  To: Ard Biesheuvel, Taylor Beebe
  Cc: devel@edk2.groups.io, Andrew Fish, Ard Biesheuvel, Bi, Dandan,
	Dong, Eric, Gerd Hoffmann, Dong, Guo, Guo, Gua, Lu, James,
	Wang, Jian J, Yao, Jiewen, Justen, Jordan L, Leif Lindholm,
	Gao, Liming, Kumar, Rahul R, Sami Mujawar, Rhodes, Sean,
	Lazlo Ersek

Taylor,
Thanks for spending time on removing the duplicated code in DxeCore and SmmCore.

I am ok with your current patch series. But I do have some suggestions that you or someone else could possibly enhance the lib API in future:

In MdeModulePkg\Core\Dxe\Misc\MemoryAttributesTable.c, InsertImageRecord() is implemented to call the new ImagePropertiesRecordLib as follows:
1. CreateImagePropertiesRecord() to create the IMAGE_PROPERTIES_RECORD instance.
  1.a. The lib parses the PE-COFF header to extract all the sections.
      Should we update PeCoffLib to add the missing capability that extracts the section info?
      I am ok to keep the section extraction code in ImagePropertiesRecordLib as the comments below are more cared by me.

2. if no code section, error
  2.a. Can we update CreateImagePropertiesRecord() to return failure status if no code section is found?
     We only need the lib API to return success for no-code-section case when caller does require to handle it differently.

3. IsImageRecordCodeSectionValid() to check if code sections are valid.
  Should we update the lib implementation to do the check before CreateImagePropertiesRecord() returns? This could reduce one API interface. Also this makes the caller easier to write.

4. Insert the IMAGE_PROPERTIES_RECORD instance to ImageRecordList.
  Should we rename CreateImagePropertiesRecord() to InsertImagePropertiesRecord() so that the insertion is done before InsertImagePropertiesRecord() returns?

5. Sort the ImageRecordList.
  Should we update the CreateImagePropertiesRecord() /InsertImagePropertiesRecord() to sort the list internally before it returns?


In summary, we could design the library API in a way that caller could call as follows:

LIST_ENTRY mImageList;
VOID *ImagePropertiesRecord;

InitializeListHead (&mImageList);
InsertImagePropertiesRecord (&mImageList, ImageBase, ImageSize, &ImagePropertiesRecord);
// caller doesn't know what's stored for one image properties record. It only knows a "handle" to the image properties record.
Saves ImagePropertiesRecord in EFI_RUNTIME_IMAGE_ENTRY for later unload.

If any error happens later on:
  DeleteImagePropertiesRecord (ImagePropertiesRecord);


So, following APIs can be eliminated:
* Structure IMAGE_PROPERTIES_RECORD_CODE_SECTION
* Structure IMAGE_PROPERTIES_RECORD
* SortImageRecordCodeSection()
* IsImageRecordCodeSectionValid()
* SortImageRecord()
* SwapImageRecord()
* SwapImageRecordCodeSection()
* FindImageRecord()

And only following APIs are needed:
* InsertImagePropertiesRecord()
* DeleteImagePropertiesRecord()
* SplitMemoryDescriptors() or SplitTable()
* DumpImageRecords()



Thanks,
Ray
> -----Original Message-----
> From: Ard Biesheuvel <ardb@kernel.org>
> Sent: Tuesday, November 28, 2023 2:40 AM
> To: Taylor Beebe <taylor.d.beebe@gmail.com>
> Cc: devel@edk2.groups.io; Andrew Fish <afish@apple.com>; Ard Biesheuvel
> <ardb+tianocore@kernel.org>; Bi, Dandan <dandan.bi@intel.com>; Dong,
> Eric <eric.dong@intel.com>; Gerd Hoffmann <kraxel@redhat.com>; Dong,
> Guo <guo.dong@intel.com>; Guo, Gua <gua.guo@intel.com>; Lu, James
> <james.lu@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen
> <jiewen.yao@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Leif
> Lindholm <quic_llindhol@quicinc.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>; Kumar, Rahul R <rahul.r.kumar@intel.com>; Ni,
> Ray <ray.ni@intel.com>; Sami Mujawar <sami.mujawar@arm.com>; Rhodes,
> Sean <sean@starlabs.systems>; Lazlo Ersek <lersek@redhat.com>
> Subject: Re: [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT
> Bugs​
> 
> On Mon, 27 Nov 2023 at 19:18, Taylor Beebe <taylor.d.beebe@gmail.com>
> wrote:
> >
> > v5:
> > This version is purely an update of commit messages and orientation.
> > No code changes were made.
> > - Split patch 9 into 3 separate patches so each fix is in its own
> >   commit.
> > - Updated the commit comment of patch 11 to add context.
> >
> 
> Thanks for sticking with this.
> 
> For the series,
> 
> Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
> 
> 
> 
> > v4:
> > - Expose additional functions in the Library API
> > - Add NULL checks to library functions and return a
> >   status where applicable.
> >
> > v3:
> > - Refactor patch series so the transition of logic from the DXE
> >   MAT logic to the new library is more clear.
> > - Update function headers to improve clarity and follow EDK2
> >   standards.
> > - Add Create and Delete functions for Image Properties Records
> >   and redirect some of the SMM and DXE MAT code to use these
> >   functions.
> > - Update/Add DumpImageRecords() to print the image name and code
> >   sections of each runtime image which will be put in the MAT.
> >   The DXE and SMM MAT logic will now invoke the DumpImageRecords()
> >   on DEBUG builds at the EndOfDxe event to install the MAT.
> >
> > v2:
> > - A one-line change in patch 3 was moved to patch 9 for correctness.
> >
> > Reference: https://github.com/tianocore/edk2/pull/4590
> > Bugzilla: https://bugzilla.tianocore.org/show_bug.cgi?id=4492
> >
> > The UEFI and SMM MAT logic contains duplicate logic for manipulating
> image
> > properties records which is used to track runtime images.
> > This patch series adds a new library, ImagePropertiesRecordLib,
> > which consolidates this logic and fixes the bugs which currently exist in
> > the MAT logic.
> >
> > The first patch adds the ImagePropertiesRecordLib implementation which
> > is a copy of the UEFI MAT logic with minor modifications to remove the
> > reliance on globabl variables and make the code unit testable.
> >
> > The second patch adds a unit test for the ImagePropertiesRecordLib. The
> > logic tests various potential layouts of the EFI memory map and runtime
> > images. 3/4 of these tests will fail which demonstrates the MAT logic
> > bugs.
> >
> > The third patch fixes the logic in the ImagePropertiesRecordLib so
> > that all of the unit tests pass and the MAT logic can be fixed by
> > using the library.
> >
> > The remaining patches add library instances to DSC files and remove
> > the image properties record logic from the SMM and UEFI MAT logic.
> >
> > Cc: Andrew Fish <afish@apple.com>
> > Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> > Cc: Dandan Bi <dandan.bi@intel.com>
> > Cc: Eric Dong <eric.dong@intel.com>
> > Cc: Gerd Hoffmann <kraxel@redhat.com>
> > Cc: Guo Dong <guo.dong@intel.com>
> > Cc: Gua Guo <gua.guo@intel.com>
> > Cc: James Lu <james.lu@intel.com>
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Leif Lindholm <quic_llindhol@quicinc.com>
> > Cc: Liming Gao <gaoliming@byosoft.com.cn>
> > Cc: Rahul Kumar <rahul1.kumar@intel.com>
> > Cc: Ray Ni <ray.ni@intel.com>
> > Cc: Sami Mujawar <sami.mujawar@arm.com>
> > Cc: Sean Rhodes <sean@starlabs.systems>
> > Cc: Lazlo Ersek <lersek@redhat.com>
> >
> > Taylor Beebe (16):
> >   MdeModulePkg: Add ImagePropertiesRecordLib
> >   ArmVirtPkg: Add ImagePropertiesRecordLib Instance
> >   EmulatorPkg: Add ImagePropertiesRecordLib Instance
> >   OvmfPkg: Add ImagePropertiesRecordLib Instance
> >   UefiPayloadPkg: Add ImagePropertiesRecordLib Instance
> >   MdeModulePkg: Update MemoryAttributesTable.c to Reduce Global
> Variable
> >     Use
> >   MdeModulePkg: Move Some DXE MAT Logic to
> ImagePropertiesRecordLib
> >   MdeModulePkg: Add ImagePropertiesRecordLib Host-Based Unit Test
> >   MdeModulePkg: Fix MAT Descriptor Count Calculation
> >   MdeModulePkg: Fix MAT SplitRecord() Logic
> >   MdeModulePkg: Fix MAT SplitTable() Logic
> >   MdeModulePkg: Add NULL checks and Return Status to
> >     ImagePropertiesRecordLib
> >   UefiCpuPkg: Use Attribute From SMM MemoryAttributesTable if Nonzero
> >   MdeModulePkg: Transition SMM MAT Logic to Use
> ImagePropertiesRecordLib
> >   MdeModulePkg: Add Logic to Create/Delete Image Properties Records
> >   MdeModulePkg: Update DumpImageRecord() in
> ImagePropertiesRecordLib
> >
> >  MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
> |  967 +----------------
> >  MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
> |   24 +-
> >  MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
> |  958 +---------------
> >
> MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLi
> b.c                        | 1144 ++++++++++++++++++++
> >
> MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImageProperties
> RecordLibUnitTestHost.c   |  938 ++++++++++++++++
> >  UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
> |   19 +-
> >  ArmVirtPkg/ArmVirt.dsc.inc
> |    1 +
> >  EmulatorPkg/EmulatorPkg.dsc
> |    1 +
> >  MdeModulePkg/Core/Dxe/DxeMain.h
> |   20 -
> >  MdeModulePkg/Core/Dxe/DxeMain.inf
> |    1 +
> >  MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
> |    1 +
> >  MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
> |  234 ++++
> >
> MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLi
> b.inf                      |   31 +
> >
> MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImageProperties
> RecordLibUnitTestHost.inf |   35 +
> >  MdeModulePkg/MdeModulePkg.dec
> |    5 +
> >  MdeModulePkg/MdeModulePkg.dsc
> |    2 +
> >  MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> |    6 +
> >  OvmfPkg/AmdSev/AmdSevX64.dsc
> |    1 +
> >  OvmfPkg/Bhyve/BhyveX64.dsc
> |    1 +
> >  OvmfPkg/CloudHv/CloudHvX64.dsc
> |    1 +
> >  OvmfPkg/IntelTdx/IntelTdxX64.dsc
> |    1 +
> >  OvmfPkg/Microvm/MicrovmX64.dsc
> |    1 +
> >  OvmfPkg/OvmfPkgIa32.dsc
> |    1 +
> >  OvmfPkg/OvmfPkgIa32X64.dsc
> |    1 +
> >  OvmfPkg/OvmfPkgX64.dsc
> |    1 +
> >  OvmfPkg/OvmfXen.dsc
> |    1 +
> >  OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc
> |    1 +
> >  UefiPayloadPkg/UefiPayloadPkg.dsc
> |    1 +
> >  28 files changed, 2524 insertions(+), 1874 deletions(-)
> >  create mode 100644
> MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLi
> b.c
> >  create mode 100644
> MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImageProperties
> RecordLibUnitTestHost.c
> >  create mode 100644
> MdeModulePkg/Include/Library/ImagePropertiesRecordLib.h
> >  create mode 100644
> MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLi
> b.inf
> >  create mode 100644
> MdeModulePkg/Library/ImagePropertiesRecordLib/UnitTest/ImageProperties
> RecordLibUnitTestHost.inf
> >
> > --
> > 2.42.0.windows.2
> >


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#111804): https://edk2.groups.io/g/devel/message/111804
Mute This Topic: https://groups.io/mt/102834905/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/12367111/7686176/1913456212/xyzzy [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2023-11-27 18:18 ` [edk2-devel] [PATCH v5 10/16] MdeModulePkg: Fix MAT SplitRecord() Logic Taylor Beebe
@ 2024-04-12  5:14   ` Huang, Yanbo
  2024-04-12 15:09     ` Taylor Beebe
  0 siblings, 1 reply; 33+ messages in thread
From: Huang, Yanbo @ 2024-04-12  5:14 UTC (permalink / raw)
  To: devel@edk2.groups.io, taylor.d.beebe@gmail.com
  Cc: Wang, Jian J, Gao, Liming, Bi, Dandan, Zhou, Jianfeng,
	Huang, Yanbo

Hi Beebe,

Recently we found this commit " MdeModulePkg: Fix MAT SplitRecord() Logic " will cause SUT reset after enable some knobs.
I filed one Bugzilla for it: https://bugzilla.tianocore.org/show_bug.cgi?id=4751

After debug, we found in SplitRecord API, many entries attribute are set to 0, not align with the UEFI spec:
"Memory Attributes Table (MAT):
EFI_MEMORY_ATTRIBUTES_TABLE. The entire UEFI runtime must be described by this table.
All entries must include attributes EFI_MEMORY_RO, EFI_MEMORY_XP, or both. Memory MUST be either readable and executable OR writeable and non-executable."
This should be the root cause of this issue.
When we update "NewRecord->Attribute     = TempRecord.Attribute;" to "NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;", SUT can boot to windows.

@taylor.d.beebe@gmail.com Could you please help to send one formal fix patch for this issue?
Thanks!

Best Regards,
Yanbo Huang

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Taylor Beebe
Sent: Tuesday, November 28, 2023 2:18 AM
To: devel@edk2.groups.io
Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Bi, Dandan <dandan.bi@intel.com>
Subject: [edk2-devel] [PATCH v5 10/16] MdeModulePkg: Fix MAT SplitRecord() Logic

SplitRecord() does not handle the case where a memory descriptor describes an image region plus extra pages before or after the image region. This patch fixes this case by carving off the unrelated regions into their own descriptors.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c | 56 ++++++++++----------
 1 file changed, 27 insertions(+), 29 deletions(-)

diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
index 7c0ecd07c1bb..9d4082280bf5 100644
--- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
+++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecor
+++ dLib.c
@@ -323,7 +323,6 @@ SplitRecord (
   UINT64                   PhysicalEnd;
   UINTN                    NewRecordCount;
   UINTN                    TotalNewRecordCount;
-  BOOLEAN                  IsLastRecordData;
 
   if (MaxSplitRecordCount == 0) {
     CopyMem (NewRecord, OldRecord, DescriptorSize); @@ -344,35 +343,16 @@ SplitRecord (
     NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
     if (NewImageRecord == NULL) {
       //
-      // No more image covered by this range, stop
+      // No more images cover this range, check if we've reached the end of the old descriptor. If not,
+      // add the remaining range to the new descriptor list.
       //
-      if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {
-        //
-        // If this is still address in this record, need record.
-        //
-        NewRecord        = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-        IsLastRecordData = FALSE;
-        if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) {
-          IsLastRecordData = TRUE;
-        }
-
-        if (IsLastRecordData) {
-          //
-          // Last record is DATA, just merge it.
-          //
-          NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - NewRecord->PhysicalStart);
-        } else {
-          //
-          // Last record is CODE, create a new DATA entry.
-          //
-          NewRecord                = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
-          NewRecord->Type          = TempRecord.Type;
-          NewRecord->PhysicalStart = TempRecord.PhysicalStart;
-          NewRecord->VirtualStart  = 0;
-          NewRecord->NumberOfPages = TempRecord.NumberOfPages;
-          NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
-          TotalNewRecordCount++;
-        }
+      if (PhysicalEnd > PhysicalStart) {
+        NewRecord->Type          = TempRecord.Type;
+        NewRecord->PhysicalStart = PhysicalStart;
+        NewRecord->VirtualStart  = 0;
+        NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
+        NewRecord->Attribute     = TempRecord.Attribute;
+        TotalNewRecordCount++;
       }
 
       break;
@@ -380,6 +360,24 @@ SplitRecord (
 
     ImageRecord = NewImageRecord;
 
+    //
+    // Update PhysicalStart to exclude the portion before the image buffer
+    //
+    if (TempRecord.PhysicalStart < ImageRecord->ImageBase) {
+      NewRecord->Type          = TempRecord.Type;
+      NewRecord->PhysicalStart = TempRecord.PhysicalStart;
+      NewRecord->VirtualStart  = 0;
+      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecord->ImageBase - TempRecord.PhysicalStart);
+      NewRecord->Attribute     = TempRecord.Attribute;
+      TotalNewRecordCount++;
+
+      PhysicalStart            = ImageRecord->ImageBase;
+      TempRecord.PhysicalStart = PhysicalStart;
+      TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - 
+ PhysicalStart);
+
+      NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + DescriptorSize);
+    }
+
     //
     // Set new record
     //
--
2.42.0.windows.2








-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117641): https://edk2.groups.io/g/devel/message/117641
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-12  5:14   ` [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows Huang, Yanbo
@ 2024-04-12 15:09     ` Taylor Beebe
  2024-04-14 14:35       ` Huang, Yanbo
  0 siblings, 1 reply; 33+ messages in thread
From: Taylor Beebe @ 2024-04-12 15:09 UTC (permalink / raw)
  To: Huang, Yanbo, devel@edk2.groups.io
  Cc: Wang, Jian J, Gao, Liming, Bi, Dandan, Zhou, Jianfeng

Hi Yanbo,

Can you help me understand the memory layout which causes this issue?

If a single EfiRuntimeServicesCode descriptor needs to be split because 
an image is within the memory range. I think that descriptor is split 
like so in the case you're encountering:

-------------------  ---       ---
|       DATA      |     |        |
-------------------     |        |
|       CODE      |     | Image  |
-------------------     | Memory | EfiRuntimeServicesCode
|       DATA      |     |        |
-------------------  ---         |
|   Extra Pages   |              |
-------------------            ---

In this case, because the memory type of the buffer is 
EfiRuntimeServicesCode, shouldn't the final pages be EFI_MEMORY_RO?

Thanks!
-Taylor
On 4/11/2024 10:14 PM, Huang, Yanbo wrote:
> Hi Beebe,
>
> Recently we found this commit " MdeModulePkg: Fix MAT SplitRecord() Logic " will cause SUT reset after enable some knobs.
> I filed one Bugzilla for it: https://bugzilla.tianocore.org/show_bug.cgi?id=4751
>
> After debug, we found in SplitRecord API, many entries attribute are set to 0, not align with the UEFI spec:
> "Memory Attributes Table (MAT):
> EFI_MEMORY_ATTRIBUTES_TABLE. The entire UEFI runtime must be described by this table.
> All entries must include attributes EFI_MEMORY_RO, EFI_MEMORY_XP, or both. Memory MUST be either readable and executable OR writeable and non-executable."
> This should be the root cause of this issue.
> When we update "NewRecord->Attribute     = TempRecord.Attribute;" to "NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;", SUT can boot to windows.
>
> @taylor.d.beebe@gmail.com Could you please help to send one formal fix patch for this issue?
> Thanks!
>
> Best Regards,
> Yanbo Huang
>
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Taylor Beebe
> Sent: Tuesday, November 28, 2023 2:18 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Bi, Dandan <dandan.bi@intel.com>
> Subject: [edk2-devel] [PATCH v5 10/16] MdeModulePkg: Fix MAT SplitRecord() Logic
>
> SplitRecord() does not handle the case where a memory descriptor describes an image region plus extra pages before or after the image region. This patch fixes this case by carving off the unrelated regions into their own descriptors.
>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Dandan Bi <dandan.bi@intel.com>
> Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
> ---
>   MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c | 56 ++++++++++----------
>   1 file changed, 27 insertions(+), 29 deletions(-)
>
> diff --git a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
> index 7c0ecd07c1bb..9d4082280bf5 100644
> --- a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c
> +++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecor
> +++ dLib.c
> @@ -323,7 +323,6 @@ SplitRecord (
>     UINT64                   PhysicalEnd;
>     UINTN                    NewRecordCount;
>     UINTN                    TotalNewRecordCount;
> -  BOOLEAN                  IsLastRecordData;
>   
>     if (MaxSplitRecordCount == 0) {
>       CopyMem (NewRecord, OldRecord, DescriptorSize); @@ -344,35 +343,16 @@ SplitRecord (
>       NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
>       if (NewImageRecord == NULL) {
>         //
> -      // No more image covered by this range, stop
> +      // No more images cover this range, check if we've reached the end of the old descriptor. If not,
> +      // add the remaining range to the new descriptor list.
>         //
> -      if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {
> -        //
> -        // If this is still address in this record, need record.
> -        //
> -        NewRecord        = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
> -        IsLastRecordData = FALSE;
> -        if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) {
> -          IsLastRecordData = TRUE;
> -        }
> -
> -        if (IsLastRecordData) {
> -          //
> -          // Last record is DATA, just merge it.
> -          //
> -          NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - NewRecord->PhysicalStart);
> -        } else {
> -          //
> -          // Last record is CODE, create a new DATA entry.
> -          //
> -          NewRecord                = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
> -          NewRecord->Type          = TempRecord.Type;
> -          NewRecord->PhysicalStart = TempRecord.PhysicalStart;
> -          NewRecord->VirtualStart  = 0;
> -          NewRecord->NumberOfPages = TempRecord.NumberOfPages;
> -          NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
> -          TotalNewRecordCount++;
> -        }
> +      if (PhysicalEnd > PhysicalStart) {
> +        NewRecord->Type          = TempRecord.Type;
> +        NewRecord->PhysicalStart = PhysicalStart;
> +        NewRecord->VirtualStart  = 0;
> +        NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
> +        NewRecord->Attribute     = TempRecord.Attribute;
> +        TotalNewRecordCount++;
>         }
>   
>         break;
> @@ -380,6 +360,24 @@ SplitRecord (
>   
>       ImageRecord = NewImageRecord;
>   
> +    //
> +    // Update PhysicalStart to exclude the portion before the image buffer
> +    //
> +    if (TempRecord.PhysicalStart < ImageRecord->ImageBase) {
> +      NewRecord->Type          = TempRecord.Type;
> +      NewRecord->PhysicalStart = TempRecord.PhysicalStart;
> +      NewRecord->VirtualStart  = 0;
> +      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecord->ImageBase - TempRecord.PhysicalStart);
> +      NewRecord->Attribute     = TempRecord.Attribute;
> +      TotalNewRecordCount++;
> +
> +      PhysicalStart            = ImageRecord->ImageBase;
> +      TempRecord.PhysicalStart = PhysicalStart;
> +      TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd -
> + PhysicalStart);
> +
> +      NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + DescriptorSize);
> +    }
> +
>       //
>       // Set new record
>       //
> --
> 2.42.0.windows.2
>
>
>
> 
>
>


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117710): https://edk2.groups.io/g/devel/message/117710
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-12 15:09     ` Taylor Beebe
@ 2024-04-14 14:35       ` Huang, Yanbo
  2024-04-15 10:57         ` Dandan Bi
  0 siblings, 1 reply; 33+ messages in thread
From: Huang, Yanbo @ 2024-04-14 14:35 UTC (permalink / raw)
  To: Taylor Beebe, devel@edk2.groups.io
  Cc: Wang, Jian J, Gao, Liming, Bi, Dandan, Zhou, Jianfeng

Hi Taylor,

For your mentioned: "In this case, because the memory type of the buffer is EfiRuntimeServicesCode, shouldn't the final pages be EFI_MEMORY_RO?"

After print the attributes, the attribute are not set to EFI_MEMORY_RO, nearly all of the NewRecord->Attribute are set to 0 in SplitRecord API.

Best Regards,
Yanbo Huang
-----Original Message-----
From: Taylor Beebe <taylor.d.beebe@gmail.com> 
Sent: Friday, April 12, 2024 11:10 PM
To: Huang, Yanbo <yanbo.huang@intel.com>; devel@edk2.groups.io
Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Bi, Dandan <dandan.bi@intel.com>; Zhou, Jianfeng <jianfeng.zhou@intel.com>
Subject: Re: MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows

Hi Yanbo,

Can you help me understand the memory layout which causes this issue?

If a single EfiRuntimeServicesCode descriptor needs to be split because an image is within the memory range. I think that descriptor is split like so in the case you're encountering:

-------------------  ---       ---
|       DATA      |     |        |
-------------------     |        |
|       CODE      |     | Image  |
-------------------     | Memory | EfiRuntimeServicesCode
|       DATA      |     |        |
-------------------  ---         |
|   Extra Pages   |              |
-------------------            ---

In this case, because the memory type of the buffer is EfiRuntimeServicesCode, shouldn't the final pages be EFI_MEMORY_RO?

Thanks!
-Taylor
On 4/11/2024 10:14 PM, Huang, Yanbo wrote:
> Hi Beebe,
>
> Recently we found this commit " MdeModulePkg: Fix MAT SplitRecord() Logic " will cause SUT reset after enable some knobs.
> I filed one Bugzilla for it: 
> https://bugzilla.tianocore.org/show_bug.cgi?id=4751
>
> After debug, we found in SplitRecord API, many entries attribute are set to 0, not align with the UEFI spec:
> "Memory Attributes Table (MAT):
> EFI_MEMORY_ATTRIBUTES_TABLE. The entire UEFI runtime must be described by this table.
> All entries must include attributes EFI_MEMORY_RO, EFI_MEMORY_XP, or both. Memory MUST be either readable and executable OR writeable and non-executable."
> This should be the root cause of this issue.
> When we update "NewRecord->Attribute     = TempRecord.Attribute;" to "NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;", SUT can boot to windows.
>
> @taylor.d.beebe@gmail.com Could you please help to send one formal fix patch for this issue?
> Thanks!
>
> Best Regards,
> Yanbo Huang
>
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Taylor 
> Beebe
> Sent: Tuesday, November 28, 2023 2:18 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming 
> <gaoliming@byosoft.com.cn>; Bi, Dandan <dandan.bi@intel.com>
> Subject: [edk2-devel] [PATCH v5 10/16] MdeModulePkg: Fix MAT 
> SplitRecord() Logic
>
> SplitRecord() does not handle the case where a memory descriptor describes an image region plus extra pages before or after the image region. This patch fixes this case by carving off the unrelated regions into their own descriptors.
>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Dandan Bi <dandan.bi@intel.com>
> Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
> ---
>   MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c | 56 ++++++++++----------
>   1 file changed, 27 insertions(+), 29 deletions(-)
>
> diff --git 
> a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordL
> ib.c 
> b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordL
> ib.c index 7c0ecd07c1bb..9d4082280bf5 100644
> --- 
> a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordL
> ib.c
> +++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRec
> +++ or
> +++ dLib.c
> @@ -323,7 +323,6 @@ SplitRecord (
>     UINT64                   PhysicalEnd;
>     UINTN                    NewRecordCount;
>     UINTN                    TotalNewRecordCount;
> -  BOOLEAN                  IsLastRecordData;
>   
>     if (MaxSplitRecordCount == 0) {
>       CopyMem (NewRecord, OldRecord, DescriptorSize); @@ -344,35 +343,16 @@ SplitRecord (
>       NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
>       if (NewImageRecord == NULL) {
>         //
> -      // No more image covered by this range, stop
> +      // No more images cover this range, check if we've reached the end of the old descriptor. If not,
> +      // add the remaining range to the new descriptor list.
>         //
> -      if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {
> -        //
> -        // If this is still address in this record, need record.
> -        //
> -        NewRecord        = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
> -        IsLastRecordData = FALSE;
> -        if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) {
> -          IsLastRecordData = TRUE;
> -        }
> -
> -        if (IsLastRecordData) {
> -          //
> -          // Last record is DATA, just merge it.
> -          //
> -          NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - NewRecord->PhysicalStart);
> -        } else {
> -          //
> -          // Last record is CODE, create a new DATA entry.
> -          //
> -          NewRecord                = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
> -          NewRecord->Type          = TempRecord.Type;
> -          NewRecord->PhysicalStart = TempRecord.PhysicalStart;
> -          NewRecord->VirtualStart  = 0;
> -          NewRecord->NumberOfPages = TempRecord.NumberOfPages;
> -          NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
> -          TotalNewRecordCount++;
> -        }
> +      if (PhysicalEnd > PhysicalStart) {
> +        NewRecord->Type          = TempRecord.Type;
> +        NewRecord->PhysicalStart = PhysicalStart;
> +        NewRecord->VirtualStart  = 0;
> +        NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
> +        NewRecord->Attribute     = TempRecord.Attribute;
> +        TotalNewRecordCount++;
>         }
>   
>         break;
> @@ -380,6 +360,24 @@ SplitRecord (
>   
>       ImageRecord = NewImageRecord;
>   
> +    //
> +    // Update PhysicalStart to exclude the portion before the image buffer
> +    //
> +    if (TempRecord.PhysicalStart < ImageRecord->ImageBase) {
> +      NewRecord->Type          = TempRecord.Type;
> +      NewRecord->PhysicalStart = TempRecord.PhysicalStart;
> +      NewRecord->VirtualStart  = 0;
> +      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecord->ImageBase - TempRecord.PhysicalStart);
> +      NewRecord->Attribute     = TempRecord.Attribute;
> +      TotalNewRecordCount++;
> +
> +      PhysicalStart            = ImageRecord->ImageBase;
> +      TempRecord.PhysicalStart = PhysicalStart;
> +      TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - 
> + PhysicalStart);
> +
> +      NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + DescriptorSize);
> +    }
> +
>       //
>       // Set new record
>       //
> --
> 2.42.0.windows.2
>
>
>
> 
>
>


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117721): https://edk2.groups.io/g/devel/message/117721
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-14 14:35       ` Huang, Yanbo
@ 2024-04-15 10:57         ` Dandan Bi
  2024-04-16  1:17           ` Taylor Beebe
  0 siblings, 1 reply; 33+ messages in thread
From: Dandan Bi @ 2024-04-15 10:57 UTC (permalink / raw)
  To: Huang, Yanbo, Taylor Beebe, devel@edk2.groups.io
  Cc: Wang, Jian J, Gao, Liming, Zhou, Jianfeng, Bi, Dandan

Hi Taylor,

With this patch, MAT contains some entries with Attribute - 0x8000000000000000, doesn't have EFI_MEMORY_RO or EFI_MEMORY_XP.
After revert this patch, don't see such entries in MAT.

a. MAT with this patch:
Entry (0x609E4268)
  Type              - 0x5
  PhysicalStart     - 0x00000000769CF000
  VirtualStart      - 0x0000000000000000
  NumberOfPages     - 0x0000000000000016
  Attribute         - 0x8000000000000000
Entry (0x609E4298)
  Type              - 0x5
  PhysicalStart     - 0x00000000769E5000
  VirtualStart      - 0x0000000000000000
  NumberOfPages     - 0x0000000000000001
  Attribute         - 0x8000000000004000
Entry (0x609E42C8)
  Type              - 0x5
  PhysicalStart     - 0x00000000769E6000
  VirtualStart      - 0x0000000000000000
  NumberOfPages     - 0x0000000000000002
  Attribute         - 0x8000000000020000

b. MAT without this patch:
Entry (0x609E4268)
  Type              - 0x5
  PhysicalStart     - 0x00000000769CF000
  VirtualStart      - 0x0000000000000000
  NumberOfPages     - 0x0000000000000017
  Attribute         - 0x8000000000004000
Entry (0x609E4298)
  Type              - 0x5
  PhysicalStart     - 0x00000000769E6000
  VirtualStart      - 0x0000000000000000
  NumberOfPages     - 0x0000000000000002
  Attribute         - 0x8000000000020000

1. For example, when OldRecord in old memory map with:
        Type - 0x00000005
        Attribute - 0x800000000000000F
        PhysicalStart - 0x769CF000
    PhysicalStart is smaller than ImageBase 0x769E5000, with this patch, it will create a new memory descriptor entry for range 0x769CF000~0x769E5000 and without EFI_MEMORY_RO or EFI_MEMORY_XP Attribute.
    Then it will only contain EFI_MEMORY_RUNTIME Attribute in MAT as doing  MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME); when install MAT.
    It seems not aligned with UEFI Spec " The only valid bits for Attribute field currently are EFI_MEMORY_RO ,EFI_MEMORY_XP , plus EFI_MEMORY_RUNTIME "?
    Could you please help double check? Thanks.

2. In function SetNewRecord, it semes already cover the DATA entry before the CODE and the DATA entry after the CODE.
    And old SplitRecord function without this patch, also has the entry to cover the reaming range of this record if no more image covered by this range.
    Why do we still need this patch? Could you please help explain? Thanks.



Thanks,
Dandan
-----Original Message-----
From: Huang, Yanbo <yanbo.huang@intel.com> 
Sent: Sunday, April 14, 2024 10:36 PM
To: Taylor Beebe <taylor.d.beebe@gmail.com>; devel@edk2.groups.io
Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Bi, Dandan <dandan.bi@intel.com>; Zhou, Jianfeng <jianfeng.zhou@intel.com>
Subject: RE: MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows

Hi Taylor,

For your mentioned: "In this case, because the memory type of the buffer is EfiRuntimeServicesCode, shouldn't the final pages be EFI_MEMORY_RO?"

After print the attributes, the attribute are not set to EFI_MEMORY_RO, nearly all of the NewRecord->Attribute are set to 0 in SplitRecord API.

Best Regards,
Yanbo Huang
-----Original Message-----
From: Taylor Beebe <taylor.d.beebe@gmail.com>
Sent: Friday, April 12, 2024 11:10 PM
To: Huang, Yanbo <yanbo.huang@intel.com>; devel@edk2.groups.io
Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Bi, Dandan <dandan.bi@intel.com>; Zhou, Jianfeng <jianfeng.zhou@intel.com>
Subject: Re: MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows

Hi Yanbo,

Can you help me understand the memory layout which causes this issue?

If a single EfiRuntimeServicesCode descriptor needs to be split because an image is within the memory range. I think that descriptor is split like so in the case you're encountering:

-------------------  ---       ---
|       DATA      |     |        |
-------------------     |        |
|       CODE      |     | Image  |
-------------------     | Memory | EfiRuntimeServicesCode
|       DATA      |     |        |
-------------------  ---         |
|   Extra Pages   |              |
-------------------            ---

In this case, because the memory type of the buffer is EfiRuntimeServicesCode, shouldn't the final pages be EFI_MEMORY_RO?

Thanks!
-Taylor
On 4/11/2024 10:14 PM, Huang, Yanbo wrote:
> Hi Beebe,
>
> Recently we found this commit " MdeModulePkg: Fix MAT SplitRecord() Logic " will cause SUT reset after enable some knobs.
> I filed one Bugzilla for it: 
> https://bugzilla.tianocore.org/show_bug.cgi?id=4751
>
> After debug, we found in SplitRecord API, many entries attribute are set to 0, not align with the UEFI spec:
> "Memory Attributes Table (MAT):
> EFI_MEMORY_ATTRIBUTES_TABLE. The entire UEFI runtime must be described by this table.
> All entries must include attributes EFI_MEMORY_RO, EFI_MEMORY_XP, or both. Memory MUST be either readable and executable OR writeable and non-executable."
> This should be the root cause of this issue.
> When we update "NewRecord->Attribute     = TempRecord.Attribute;" to "NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;", SUT can boot to windows.
>
> @taylor.d.beebe@gmail.com Could you please help to send one formal fix patch for this issue?
> Thanks!
>
> Best Regards,
> Yanbo Huang
>
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Taylor 
> Beebe
> Sent: Tuesday, November 28, 2023 2:18 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming 
> <gaoliming@byosoft.com.cn>; Bi, Dandan <dandan.bi@intel.com>
> Subject: [edk2-devel] [PATCH v5 10/16] MdeModulePkg: Fix MAT
> SplitRecord() Logic
>
> SplitRecord() does not handle the case where a memory descriptor describes an image region plus extra pages before or after the image region. This patch fixes this case by carving off the unrelated regions into their own descriptors.
>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Dandan Bi <dandan.bi@intel.com>
> Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com>
> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
> ---
>   MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.c | 56 ++++++++++----------
>   1 file changed, 27 insertions(+), 29 deletions(-)
>
> diff --git
> a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordL
> ib.c
> b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordL
> ib.c index 7c0ecd07c1bb..9d4082280bf5 100644
> ---
> a/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordL
> ib.c
> +++ b/MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRec
> +++ or
> +++ dLib.c
> @@ -323,7 +323,6 @@ SplitRecord (
>     UINT64                   PhysicalEnd;
>     UINTN                    NewRecordCount;
>     UINTN                    TotalNewRecordCount;
> -  BOOLEAN                  IsLastRecordData;
>   
>     if (MaxSplitRecordCount == 0) {
>       CopyMem (NewRecord, OldRecord, DescriptorSize); @@ -344,35 +343,16 @@ SplitRecord (
>       NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
>       if (NewImageRecord == NULL) {
>         //
> -      // No more image covered by this range, stop
> +      // No more images cover this range, check if we've reached the end of the old descriptor. If not,
> +      // add the remaining range to the new descriptor list.
>         //
> -      if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {
> -        //
> -        // If this is still address in this record, need record.
> -        //
> -        NewRecord        = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
> -        IsLastRecordData = FALSE;
> -        if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) {
> -          IsLastRecordData = TRUE;
> -        }
> -
> -        if (IsLastRecordData) {
> -          //
> -          // Last record is DATA, just merge it.
> -          //
> -          NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - NewRecord->PhysicalStart);
> -        } else {
> -          //
> -          // Last record is CODE, create a new DATA entry.
> -          //
> -          NewRecord                = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
> -          NewRecord->Type          = TempRecord.Type;
> -          NewRecord->PhysicalStart = TempRecord.PhysicalStart;
> -          NewRecord->VirtualStart  = 0;
> -          NewRecord->NumberOfPages = TempRecord.NumberOfPages;
> -          NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
> -          TotalNewRecordCount++;
> -        }
> +      if (PhysicalEnd > PhysicalStart) {
> +        NewRecord->Type          = TempRecord.Type;
> +        NewRecord->PhysicalStart = PhysicalStart;
> +        NewRecord->VirtualStart  = 0;
> +        NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
> +        NewRecord->Attribute     = TempRecord.Attribute;
> +        TotalNewRecordCount++;
>         }
>   
>         break;
> @@ -380,6 +360,24 @@ SplitRecord (
>   
>       ImageRecord = NewImageRecord;
>   
> +    //
> +    // Update PhysicalStart to exclude the portion before the image buffer
> +    //
> +    if (TempRecord.PhysicalStart < ImageRecord->ImageBase) {
> +      NewRecord->Type          = TempRecord.Type;
> +      NewRecord->PhysicalStart = TempRecord.PhysicalStart;
> +      NewRecord->VirtualStart  = 0;
> +      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecord->ImageBase - TempRecord.PhysicalStart);
> +      NewRecord->Attribute     = TempRecord.Attribute;
> +      TotalNewRecordCount++;
> +
> +      PhysicalStart            = ImageRecord->ImageBase;
> +      TempRecord.PhysicalStart = PhysicalStart;
> +      TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - 
> + PhysicalStart);
> +
> +      NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + DescriptorSize);
> +    }
> +
>       //
>       // Set new record
>       //
> --
> 2.42.0.windows.2
>
>
>
> 
>
>


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117773): https://edk2.groups.io/g/devel/message/117773
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-15 10:57         ` Dandan Bi
@ 2024-04-16  1:17           ` Taylor Beebe
  2024-04-17  2:32             ` Taylor Beebe
  0 siblings, 1 reply; 33+ messages in thread
From: Taylor Beebe @ 2024-04-16  1:17 UTC (permalink / raw)
  To: Bi, Dandan, Huang, Yanbo, devel@edk2.groups.io
  Cc: Wang, Jian J, Gao, Liming, Zhou, Jianfeng

[-- Attachment #1: Type: text/plain, Size: 4817 bytes --]


On 4/15/2024 3:57 AM, Bi, Dandan wrote:
> Hi Taylor,
>
> With this patch, MAT contains some entries with Attribute - 0x8000000000000000, doesn't have EFI_MEMORY_RO or EFI_MEMORY_XP.
> After revert this patch, don't see such entries in MAT.
>
> a. MAT with this patch:
> Entry (0x609E4268)
>    Type              - 0x5
>    PhysicalStart     - 0x00000000769CF000
>    VirtualStart      - 0x0000000000000000
>    NumberOfPages     - 0x0000000000000016
>    Attribute         - 0x8000000000000000
> Entry (0x609E4298)
>    Type              - 0x5
>    PhysicalStart     - 0x00000000769E5000
>    VirtualStart      - 0x0000000000000000
>    NumberOfPages     - 0x0000000000000001
>    Attribute         - 0x8000000000004000
> Entry (0x609E42C8)
>    Type              - 0x5
>    PhysicalStart     - 0x00000000769E6000
>    VirtualStart      - 0x0000000000000000
>    NumberOfPages     - 0x0000000000000002
>    Attribute         - 0x8000000000020000
>
> b. MAT without this patch:
> Entry (0x609E4268)
>    Type              - 0x5
>    PhysicalStart     - 0x00000000769CF000
>    VirtualStart      - 0x0000000000000000
>    NumberOfPages     - 0x0000000000000017
>    Attribute         - 0x8000000000004000
> Entry (0x609E4298)
>    Type              - 0x5
>    PhysicalStart     - 0x00000000769E6000
>    VirtualStart      - 0x0000000000000000
>    NumberOfPages     - 0x0000000000000002
>    Attribute         - 0x8000000000020000
>
> 1. For example, when OldRecord in old memory map with:
>          Type - 0x00000005
>          Attribute - 0x800000000000000F
>          PhysicalStart - 0x769CF000
>      PhysicalStart is smaller than ImageBase 0x769E5000, with this patch, it will create a new memory descriptor entry for range 0x769CF000~0x769E5000 and without EFI_MEMORY_RO or EFI_MEMORY_XP Attribute.
>      Then it will only contain EFI_MEMORY_RUNTIME Attribute in MAT as doing  MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME); when install MAT.
>      It seems not aligned with UEFI Spec " The only valid bits for Attribute field currently are EFI_MEMORY_RO ,EFI_MEMORY_XP , plus EFI_MEMORY_RUNTIME "?
>      Could you please help double check? Thanks.
Agreed that this is currently the behaviour and that the range should 
have a restrictive access attribute. More below.
> 2. In function SetNewRecord, it semes already cover the DATA entry before the CODE and the DATA entry after the CODE.
>      And old SplitRecord function without this patch, also has the entry to cover the reaming range of this record if no more image covered by this range.
>      Why do we still need this patch? Could you please help explain? Thanks.

GetMemoryMap() will merge adjacent descriptors which have the same type 
and attributes. This means that a single EfiRuntimeServicesCode 
descriptor within the memory map returned by CoreGetMemoryMap() could 
describe memory with the following layout (NOTE: this layout is odd but 
needs to be handled to fulfill the SplitTable() contract):

-------------------------
Some EfiRuntimeServicesCode memory
-------------------------
Runtime Image DATA Section
-------------------------
Runtime Image CODE Section
-------------------------
Runtime Image DATA Section
-------------------------
Some EfiRuntimeServicesCode memory
-------------------------

In this possible layout, the pre-patch logic would assume that the 
regions before and after the image were part of the image's data 
sections and would mark them as EFI_MEMORY_XP. The post-patch logic does 
not mark them with any access attributes which is fine but the DXE MAT 
logic needs to walk the memory map returned by SplitTable() to add 
access attributes to runtime regions which don't have any.

In your example, because PhysicalStart < ImageBase and 
0769CF000-0x769E5000 is EfiRuntimeServicesCode, the access attribute 
should technically be EFI_MEMORY_RO. It's likely that 
0769CF000-0x769E5000is just the unused memory bucket and so it might be 
best to mark it both EFI_MEMORY_RO and EFI_MEMORY_XP.

*An open question to the community:* Are there cases where runtime 
executable code is in a buffer separate from a loaded runtime image? Can 
the EfiRuntimeServicesCode memory regions not part of an image be 
specified in the MAT as both EFI_MEMORY_RO and EFI_MEMORY_XP, or even 
dropped entirely?

Thanks :)
-Taylor


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117813): https://edk2.groups.io/g/devel/message/117813
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



[-- Attachment #2: Type: text/html, Size: 6314 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-16  1:17           ` Taylor Beebe
@ 2024-04-17  2:32             ` Taylor Beebe
  2024-04-17 14:04               ` Huang, Yanbo
  0 siblings, 1 reply; 33+ messages in thread
From: Taylor Beebe @ 2024-04-17  2:32 UTC (permalink / raw)
  To: Bi, Dandan, Huang, Yanbo, devel@edk2.groups.io
  Cc: Wang, Jian J, Gao, Liming, Zhou, Jianfeng

[-- Attachment #1: Type: text/plain, Size: 5226 bytes --]

Hi Yanbo,

Can you confirm that the following resolves the issue you're seeing?

[PATCH v1] MdeModulePkg: Fixup MAT Attributes After Splitting EFI Memory 
Map (groups.io) <https://edk2.groups.io/g/devel/message/117889>

-Taylor

On 4/15/2024 6:17 PM, Taylor Beebe wrote:
> On 4/15/2024 3:57 AM, Bi, Dandan wrote:
>> Hi Taylor,
>>
>> With this patch, MAT contains some entries with Attribute - 0x8000000000000000, doesn't have EFI_MEMORY_RO or EFI_MEMORY_XP.
>> After revert this patch, don't see such entries in MAT.
>>
>> a. MAT with this patch:
>> Entry (0x609E4268)
>>    Type              - 0x5
>>    PhysicalStart     - 0x00000000769CF000
>>    VirtualStart      - 0x0000000000000000
>>    NumberOfPages     - 0x0000000000000016
>>    Attribute         - 0x8000000000000000
>> Entry (0x609E4298)
>>    Type              - 0x5
>>    PhysicalStart     - 0x00000000769E5000
>>    VirtualStart      - 0x0000000000000000
>>    NumberOfPages     - 0x0000000000000001
>>    Attribute         - 0x8000000000004000
>> Entry (0x609E42C8)
>>    Type              - 0x5
>>    PhysicalStart     - 0x00000000769E6000
>>    VirtualStart      - 0x0000000000000000
>>    NumberOfPages     - 0x0000000000000002
>>    Attribute         - 0x8000000000020000
>>
>> b. MAT without this patch:
>> Entry (0x609E4268)
>>    Type              - 0x5
>>    PhysicalStart     - 0x00000000769CF000
>>    VirtualStart      - 0x0000000000000000
>>    NumberOfPages     - 0x0000000000000017
>>    Attribute         - 0x8000000000004000
>> Entry (0x609E4298)
>>    Type              - 0x5
>>    PhysicalStart     - 0x00000000769E6000
>>    VirtualStart      - 0x0000000000000000
>>    NumberOfPages     - 0x0000000000000002
>>    Attribute         - 0x8000000000020000
>>
>> 1. For example, when OldRecord in old memory map with:
>>          Type - 0x00000005
>>          Attribute - 0x800000000000000F
>>          PhysicalStart - 0x769CF000
>>      PhysicalStart is smaller than ImageBase 0x769E5000, with this patch, it will create a new memory descriptor entry for range 0x769CF000~0x769E5000 and without EFI_MEMORY_RO or EFI_MEMORY_XP Attribute.
>>      Then it will only contain EFI_MEMORY_RUNTIME Attribute in MAT as doing  MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME); when install MAT.
>>      It seems not aligned with UEFI Spec " The only valid bits for Attribute field currently are EFI_MEMORY_RO ,EFI_MEMORY_XP , plus EFI_MEMORY_RUNTIME "?
>>      Could you please help double check? Thanks.
> Agreed that this is currently the behaviour and that the range should 
> have a restrictive access attribute. More below.
>> 2. In function SetNewRecord, it semes already cover the DATA entry before the CODE and the DATA entry after the CODE.
>>      And old SplitRecord function without this patch, also has the entry to cover the reaming range of this record if no more image covered by this range.
>>      Why do we still need this patch? Could you please help explain? Thanks.
>
> GetMemoryMap() will merge adjacent descriptors which have the same 
> type and attributes. This means that a single EfiRuntimeServicesCode 
> descriptor within the memory map returned by CoreGetMemoryMap() could 
> describe memory with the following layout (NOTE: this layout is odd 
> but needs to be handled to fulfill the SplitTable() contract):
>
> -------------------------
> Some EfiRuntimeServicesCode memory
> -------------------------
> Runtime Image DATA Section
> -------------------------
> Runtime Image CODE Section
> -------------------------
> Runtime Image DATA Section
> -------------------------
> Some EfiRuntimeServicesCode memory
> -------------------------
>
> In this possible layout, the pre-patch logic would assume that the 
> regions before and after the image were part of the image's data 
> sections and would mark them as EFI_MEMORY_XP. The post-patch logic 
> does not mark them with any access attributes which is fine but the 
> DXE MAT logic needs to walk the memory map returned by SplitTable() to 
> add access attributes to runtime regions which don't have any.
>
> In your example, because PhysicalStart < ImageBase and 
> 0769CF000-0x769E5000 is EfiRuntimeServicesCode, the access attribute 
> should technically be EFI_MEMORY_RO. It's likely that 
> 0769CF000-0x769E5000is just the unused memory bucket and so it might 
> be best to mark it both EFI_MEMORY_RO and EFI_MEMORY_XP.
>
> *An open question to the community:* Are there cases where runtime 
> executable code is in a buffer separate from a loaded runtime image? 
> Can the EfiRuntimeServicesCode memory regions not part of an image be 
> specified in the MAT as both EFI_MEMORY_RO and EFI_MEMORY_XP, or even 
> dropped entirely?
>
> Thanks :)
> -Taylor


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117890): https://edk2.groups.io/g/devel/message/117890
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



[-- Attachment #2: Type: text/html, Size: 6993 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-17  2:32             ` Taylor Beebe
@ 2024-04-17 14:04               ` Huang, Yanbo
  2024-04-17 23:53                 ` Taylor Beebe
  0 siblings, 1 reply; 33+ messages in thread
From: Huang, Yanbo @ 2024-04-17 14:04 UTC (permalink / raw)
  To: devel@edk2.groups.io, taylor.d.beebe@gmail.com, Bi, Dandan
  Cc: Wang, Jian J, Gao, Liming, Zhou, Jianfeng

[-- Attachment #1: Type: text/plain, Size: 5823 bytes --]

Hi Taylor,

Thanks for your update.
After test, issue can be fixed by your patch.
But why we not set the EFI_MEMORY_XP or EFI_MEMORY_RO attribute in SplitRecord API?
If we set the attribute in the beginning of the NewRecord created, it seems we don’t need to EnforceMemoryMapAttribute later?

Best Regards,
Yanbo Huang

From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Taylor Beebe
Sent: Wednesday, April 17, 2024 10:33 AM
To: Bi, Dandan <dandan.bi@intel.com>; Huang, Yanbo <yanbo.huang@intel.com>; devel@edk2.groups.io
Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Zhou, Jianfeng <jianfeng.zhou@intel.com>
Subject: Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows


Hi Yanbo,

Can you confirm that the following resolves the issue you're seeing?

[PATCH v1] MdeModulePkg: Fixup MAT Attributes After Splitting EFI Memory Map (groups.io)<https://edk2.groups.io/g/devel/message/117889>

-Taylor
On 4/15/2024 6:17 PM, Taylor Beebe wrote:
On 4/15/2024 3:57 AM, Bi, Dandan wrote:

Hi Taylor,



With this patch, MAT contains some entries with Attribute - 0x8000000000000000, doesn't have EFI_MEMORY_RO or EFI_MEMORY_XP.

After revert this patch, don't see such entries in MAT.



a. MAT with this patch:

Entry (0x609E4268)

  Type              - 0x5

  PhysicalStart     - 0x00000000769CF000

  VirtualStart      - 0x0000000000000000

  NumberOfPages     - 0x0000000000000016

  Attribute         - 0x8000000000000000

Entry (0x609E4298)

  Type              - 0x5

  PhysicalStart     - 0x00000000769E5000

  VirtualStart      - 0x0000000000000000

  NumberOfPages     - 0x0000000000000001

  Attribute         - 0x8000000000004000

Entry (0x609E42C8)

  Type              - 0x5

  PhysicalStart     - 0x00000000769E6000

  VirtualStart      - 0x0000000000000000

  NumberOfPages     - 0x0000000000000002

  Attribute         - 0x8000000000020000



b. MAT without this patch:

Entry (0x609E4268)

  Type              - 0x5

  PhysicalStart     - 0x00000000769CF000

  VirtualStart      - 0x0000000000000000

  NumberOfPages     - 0x0000000000000017

  Attribute         - 0x8000000000004000

Entry (0x609E4298)

  Type              - 0x5

  PhysicalStart     - 0x00000000769E6000

  VirtualStart      - 0x0000000000000000

  NumberOfPages     - 0x0000000000000002

  Attribute         - 0x8000000000020000



1. For example, when OldRecord in old memory map with:

        Type - 0x00000005

        Attribute - 0x800000000000000F

        PhysicalStart - 0x769CF000

    PhysicalStart is smaller than ImageBase 0x769E5000, with this patch, it will create a new memory descriptor entry for range 0x769CF000~0x769E5000 and without EFI_MEMORY_RO or EFI_MEMORY_XP Attribute.

    Then it will only contain EFI_MEMORY_RUNTIME Attribute in MAT as doing  MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME); when install MAT.

    It seems not aligned with UEFI Spec " The only valid bits for Attribute field currently are EFI_MEMORY_RO ,EFI_MEMORY_XP , plus EFI_MEMORY_RUNTIME "?

    Could you please help double check? Thanks.
Agreed that this is currently the behaviour and that the range should have a restrictive access attribute. More below.

2. In function SetNewRecord, it semes already cover the DATA entry before the CODE and the DATA entry after the CODE.

    And old SplitRecord function without this patch, also has the entry to cover the reaming range of this record if no more image covered by this range.

    Why do we still need this patch? Could you please help explain? Thanks.

GetMemoryMap() will merge adjacent descriptors which have the same type and attributes. This means that a single EfiRuntimeServicesCode descriptor within the memory map returned by CoreGetMemoryMap() could describe memory with the following layout (NOTE: this layout is odd but needs to be handled to fulfill the SplitTable() contract):
-------------------------
Some EfiRuntimeServicesCode memory
-------------------------
Runtime Image DATA Section
-------------------------
Runtime Image CODE Section
-------------------------
Runtime Image DATA Section
-------------------------
Some EfiRuntimeServicesCode memory
-------------------------

In this possible layout, the pre-patch logic would assume that the regions before and after the image were part of the image's data sections and would mark them as EFI_MEMORY_XP. The post-patch logic does not mark them with any access attributes which is fine but the DXE MAT logic needs to walk the memory map returned by SplitTable() to add access attributes to runtime regions which don't have any.

In your example, because PhysicalStart < ImageBase and 0769CF000-0x769E5000 is EfiRuntimeServicesCode, the access attribute should technically be EFI_MEMORY_RO. It's likely that 0769CF000-0x769E5000 is just the unused memory bucket and so it might be best to mark it both EFI_MEMORY_RO and EFI_MEMORY_XP.

An open question to the community: Are there cases where runtime executable code is in a buffer separate from a loaded runtime image? Can the EfiRuntimeServicesCode memory regions not part of an image be specified in the MAT as both EFI_MEMORY_RO and EFI_MEMORY_XP, or even dropped entirely?
Thanks :)
-Taylor



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117921): https://edk2.groups.io/g/devel/message/117921
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



[-- Attachment #2: Type: text/html, Size: 11973 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-17 14:04               ` Huang, Yanbo
@ 2024-04-17 23:53                 ` Taylor Beebe
  2024-04-18 13:02                   ` Dandan Bi
  0 siblings, 1 reply; 33+ messages in thread
From: Taylor Beebe @ 2024-04-17 23:53 UTC (permalink / raw)
  To: Huang, Yanbo, devel@edk2.groups.io, Bi, Dandan
  Cc: Wang, Jian J, Gao, Liming, Zhou, Jianfeng

[-- Attachment #1: Type: text/plain, Size: 1769 bytes --]

Hi Yanbo,

I didn't do it in the way you suggest for the same reason that the 
SplitTable() logic doesn't set attributes
on descriptors of type EfiRuntimeServicesData or other memory types. The 
purpose of the SplitTable() function
is to use the input image records to split descriptors so each image 
section has it's own descriptor. I think
it's reasonable to set the attributes on descriptors associated with 
images because those new descriptors are the
intended side effect of the function, but I don't think setting 
attributes on other descriptors is a good design pattern.
This pattern matches what's done in PiSmmCore/MemoryAttributesTable.c. 
Also, even if we did
it the way you suggest, we would still need call 
EnforceMemoryMapAttribute() later to set XP on the
EfiRuntimeServicesData descriptors.

Can you or Dandan explain the origin of the extra EfiRuntimeServicesCode 
regions which aren't
part of loaded runtime images? It would be a good datapoint for our 
discussion on the proposed fix.

-Taylor
On 4/17/2024 7:04 AM, Huang, Yanbo wrote:
>
> Hi Taylor,
>
> Thanks for your update.
>
> After test, issue can be fixed by your patch.
>
> But why we not set the EFI_MEMORY_XP or EFI_MEMORY_RO attribute in 
> SplitRecord API?
>
> If we set the attribute in the beginning of the NewRecord created, it 
> seems we don’t need to EnforceMemoryMapAttribute later?
>
> Best Regards,
>
> Yanbo Huang
>


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117937): https://edk2.groups.io/g/devel/message/117937
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



[-- Attachment #2: Type: text/html, Size: 4755 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-17 23:53                 ` Taylor Beebe
@ 2024-04-18 13:02                   ` Dandan Bi
  2024-04-18 13:17                     ` Ard Biesheuvel
  0 siblings, 1 reply; 33+ messages in thread
From: Dandan Bi @ 2024-04-18 13:02 UTC (permalink / raw)
  To: Taylor Beebe, Huang, Yanbo, devel@edk2.groups.io
  Cc: Wang, Jian J, Gao, Liming, Zhou, Jianfeng, Bi, Dandan

[-- Attachment #1: Type: text/plain, Size: 3336 bytes --]

Hi Taylor,

>>Extra EfiRuntimeServicesCode regions which aren't part of loaded runtime images.
This may be related to the original size of EfiRuntimeServicesCode in memory map, and the size can be configured via PcdPlatformEfiRtCodeMemorySize.

If the size is large enough to hold all the runtime images and still has some remaining regions, then these regions are with EfiRuntimeServicesCode type and aren't part of loaded runtime images, right?
Pre-change https://github.com/tianocore/edk2/commit/e2f2bbe208b4c7ebcedacfc8333df1e52cbf07eb, such EfiRuntimeServicesCode regions are set with EFI_MEMORY_XP attribute.
Post-change https://github.com/tianocore/edk2/commit/e2f2bbe208b4c7ebcedacfc8333df1e52cbf07eb,  these regions don’t have any access attribute.
And now this patch [PATCH v1] MdeModulePkg: Fixup MAT Attributes After Splitting EFI Memory Map (groups.io)<https://edk2.groups.io/g/devel/message/117889> set these regions with EFI_MEMORY_RO.
I am not sure which attribute should be set for these regions.  And old codes with EFI_MEMORY_XP attribute for a long time and seems not cause any issue.


Thanks,
Dandan
From: Taylor Beebe <taylor.d.beebe@gmail.com>
Sent: Thursday, April 18, 2024 7:54 AM
To: Huang, Yanbo <yanbo.huang@intel.com>; devel@edk2.groups.io; Bi, Dandan <dandan.bi@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Zhou, Jianfeng <jianfeng.zhou@intel.com>
Subject: Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows


Hi Yanbo,
I didn't do it in the way you suggest for the same reason that the SplitTable() logic doesn't set attributes
on descriptors of type EfiRuntimeServicesData or other memory types. The purpose of the SplitTable() function
is to use the input image records to split descriptors so each image section has it's own descriptor. I think
it's reasonable to set the attributes on descriptors associated with images because those new descriptors are the
intended side effect of the function, but I don't think setting attributes on other descriptors is a good design pattern.
This pattern matches what's done in PiSmmCore/MemoryAttributesTable.c. Also, even if we did
it the way you suggest, we would still need call EnforceMemoryMapAttribute() later to set XP on the
EfiRuntimeServicesData descriptors.

Can you or Dandan explain the origin of the extra  EfiRuntimeServicesCode regions which aren't
part of loaded runtime images? It would be a good datapoint for our discussion on the proposed fix.

-Taylor
On 4/17/2024 7:04 AM, Huang, Yanbo wrote:
Hi Taylor,

Thanks for your update.
After test, issue can be fixed by your patch.
But why we not set the EFI_MEMORY_XP or EFI_MEMORY_RO attribute in SplitRecord API?
If we set the attribute in the beginning of the NewRecord created, it seems we don’t need to EnforceMemoryMapAttribute later?

Best Regards,
Yanbo Huang


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117989): https://edk2.groups.io/g/devel/message/117989
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



[-- Attachment #2: Type: text/html, Size: 7399 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-18 13:02                   ` Dandan Bi
@ 2024-04-18 13:17                     ` Ard Biesheuvel
  2024-04-18 13:56                       ` Huang, Yanbo
  0 siblings, 1 reply; 33+ messages in thread
From: Ard Biesheuvel @ 2024-04-18 13:17 UTC (permalink / raw)
  To: devel, dandan.bi
  Cc: Taylor Beebe, Huang, Yanbo, Wang, Jian J, Gao, Liming,
	Zhou, Jianfeng

Hello Dandan,

On Thu, 18 Apr 2024 at 15:03, Dandan Bi <dandan.bi@intel.com> wrote:
>
> Hi Taylor,
>
>
>
> >>Extra EfiRuntimeServicesCode regions which aren't part of loaded runtime images.
>
> This may be related to the original size of EfiRuntimeServicesCode in memory map, and the size can be configured via PcdPlatformEfiRtCodeMemorySize.
>

That PCD does not exist in EDK2. Can you explain what it does on your platform?


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117990): https://edk2.groups.io/g/devel/message/117990
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-18 13:17                     ` Ard Biesheuvel
@ 2024-04-18 13:56                       ` Huang, Yanbo
  2024-04-18 14:21                         ` Oliver Smith-Denny
  0 siblings, 1 reply; 33+ messages in thread
From: Huang, Yanbo @ 2024-04-18 13:56 UTC (permalink / raw)
  To: Ard Biesheuvel, devel@edk2.groups.io, Bi, Dandan
  Cc: Taylor Beebe, Wang, Jian J, Gao, Liming, Zhou, Jianfeng

The PCD PcdPlatformEfiRtCodeMemorySize is used in https://github.com/tianocore/edk2-platforms/blob/master/Platform/Intel/MinPlatformPkg/PlatformInit/PlatformInitPei/PlatformInitPreMem.c
This PCD seems defined the size allocated for run time services code, and the similar PCD is PcdPlatformEfiRtDataMemorySize, seems defined the size allocated for run time services data.
I guess dandan means if the runtime services code size is small than the PCD defined, then the " Extra EfiRuntimeServicesCode regions which aren't part of loaded runtime images." size should be FixedPcdGet32 (PcdPlatformEfiRtCodeMemorySize) - the actual runtime image code size?

Best Regards,
Yanbo Huang
-----Original Message-----
From: Ard Biesheuvel <ardb@kernel.org> 
Sent: Thursday, April 18, 2024 9:18 PM
To: devel@edk2.groups.io; Bi, Dandan <dandan.bi@intel.com>
Cc: Taylor Beebe <taylor.d.beebe@gmail.com>; Huang, Yanbo <yanbo.huang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Zhou, Jianfeng <jianfeng.zhou@intel.com>
Subject: Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows

Hello Dandan,

On Thu, 18 Apr 2024 at 15:03, Dandan Bi <dandan.bi@intel.com> wrote:
>
> Hi Taylor,
>
>
>
> >>Extra EfiRuntimeServicesCode regions which aren't part of loaded runtime images.
>
> This may be related to the original size of EfiRuntimeServicesCode in memory map, and the size can be configured via PcdPlatformEfiRtCodeMemorySize.
>

That PCD does not exist in EDK2. Can you explain what it does on your platform?


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117992): https://edk2.groups.io/g/devel/message/117992
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-18 13:56                       ` Huang, Yanbo
@ 2024-04-18 14:21                         ` Oliver Smith-Denny
  2024-04-19  6:43                           ` Ni, Ray
  0 siblings, 1 reply; 33+ messages in thread
From: Oliver Smith-Denny @ 2024-04-18 14:21 UTC (permalink / raw)
  To: devel, yanbo.huang, Ard Biesheuvel, Bi, Dandan
  Cc: Taylor Beebe, Wang, Jian J, Gao, Liming, Zhou, Jianfeng

On 4/18/2024 6:56 AM, Huang, Yanbo wrote:
> The PCD PcdPlatformEfiRtCodeMemorySize is used in https://github.com/tianocore/edk2-platforms/blob/master/Platform/Intel/MinPlatformPkg/PlatformInit/PlatformInitPei/PlatformInitPreMem.c
> This PCD seems defined the size allocated for run time services code, and the similar PCD is PcdPlatformEfiRtDataMemorySize, seems defined the size allocated for run time services data.
> I guess dandan means if the runtime services code size is small than the PCD defined, then the " Extra EfiRuntimeServicesCode regions which aren't part of loaded runtime images." size should be FixedPcdGet32 (PcdPlatformEfiRtCodeMemorySize) - the actual runtime image code size?
> 

Drawing the lines here, we will lie in the EFI_MEMORY_MAP to say that
all bin memory is allocated, regardless of this PCD:

https://github.com/tianocore/edk2/blob/0afb8743493853e30171f6000de51242e22a1eb8/MdeModulePkg/Core/Dxe/Mem/Page.c#L1973-L1989

So this is just junk unallocated memory that we are reporting as
a type it *could* be if an allocation occurs to minimize failures
of ExitBootServices. Which is questionable. But in terms of
attributes, I would expect we either have this unallocated
memory marked the same as the bin type or better, mark it RP
if we can (Taylor is making a change to set RP on free memory
by default, so we would have this in the page table, but we
would need to decide what we tell the OS).

Going back to the questionableness of this: can we not report
the entire bin as allocated memory to the OS? I understand
what the comment is saying; I don't like that we will lie to
the OS and reserve larger chunks of runtime memory than we
actually need and that will get the wrong permissions set on
it (for example making this garbage data be executable).

Thanks,
Oliver


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117994): https://edk2.groups.io/g/devel/message/117994
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-18 14:21                         ` Oliver Smith-Denny
@ 2024-04-19  6:43                           ` Ni, Ray
  2024-04-23 14:33                             ` Oliver Smith-Denny
  0 siblings, 1 reply; 33+ messages in thread
From: Ni, Ray @ 2024-04-19  6:43 UTC (permalink / raw)
  To: devel@edk2.groups.io, Huang, Yanbo, Ard Biesheuvel, Bi, Dandan,
	osde@linux.microsoft.com
  Cc: Taylor Beebe, Wang, Jian J, Gao, Liming, Zhou, Jianfeng

[-- Attachment #1: Type: text/plain, Size: 1362 bytes --]



So this is just junk unallocated memory that we are reporting as
a type it *could* be if an allocation occurs to minimize failures
of ExitBootServices. Which is questionable. But in terms of
attributes, I would expect we either have this unallocated
memory marked the same as the bin type or better, mark it RP
if we can (Taylor is making a change to set RP on free memory
by default, so we would have this in the page table, but we
would need to decide what we tell the OS).

[Ray] When reviewing today's logic of memory protection through page table, I feel that it was designed improperly in the beginning.
My rough thought is:
* All memory is RP initially (as you said Taylor will do that)
* Allocated memory is mapped as either RO or XD, depending on code/data. Or RP if it's a guard page.

Maybe I am not aware of some limitations of the above idea. The limitations prevented the initial design be in this way.
Or what Taylor will do aligns to the idea?

Thanks,
Ray


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118006): https://edk2.groups.io/g/devel/message/118006
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



[-- Attachment #2: Type: text/html, Size: 3077 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows
  2024-04-19  6:43                           ` Ni, Ray
@ 2024-04-23 14:33                             ` Oliver Smith-Denny
  0 siblings, 0 replies; 33+ messages in thread
From: Oliver Smith-Denny @ 2024-04-23 14:33 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io, Huang, Yanbo, Ard Biesheuvel,
	Bi, Dandan
  Cc: Taylor Beebe, Wang, Jian J, Gao, Liming, Zhou, Jianfeng

On 4/18/2024 11:43 PM, Ni, Ray wrote:
> 
> 
> So this is just junk unallocated memory that we are reporting as
> a type it *could* be if an allocation occurs to minimize failures
> of ExitBootServices. Which is questionable. But in terms of
> attributes, I would expect we either have this unallocated
> memory marked the same as the bin type or better, mark it RP
> if we can (Taylor is making a change to set RP on free memory
> by default, so we would have this in the page table, but we
> would need to decide what we tell the OS).
> 
> [Ray] When reviewing today's logic of memory protection through page 
> table, I feel that it was designed improperly in the beginning.
> My rough thought is:
> * All memory is RP initially (as you said Taylor will do that)

Correct, Taylor is working on a change here and actually taking this a
step further, that all free memory will be RP, to catch any use after
free and keep a safer environment.

> * Allocated memory is mapped as either RO or XD, depending on code/data. 
> Or RP if it's a guard page.

This is mostly true, of course it depends on how the memory protections
are configured. I would like to see this go to not being an option but
something that DxeCore enforces by default depending on memory type
allocated.

> 
> Maybe I am not aware of some limitations of the above idea. The 
> limitations prevented the initial design be in this way.
> Or what Taylor will do aligns to the idea?
> 

The issue in this mailing thread is not what DXE's page tables are,
but what get reported in the MAT to the OS. Before Taylor's change
to improve the SplitTable logic the extra RuntimeServicesCode sections
that get reported to the OS (these are the leftover sections in the
memory bins to improve the chance for S4 resume) were getting reported
as XP. Taylor is proposing these get marked RO instead as they are
marked as Code sections (although they really hold junk in them).

Another path would be can we mark them both RO and XP. These are junk
sections, they should not be used and definitely not executed from. We
only report them to the OS so that our memory map changes less between
boots (I also wonder if there are better ways we can do this, but I'll
have to think about this more).

Thanks,
Oliver




-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118143): https://edk2.groups.io/g/devel/message/118143
Mute This Topic: https://groups.io/mt/105477564/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2024-04-23 14:33 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-27 18:17 [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Taylor Beebe
2023-11-27 18:17 ` [edk2-devel] [PATCH v5 01/16] MdeModulePkg: Add ImagePropertiesRecordLib Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 02/16] ArmVirtPkg: Add ImagePropertiesRecordLib Instance Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 03/16] EmulatorPkg: " Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 04/16] OvmfPkg: " Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 05/16] UefiPayloadPkg: " Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 06/16] MdeModulePkg: Update MemoryAttributesTable.c to Reduce Global Variable Use Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 07/16] MdeModulePkg: Move Some DXE MAT Logic to ImagePropertiesRecordLib Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 08/16] MdeModulePkg: Add ImagePropertiesRecordLib Host-Based Unit Test Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 09/16] MdeModulePkg: Fix MAT Descriptor Count Calculation Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 10/16] MdeModulePkg: Fix MAT SplitRecord() Logic Taylor Beebe
2024-04-12  5:14   ` [edk2-devel] MdeModulePkg: Fix MAT SplitRecord() Logic introduce one bug and will cause SUT reset when boot to windows Huang, Yanbo
2024-04-12 15:09     ` Taylor Beebe
2024-04-14 14:35       ` Huang, Yanbo
2024-04-15 10:57         ` Dandan Bi
2024-04-16  1:17           ` Taylor Beebe
2024-04-17  2:32             ` Taylor Beebe
2024-04-17 14:04               ` Huang, Yanbo
2024-04-17 23:53                 ` Taylor Beebe
2024-04-18 13:02                   ` Dandan Bi
2024-04-18 13:17                     ` Ard Biesheuvel
2024-04-18 13:56                       ` Huang, Yanbo
2024-04-18 14:21                         ` Oliver Smith-Denny
2024-04-19  6:43                           ` Ni, Ray
2024-04-23 14:33                             ` Oliver Smith-Denny
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 11/16] MdeModulePkg: Fix MAT SplitTable() Logic Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 12/16] MdeModulePkg: Add NULL checks and Return Status to ImagePropertiesRecordLib Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 13/16] UefiCpuPkg: Use Attribute From SMM MemoryAttributesTable if Nonzero Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 14/16] MdeModulePkg: Transition SMM MAT Logic to Use ImagePropertiesRecordLib Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 15/16] MdeModulePkg: Add Logic to Create/Delete Image Properties Records Taylor Beebe
2023-11-27 18:18 ` [edk2-devel] [PATCH v5 16/16] MdeModulePkg: Update DumpImageRecord() in ImagePropertiesRecordLib Taylor Beebe
2023-11-27 18:40 ` [edk2-devel] [PATCH v5 00/16] Add ImagePropertiesRecordLib and Fix MAT Bugs​ Ard Biesheuvel
2023-11-28 10:22   ` Ni, Ray

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox