* [PATCH v2 1/6] MdeModulePkg/MdeModulePkg.dec: Add NULL pointer detection PCD
2017-09-21 5:20 ` [PATCH v2 0/6] Add NULL pointer detection feature Jian J Wang
@ 2017-09-21 5:20 ` Jian J Wang
2017-09-25 8:01 ` Zeng, Star
2017-09-21 5:20 ` [PATCH v2 2/6] MdeModulePkg/DxeIpl: Implement NULL pointer detection Jian J Wang
` (4 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Jian J Wang @ 2017-09-21 5:20 UTC (permalink / raw)
To: edk2-devel
Cc: Wang, Jian J, Star Zeng, Eric Dong, Laszlo Ersek, Jiewen Yao,
Michael Kinney, Jordan Justen, Ayellet Wolman
From: "Wang, Jian J" <jian.j.wang@intel.com>
PCD PcdNullPointerDetectionPropertyMask is a bitmask used to control the
NULL address detection functionality in code for different phases.
If enabled, accessing NULL address in UEFI or SMM code can be caught
as a page fault exception.
BIT0 - Enable NULL pointer detection for UEFI.
BIT1 - Enable NULL pointer detection for SMM.
BIT2..6 - Reserved for future uses.
BIT7 - Disable NULL pointer detection just after EndOfDxe. This is a
workaround for those unsolvable NULL access issues in
OptionROM, boot loader, etc. It can also help to avoid
unnecessary exception caused by legacy memory (0-4095) access
after EndOfDxe, such as Windows 7 boot on Qemu.
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ayellet Wolman <ayellet.wolman@intel.com>
Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
---
MdeModulePkg/MdeModulePkg.dec | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 403a66a5ad..3f90b8d7e6 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -863,6 +863,19 @@
# @ValidList 0x80000006 | 0x03058002
gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|UINT32|0x30001040
+ ## Mask to control the NULL address detection in code for different phases.
+ # If enabled, accessing NULL address in UEFI or SMM code can be caught.<BR><BR>
+ # BIT0 - Enable NULL pointer detection for UEFI.<BR>
+ # BIT1 - Enable NULL pointer detection for SMM.<BR>
+ # BIT2..6 - Reserved for future uses.<BR>
+ # BIT7 - Disable NULL pointer detection just after EndOfDxe. <BR>
+ # This is a workaround for those unsolvable NULL access issues in
+ # OptionROM, boot loader, etc. It can also help to avoid unnecessary
+ # exception caused by legacy memory (0-4095) access after EndOfDxe,
+ # such as Windows 7 boot on Qemu.<BR>
+ # @Prompt Enable NULL address detection.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask|0x0|UINT8|0x30001050
+
[PcdsFixedAtBuild, PcdsPatchableInModule]
## Dynamic type PCD can be registered callback function for Pcd setting action.
# PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of callback function
--
2.14.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/6] MdeModulePkg/MdeModulePkg.dec: Add NULL pointer detection PCD
2017-09-21 5:20 ` [PATCH v2 1/6] MdeModulePkg/MdeModulePkg.dec: Add NULL pointer detection PCD Jian J Wang
@ 2017-09-25 8:01 ` Zeng, Star
2017-09-25 8:25 ` Wang, Jian J
0 siblings, 1 reply; 14+ messages in thread
From: Zeng, Star @ 2017-09-25 8:01 UTC (permalink / raw)
To: Wang, Jian J, edk2-devel@lists.01.org
Cc: Dong, Eric, Laszlo Ersek, Yao, Jiewen, Kinney, Michael D,
Justen, Jordan L, Wolman, Ayellet, Zeng, Star, Gao, Liming
You may need also add PcdNullPointerDetectionPropertyMask prompt and help into the MdeModulePkg.uni.
Thanks,
Star
-----Original Message-----
From: Wang, Jian J
Sent: Thursday, September 21, 2017 1:20 PM
To: edk2-devel@lists.01.org
Cc: Wang, Jian J <jian.j.wang@intel.com>; Zeng, Star <star.zeng@intel.com>; Dong, Eric <eric.dong@intel.com>; Laszlo Ersek <lersek@redhat.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
Subject: [PATCH v2 1/6] MdeModulePkg/MdeModulePkg.dec: Add NULL pointer detection PCD
From: "Wang, Jian J" <jian.j.wang@intel.com>
PCD PcdNullPointerDetectionPropertyMask is a bitmask used to control the NULL address detection functionality in code for different phases.
If enabled, accessing NULL address in UEFI or SMM code can be caught as a page fault exception.
BIT0 - Enable NULL pointer detection for UEFI.
BIT1 - Enable NULL pointer detection for SMM.
BIT2..6 - Reserved for future uses.
BIT7 - Disable NULL pointer detection just after EndOfDxe. This is a
workaround for those unsolvable NULL access issues in
OptionROM, boot loader, etc. It can also help to avoid
unnecessary exception caused by legacy memory (0-4095) access
after EndOfDxe, such as Windows 7 boot on Qemu.
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ayellet Wolman <ayellet.wolman@intel.com>
Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
---
MdeModulePkg/MdeModulePkg.dec | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 403a66a5ad..3f90b8d7e6 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -863,6 +863,19 @@
# @ValidList 0x80000006 | 0x03058002
gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|UINT32|0x30001040
+ ## Mask to control the NULL address detection in code for different phases.
+ # If enabled, accessing NULL address in UEFI or SMM code can be caught.<BR><BR>
+ # BIT0 - Enable NULL pointer detection for UEFI.<BR>
+ # BIT1 - Enable NULL pointer detection for SMM.<BR>
+ # BIT2..6 - Reserved for future uses.<BR>
+ # BIT7 - Disable NULL pointer detection just after EndOfDxe. <BR>
+ # This is a workaround for those unsolvable NULL access issues in
+ # OptionROM, boot loader, etc. It can also help to avoid unnecessary
+ # exception caused by legacy memory (0-4095) access after EndOfDxe,
+ # such as Windows 7 boot on Qemu.<BR>
+ # @Prompt Enable NULL address detection.
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask|0x0
+ |UINT8|0x30001050
+
[PcdsFixedAtBuild, PcdsPatchableInModule]
## Dynamic type PCD can be registered callback function for Pcd setting action.
# PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of callback function
--
2.14.1.windows.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/6] MdeModulePkg/MdeModulePkg.dec: Add NULL pointer detection PCD
2017-09-25 8:01 ` Zeng, Star
@ 2017-09-25 8:25 ` Wang, Jian J
0 siblings, 0 replies; 14+ messages in thread
From: Wang, Jian J @ 2017-09-25 8:25 UTC (permalink / raw)
To: Zeng, Star, edk2-devel@lists.01.org
Cc: Dong, Eric, Laszlo Ersek, Yao, Jiewen, Kinney, Michael D,
Justen, Jordan L, Wolman, Ayellet, Gao, Liming
Sure. Thanks for the feedback.
> -----Original Message-----
> From: Zeng, Star
> Sent: Monday, September 25, 2017 4:01 PM
> To: Wang, Jian J <jian.j.wang@intel.com>; edk2-devel@lists.01.org
> Cc: Dong, Eric <eric.dong@intel.com>; Laszlo Ersek <lersek@redhat.com>; Yao,
> Jiewen <jiewen.yao@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>;
> Wolman, Ayellet <ayellet.wolman@intel.com>; Zeng, Star
> <star.zeng@intel.com>; Gao, Liming <liming.gao@intel.com>
> Subject: RE: [PATCH v2 1/6] MdeModulePkg/MdeModulePkg.dec: Add NULL
> pointer detection PCD
>
> You may need also add PcdNullPointerDetectionPropertyMask prompt and help
> into the MdeModulePkg.uni.
>
>
> Thanks,
> Star
> -----Original Message-----
> From: Wang, Jian J
> Sent: Thursday, September 21, 2017 1:20 PM
> To: edk2-devel@lists.01.org
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Zeng, Star <star.zeng@intel.com>;
> Dong, Eric <eric.dong@intel.com>; Laszlo Ersek <lersek@redhat.com>; Yao,
> Jiewen <jiewen.yao@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>;
> Wolman, Ayellet <ayellet.wolman@intel.com>
> Subject: [PATCH v2 1/6] MdeModulePkg/MdeModulePkg.dec: Add NULL pointer
> detection PCD
>
> From: "Wang, Jian J" <jian.j.wang@intel.com>
>
> PCD PcdNullPointerDetectionPropertyMask is a bitmask used to control the
> NULL address detection functionality in code for different phases.
>
> If enabled, accessing NULL address in UEFI or SMM code can be caught as a
> page fault exception.
>
> BIT0 - Enable NULL pointer detection for UEFI.
> BIT1 - Enable NULL pointer detection for SMM.
> BIT2..6 - Reserved for future uses.
> BIT7 - Disable NULL pointer detection just after EndOfDxe. This is a
> workaround for those unsolvable NULL access issues in
> OptionROM, boot loader, etc. It can also help to avoid
> unnecessary exception caused by legacy memory (0-4095) access
> after EndOfDxe, such as Windows 7 boot on Qemu.
>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Michael Kinney <michael.d.kinney@intel.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ayellet Wolman <ayellet.wolman@intel.com>
> Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
> ---
> MdeModulePkg/MdeModulePkg.dec | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec index 403a66a5ad..3f90b8d7e6 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -863,6 +863,19 @@
> # @ValidList 0x80000006 | 0x03058002
>
> gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|UIN
> T32|0x30001040
>
> + ## Mask to control the NULL address detection in code for different phases.
> + # If enabled, accessing NULL address in UEFI or SMM code can be
> caught.<BR><BR>
> + # BIT0 - Enable NULL pointer detection for UEFI.<BR>
> + # BIT1 - Enable NULL pointer detection for SMM.<BR>
> + # BIT2..6 - Reserved for future uses.<BR>
> + # BIT7 - Disable NULL pointer detection just after EndOfDxe. <BR>
> + # This is a workaround for those unsolvable NULL access issues in
> + # OptionROM, boot loader, etc. It can also help to avoid unnecessary
> + # exception caused by legacy memory (0-4095) access after EndOfDxe,
> + # such as Windows 7 boot on Qemu.<BR>
> + # @Prompt Enable NULL address detection.
> +
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask|0x0
> + |UINT8|0x30001050
> +
> [PcdsFixedAtBuild, PcdsPatchableInModule]
> ## Dynamic type PCD can be registered callback function for Pcd setting action.
> # PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number
> of callback function
> --
> 2.14.1.windows.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 2/6] MdeModulePkg/DxeIpl: Implement NULL pointer detection
2017-09-21 5:20 ` [PATCH v2 0/6] Add NULL pointer detection feature Jian J Wang
2017-09-21 5:20 ` [PATCH v2 1/6] MdeModulePkg/MdeModulePkg.dec: Add NULL pointer detection PCD Jian J Wang
@ 2017-09-21 5:20 ` Jian J Wang
2017-09-25 8:50 ` Yao, Jiewen
2017-09-21 5:20 ` [PATCH v2 3/6] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM code Jian J Wang
` (3 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Jian J Wang @ 2017-09-21 5:20 UTC (permalink / raw)
To: edk2-devel
Cc: Star Zeng, Eric Dong, Laszlo Ersek, Jiewen Yao, Michael Kinney,
Jordan Justen, Ayellet Wolman
NULL pointer detection is done by making use of paging mechanism of CPU.
During page table setup, if enabled, the first 4-K page (0-4095) will be
marked as NOT PRESENT. Any code which unintentionally access memory between
0-4095 will trigger a Page Fault exception which warns users that there's
potential illegal code in BIOS.
This also means that legacy code which has to access memory between 0-4095
should be cautious to temporarily disable this feature before the access
and re-enable it afterwards; or disalbe this feature at all.
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ayellet Wolman <ayellet.wolman@intel.com>
Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
---
MdeModulePkg/Core/DxeIplPeim/DxeIpl.h | 25 +++++++++
MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 1 +
MdeModulePkg/Core/DxeIplPeim/DxeLoad.c | 65 ++++++++++++++++++++++++
MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c | 11 +++-
MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c | 2 +
MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 31 ++++++++---
6 files changed, 126 insertions(+), 9 deletions(-)
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
index 72d2532f50..1654bcd2dc 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
@@ -240,4 +240,29 @@ Decompress (
OUT UINTN *OutputSize
);
+/**
+ Clear legacy memory located at the first 4K-page.
+
+ This function traverses the whole HOB list to check if memory from 0 to 4095
+ exists and has not been allocated, and then clear it if so.
+
+ @param HoStart The start of HobList passed to DxeCore.
+
+**/
+VOID
+ClearLegacyMemory (
+ IN VOID *HobStart
+ );
+
+/**
+ Return configure status of NULL pointer detection feature
+
+ @return TRUE NULL pointer detection feature is enabled
+ @return FALSE NULL pointer detection feature is disabled
+**/
+BOOLEAN
+IsNullDetectionEnabled (
+ VOID
+ );
+
#endif
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
index c54afe4aa6..9d0e76a293 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
@@ -115,6 +115,7 @@
[Pcd.IA32,Pcd.X64]
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES
[Pcd.IA32,Pcd.X64,Pcd.ARM,Pcd.AARCH64]
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
index 50b5440d15..0a71b1f3de 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
@@ -825,3 +825,68 @@ UpdateStackHob (
Hob.Raw = GET_NEXT_HOB (Hob);
}
}
+
+/**
+ Clear legacy memory located at the first 4K-page, if available.
+
+ This function traverses the whole HOB list to check if memory from 0 to 4095
+ exists and has not been allocated, and then clear it if so.
+
+ @param HoStart The start of HobList passed to DxeCore.
+
+**/
+VOID
+ClearLegacyMemory (
+ IN VOID *HobStart
+ )
+{
+ EFI_PEI_HOB_POINTERS RscHob;
+ EFI_PEI_HOB_POINTERS MemHob;
+ BOOLEAN DoClear;
+
+ RscHob.Raw = HobStart;
+ MemHob.Raw = HobStart;
+ DoClear = FALSE;
+
+ //
+ // Check if page 0 exists and free
+ //
+ while ((RscHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
+ RscHob.Raw)) != NULL) {
+ if (RscHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
+ RscHob.ResourceDescriptor->PhysicalStart == 0) {
+ DoClear = TRUE;
+ //
+ // Make sure memory at 0-4095 has not been allocated.
+ //
+ while ((MemHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION,
+ MemHob.Raw)) != NULL) {
+ if (MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress
+ < EFI_PAGE_SIZE) {
+ DoClear = FALSE;
+ break;
+ }
+ MemHob.Raw = GET_NEXT_HOB (MemHob);
+ }
+ break;
+ }
+ RscHob.Raw = GET_NEXT_HOB (RscHob);
+ }
+
+ if (DoClear) {
+ DEBUG ((DEBUG_INFO, "Clearing first 4K-page!\r\n"));
+ SetMem (NULL, EFI_PAGE_SIZE, 0);
+ }
+
+ return;
+}
+
+BOOLEAN
+IsNullDetectionEnabled (
+ VOID
+ )
+{
+ return (((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) != 0) ?
+ TRUE : FALSE);
+}
+
diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
index 1957326caf..503cf88382 100644
--- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
+++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
@@ -123,7 +123,9 @@ Create4GPageTablesIa32Pae (
PageDirectoryPointerEntry->Bits.Present = 1;
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {
- if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase)) {
+ if ((IsNullDetectionEnabled () && PhysicalAddress == 0)
+ || ((PhysicalAddress < StackBase + StackSize)
+ && ((PhysicalAddress + SIZE_2MB) > StackBase))) {
//
// Need to split this 2M page that covers stack range.
//
@@ -240,6 +242,8 @@ HandOffToDxeCore (
EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
BOOLEAN BuildPageTablesIa32Pae;
+ ClearLegacyMemory (HobList.Raw);
+
Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);
ASSERT_EFI_ERROR (Status);
@@ -379,7 +383,10 @@ HandOffToDxeCore (
TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
PageTables = 0;
- BuildPageTablesIa32Pae = (BOOLEAN) (PcdGetBool (PcdSetNxForStack) && IsIa32PaeSupport () && IsExecuteDisableBitAvailable ());
+ BuildPageTablesIa32Pae = (BOOLEAN) (IsIa32PaeSupport ()
+ && IsExecuteDisableBitAvailable ()
+ && (PcdGetBool (PcdSetNxForStack)
+ || IsNullDetectionEnabled ()));
if (BuildPageTablesIa32Pae) {
PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE);
EnableExecuteDisableBit ();
diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
index 6488880eab..d93a9c5a2d 100644
--- a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
+++ b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
@@ -42,6 +42,8 @@ HandOffToDxeCore (
EFI_VECTOR_HANDOFF_INFO *VectorInfo;
EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
+ ClearLegacyMemory (HobList.Raw);
+
//
// Get Vector Hand-off Info PPI and build Guided HOB
//
diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
index 48150be4e1..80c1821eca 100644
--- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
+++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
@@ -90,8 +90,16 @@ Split2MPageTo4K (
//
PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;
PageTableEntry->Bits.ReadWrite = 1;
- PageTableEntry->Bits.Present = 1;
- if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + StackSize)) {
+
+ if (IsNullDetectionEnabled () && PhysicalAddress4K == 0) {
+ PageTableEntry->Bits.Present = 0;
+ } else {
+ PageTableEntry->Bits.Present = 1;
+ }
+
+ if (PcdGetBool (PcdSetNxForStack)
+ && (PhysicalAddress4K >= StackBase)
+ && (PhysicalAddress4K < StackBase + StackSize)) {
//
// Set Nx bit for stack.
//
@@ -137,9 +145,12 @@ Split1GPageTo2M (
PhysicalAddress2M = PhysicalAddress;
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {
- if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + SIZE_2MB) > StackBase)) {
+ if ((IsNullDetectionEnabled () && PhysicalAddress2M == 0)
+ || (PcdGetBool (PcdSetNxForStack)
+ && (PhysicalAddress2M < StackBase + StackSize)
+ && ((PhysicalAddress2M + SIZE_2MB) > StackBase))) {
//
- // Need to split this 2M page that covers stack range.
+ // Need to split this 2M page that covers NULL or stack range.
//
Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);
} else {
@@ -279,7 +290,10 @@ CreateIdentityMappingPageTables (
PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
- if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_1GB) > StackBase)) {
+ if ((IsNullDetectionEnabled () && PageAddress == 0)
+ || (PcdGetBool (PcdSetNxForStack)
+ && (PageAddress < StackBase + StackSize)
+ && ((PageAddress + SIZE_1GB) > StackBase))) {
Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize);
} else {
//
@@ -308,9 +322,12 @@ CreateIdentityMappingPageTables (
PageDirectoryPointerEntry->Bits.Present = 1;
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {
- if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_2MB) > StackBase)) {
+ if ((IsNullDetectionEnabled () && PageAddress == 0)
+ || (PcdGetBool (PcdSetNxForStack)
+ && (PageAddress < StackBase + StackSize)
+ && ((PageAddress + SIZE_2MB) > StackBase))) {
//
- // Need to split this 2M page that covers stack range.
+ // Need to split this 2M page that covers NULL or stack range.
//
Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);
} else {
--
2.14.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/6] MdeModulePkg/DxeIpl: Implement NULL pointer detection
2017-09-21 5:20 ` [PATCH v2 2/6] MdeModulePkg/DxeIpl: Implement NULL pointer detection Jian J Wang
@ 2017-09-25 8:50 ` Yao, Jiewen
2017-09-26 0:54 ` Wang, Jian J
0 siblings, 1 reply; 14+ messages in thread
From: Yao, Jiewen @ 2017-09-25 8:50 UTC (permalink / raw)
To: Wang, Jian J, edk2-devel@lists.01.org
Cc: Zeng, Star, Dong, Eric, Laszlo Ersek, Kinney, Michael D,
Justen, Jordan L, Wolman, Ayellet
Hi
I do not think NULL pointer is related to NX.
As long as NullPointer PCD is true and IA32PAE is supported, we can build page table.
+ BuildPageTablesIa32Pae = (BOOLEAN) (IsIa32PaeSupport ()
+ && IsExecuteDisableBitAvailable ()
+ && (PcdGetBool (PcdSetNxForStack)
+ || IsNullDetectionEnabled ()));
> -----Original Message-----
> From: Wang, Jian J
> Sent: Thursday, September 21, 2017 1:20 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Dong, Eric <eric.dong@intel.com>; Laszlo
> Ersek <lersek@redhat.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney,
> Michael D <michael.d.kinney@intel.com>; Justen, Jordan L
> <jordan.l.justen@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
> Subject: [PATCH v2 2/6] MdeModulePkg/DxeIpl: Implement NULL pointer
> detection
>
> NULL pointer detection is done by making use of paging mechanism of CPU.
> During page table setup, if enabled, the first 4-K page (0-4095) will be
> marked as NOT PRESENT. Any code which unintentionally access memory
> between
> 0-4095 will trigger a Page Fault exception which warns users that there's
> potential illegal code in BIOS.
>
> This also means that legacy code which has to access memory between 0-4095
> should be cautious to temporarily disable this feature before the access
> and re-enable it afterwards; or disalbe this feature at all.
>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Michael Kinney <michael.d.kinney@intel.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ayellet Wolman <ayellet.wolman@intel.com>
> Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
> ---
> MdeModulePkg/Core/DxeIplPeim/DxeIpl.h | 25 +++++++++
> MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 1 +
> MdeModulePkg/Core/DxeIplPeim/DxeLoad.c | 65
> ++++++++++++++++++++++++
> MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c | 11 +++-
> MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c | 2 +
> MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 31 ++++++++---
> 6 files changed, 126 insertions(+), 9 deletions(-)
>
> diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> index 72d2532f50..1654bcd2dc 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> @@ -240,4 +240,29 @@ Decompress (
> OUT UINTN *OutputSize
> );
>
> +/**
> + Clear legacy memory located at the first 4K-page.
> +
> + This function traverses the whole HOB list to check if memory from 0 to 4095
> + exists and has not been allocated, and then clear it if so.
> +
> + @param HoStart The start of HobList passed to DxeCore.
> +
> +**/
> +VOID
> +ClearLegacyMemory (
> + IN VOID *HobStart
> + );
> +
> +/**
> + Return configure status of NULL pointer detection feature
> +
> + @return TRUE NULL pointer detection feature is enabled
> + @return FALSE NULL pointer detection feature is disabled
> +**/
> +BOOLEAN
> +IsNullDetectionEnabled (
> + VOID
> + );
> +
> #endif
> diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> index c54afe4aa6..9d0e76a293 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> @@ -115,6 +115,7 @@
> [Pcd.IA32,Pcd.X64]
> gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
> ## SOMETIMES_CONSUMES
>
> gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
> ## CONSUMES
> + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
> ## CONSUMES
>
> [Pcd.IA32,Pcd.X64,Pcd.ARM,Pcd.AARCH64]
> gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ##
> SOMETIMES_CONSUMES
> diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> index 50b5440d15..0a71b1f3de 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> @@ -825,3 +825,68 @@ UpdateStackHob (
> Hob.Raw = GET_NEXT_HOB (Hob);
> }
> }
> +
> +/**
> + Clear legacy memory located at the first 4K-page, if available.
> +
> + This function traverses the whole HOB list to check if memory from 0 to 4095
> + exists and has not been allocated, and then clear it if so.
> +
> + @param HoStart The start of HobList passed to
> DxeCore.
> +
> +**/
> +VOID
> +ClearLegacyMemory (
> + IN VOID *HobStart
> + )
> +{
> + EFI_PEI_HOB_POINTERS RscHob;
> + EFI_PEI_HOB_POINTERS MemHob;
> + BOOLEAN DoClear;
> +
> + RscHob.Raw = HobStart;
> + MemHob.Raw = HobStart;
> + DoClear = FALSE;
> +
> + //
> + // Check if page 0 exists and free
> + //
> + while ((RscHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
> + RscHob.Raw)) != NULL) {
> + if (RscHob.ResourceDescriptor->ResourceType ==
> EFI_RESOURCE_SYSTEM_MEMORY &&
> + RscHob.ResourceDescriptor->PhysicalStart == 0) {
> + DoClear = TRUE;
> + //
> + // Make sure memory at 0-4095 has not been allocated.
> + //
> + while ((MemHob.Raw = GetNextHob
> (EFI_HOB_TYPE_MEMORY_ALLOCATION,
> + MemHob.Raw)) != NULL) {
> + if (MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress
> + < EFI_PAGE_SIZE) {
> + DoClear = FALSE;
> + break;
> + }
> + MemHob.Raw = GET_NEXT_HOB (MemHob);
> + }
> + break;
> + }
> + RscHob.Raw = GET_NEXT_HOB (RscHob);
> + }
> +
> + if (DoClear) {
> + DEBUG ((DEBUG_INFO, "Clearing first 4K-page!\r\n"));
> + SetMem (NULL, EFI_PAGE_SIZE, 0);
> + }
> +
> + return;
> +}
> +
> +BOOLEAN
> +IsNullDetectionEnabled (
> + VOID
> + )
> +{
> + return (((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) != 0) ?
> + TRUE : FALSE);
> +}
> +
> diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> index 1957326caf..503cf88382 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> @@ -123,7 +123,9 @@ Create4GPageTablesIa32Pae (
> PageDirectoryPointerEntry->Bits.Present = 1;
>
> for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512;
> IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress +=
> SIZE_2MB) {
> - if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress +
> SIZE_2MB) > StackBase)) {
> + if ((IsNullDetectionEnabled () && PhysicalAddress == 0)
> + || ((PhysicalAddress < StackBase + StackSize)
> + && ((PhysicalAddress + SIZE_2MB) > StackBase))) {
> //
> // Need to split this 2M page that covers stack range.
> //
> @@ -240,6 +242,8 @@ HandOffToDxeCore (
> EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
> BOOLEAN BuildPageTablesIa32Pae;
>
> + ClearLegacyMemory (HobList.Raw);
> +
> Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES
> (STACK_SIZE), &BaseOfStack);
> ASSERT_EFI_ERROR (Status);
>
> @@ -379,7 +383,10 @@ HandOffToDxeCore (
> TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER
> (TopOfStack, CPU_STACK_ALIGNMENT);
>
> PageTables = 0;
> - BuildPageTablesIa32Pae = (BOOLEAN) (PcdGetBool (PcdSetNxForStack) &&
> IsIa32PaeSupport () && IsExecuteDisableBitAvailable ());
> + BuildPageTablesIa32Pae = (BOOLEAN) (IsIa32PaeSupport ()
> + && IsExecuteDisableBitAvailable
> ()
> + && (PcdGetBool
> (PcdSetNxForStack)
> + || IsNullDetectionEnabled
> ()));
> if (BuildPageTablesIa32Pae) {
> PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE);
> EnableExecuteDisableBit ();
> diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
> b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
> index 6488880eab..d93a9c5a2d 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
> @@ -42,6 +42,8 @@ HandOffToDxeCore (
> EFI_VECTOR_HANDOFF_INFO *VectorInfo;
> EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
>
> + ClearLegacyMemory (HobList.Raw);
> +
> //
> // Get Vector Hand-off Info PPI and build Guided HOB
> //
> diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> index 48150be4e1..80c1821eca 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> @@ -90,8 +90,16 @@ Split2MPageTo4K (
> //
> PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;
> PageTableEntry->Bits.ReadWrite = 1;
> - PageTableEntry->Bits.Present = 1;
> - if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase +
> StackSize)) {
> +
> + if (IsNullDetectionEnabled () && PhysicalAddress4K == 0) {
> + PageTableEntry->Bits.Present = 0;
> + } else {
> + PageTableEntry->Bits.Present = 1;
> + }
> +
> + if (PcdGetBool (PcdSetNxForStack)
> + && (PhysicalAddress4K >= StackBase)
> + && (PhysicalAddress4K < StackBase + StackSize)) {
> //
> // Set Nx bit for stack.
> //
> @@ -137,9 +145,12 @@ Split1GPageTo2M (
>
> PhysicalAddress2M = PhysicalAddress;
> for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512;
> IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M +=
> SIZE_2MB) {
> - if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M +
> SIZE_2MB) > StackBase)) {
> + if ((IsNullDetectionEnabled () && PhysicalAddress2M == 0)
> + || (PcdGetBool (PcdSetNxForStack)
> + && (PhysicalAddress2M < StackBase + StackSize)
> + && ((PhysicalAddress2M + SIZE_2MB) > StackBase))) {
> //
> - // Need to split this 2M page that covers stack range.
> + // Need to split this 2M page that covers NULL or stack range.
> //
> Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry,
> StackBase, StackSize);
> } else {
> @@ -279,7 +290,10 @@ CreateIdentityMappingPageTables (
> PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
>
> for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512;
> IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress +=
> SIZE_1GB) {
> - if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase +
> StackSize) && ((PageAddress + SIZE_1GB) > StackBase)) {
> + if ((IsNullDetectionEnabled () && PageAddress == 0)
> + || (PcdGetBool (PcdSetNxForStack)
> + && (PageAddress < StackBase + StackSize)
> + && ((PageAddress + SIZE_1GB) > StackBase))) {
> Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry,
> StackBase, StackSize);
> } else {
> //
> @@ -308,9 +322,12 @@ CreateIdentityMappingPageTables (
> PageDirectoryPointerEntry->Bits.Present = 1;
>
> for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries <
> 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress +=
> SIZE_2MB) {
> - if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase +
> StackSize) && ((PageAddress + SIZE_2MB) > StackBase)) {
> + if ((IsNullDetectionEnabled () && PageAddress == 0)
> + || (PcdGetBool (PcdSetNxForStack)
> + && (PageAddress < StackBase + StackSize)
> + && ((PageAddress + SIZE_2MB) > StackBase))) {
> //
> - // Need to split this 2M page that covers stack range.
> + // Need to split this 2M page that covers NULL or stack range.
> //
> Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry,
> StackBase, StackSize);
> } else {
> --
> 2.14.1.windows.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/6] MdeModulePkg/DxeIpl: Implement NULL pointer detection
2017-09-25 8:50 ` Yao, Jiewen
@ 2017-09-26 0:54 ` Wang, Jian J
0 siblings, 0 replies; 14+ messages in thread
From: Wang, Jian J @ 2017-09-26 0:54 UTC (permalink / raw)
To: Yao, Jiewen, edk2-devel@lists.01.org
Cc: Zeng, Star, Dong, Eric, Laszlo Ersek, Kinney, Michael D,
Justen, Jordan L, Wolman, Ayellet
Good catch. Thanks for the feedback.
> -----Original Message-----
> From: Yao, Jiewen
> Sent: Monday, September 25, 2017 4:51 PM
> To: Wang, Jian J <jian.j.wang@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Dong, Eric <eric.dong@intel.com>; Laszlo
> Ersek <lersek@redhat.com>; Kinney, Michael D <michael.d.kinney@intel.com>;
> Justen, Jordan L <jordan.l.justen@intel.com>; Wolman, Ayellet
> <ayellet.wolman@intel.com>
> Subject: RE: [PATCH v2 2/6] MdeModulePkg/DxeIpl: Implement NULL pointer
> detection
>
> Hi
> I do not think NULL pointer is related to NX.
> As long as NullPointer PCD is true and IA32PAE is supported, we can build page
> table.
>
> + BuildPageTablesIa32Pae = (BOOLEAN) (IsIa32PaeSupport ()
> + && IsExecuteDisableBitAvailable ()
> + && (PcdGetBool (PcdSetNxForStack)
> + || IsNullDetectionEnabled ()));
>
>
>
>
> > -----Original Message-----
> > From: Wang, Jian J
> > Sent: Thursday, September 21, 2017 1:20 PM
> > To: edk2-devel@lists.01.org
> > Cc: Zeng, Star <star.zeng@intel.com>; Dong, Eric <eric.dong@intel.com>;
> Laszlo
> > Ersek <lersek@redhat.com>; Yao, Jiewen <jiewen.yao@intel.com>; Kinney,
> > Michael D <michael.d.kinney@intel.com>; Justen, Jordan L
> > <jordan.l.justen@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
> > Subject: [PATCH v2 2/6] MdeModulePkg/DxeIpl: Implement NULL pointer
> > detection
> >
> > NULL pointer detection is done by making use of paging mechanism of CPU.
> > During page table setup, if enabled, the first 4-K page (0-4095) will be
> > marked as NOT PRESENT. Any code which unintentionally access memory
> > between
> > 0-4095 will trigger a Page Fault exception which warns users that there's
> > potential illegal code in BIOS.
> >
> > This also means that legacy code which has to access memory between 0-
> 4095
> > should be cautious to temporarily disable this feature before the access
> > and re-enable it afterwards; or disalbe this feature at all.
> >
> > Cc: Star Zeng <star.zeng@intel.com>
> > Cc: Eric Dong <eric.dong@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Michael Kinney <michael.d.kinney@intel.com>
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Ayellet Wolman <ayellet.wolman@intel.com>
> > Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
> > ---
> > MdeModulePkg/Core/DxeIplPeim/DxeIpl.h | 25 +++++++++
> > MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 1 +
> > MdeModulePkg/Core/DxeIplPeim/DxeLoad.c | 65
> > ++++++++++++++++++++++++
> > MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c | 11 +++-
> > MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c | 2 +
> > MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 31 ++++++++---
> > 6 files changed, 126 insertions(+), 9 deletions(-)
> >
> > diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> > b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> > index 72d2532f50..1654bcd2dc 100644
> > --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> > +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> > @@ -240,4 +240,29 @@ Decompress (
> > OUT UINTN *OutputSize
> > );
> >
> > +/**
> > + Clear legacy memory located at the first 4K-page.
> > +
> > + This function traverses the whole HOB list to check if memory from 0 to
> 4095
> > + exists and has not been allocated, and then clear it if so.
> > +
> > + @param HoStart The start of HobList passed to DxeCore.
> > +
> > +**/
> > +VOID
> > +ClearLegacyMemory (
> > + IN VOID *HobStart
> > + );
> > +
> > +/**
> > + Return configure status of NULL pointer detection feature
> > +
> > + @return TRUE NULL pointer detection feature is enabled
> > + @return FALSE NULL pointer detection feature is disabled
> > +**/
> > +BOOLEAN
> > +IsNullDetectionEnabled (
> > + VOID
> > + );
> > +
> > #endif
> > diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> > b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> > index c54afe4aa6..9d0e76a293 100644
> > --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> > +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> > @@ -115,6 +115,7 @@
> > [Pcd.IA32,Pcd.X64]
> > gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
> > ## SOMETIMES_CONSUMES
> >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
> > ## CONSUMES
> > + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
> > ## CONSUMES
> >
> > [Pcd.IA32,Pcd.X64,Pcd.ARM,Pcd.AARCH64]
> > gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ##
> > SOMETIMES_CONSUMES
> > diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> > b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> > index 50b5440d15..0a71b1f3de 100644
> > --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> > +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> > @@ -825,3 +825,68 @@ UpdateStackHob (
> > Hob.Raw = GET_NEXT_HOB (Hob);
> > }
> > }
> > +
> > +/**
> > + Clear legacy memory located at the first 4K-page, if available.
> > +
> > + This function traverses the whole HOB list to check if memory from 0 to
> 4095
> > + exists and has not been allocated, and then clear it if so.
> > +
> > + @param HoStart The start of HobList passed to
> > DxeCore.
> > +
> > +**/
> > +VOID
> > +ClearLegacyMemory (
> > + IN VOID *HobStart
> > + )
> > +{
> > + EFI_PEI_HOB_POINTERS RscHob;
> > + EFI_PEI_HOB_POINTERS MemHob;
> > + BOOLEAN DoClear;
> > +
> > + RscHob.Raw = HobStart;
> > + MemHob.Raw = HobStart;
> > + DoClear = FALSE;
> > +
> > + //
> > + // Check if page 0 exists and free
> > + //
> > + while ((RscHob.Raw = GetNextHob
> (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
> > + RscHob.Raw)) != NULL) {
> > + if (RscHob.ResourceDescriptor->ResourceType ==
> > EFI_RESOURCE_SYSTEM_MEMORY &&
> > + RscHob.ResourceDescriptor->PhysicalStart == 0) {
> > + DoClear = TRUE;
> > + //
> > + // Make sure memory at 0-4095 has not been allocated.
> > + //
> > + while ((MemHob.Raw = GetNextHob
> > (EFI_HOB_TYPE_MEMORY_ALLOCATION,
> > + MemHob.Raw)) != NULL) {
> > + if (MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress
> > + < EFI_PAGE_SIZE) {
> > + DoClear = FALSE;
> > + break;
> > + }
> > + MemHob.Raw = GET_NEXT_HOB (MemHob);
> > + }
> > + break;
> > + }
> > + RscHob.Raw = GET_NEXT_HOB (RscHob);
> > + }
> > +
> > + if (DoClear) {
> > + DEBUG ((DEBUG_INFO, "Clearing first 4K-page!\r\n"));
> > + SetMem (NULL, EFI_PAGE_SIZE, 0);
> > + }
> > +
> > + return;
> > +}
> > +
> > +BOOLEAN
> > +IsNullDetectionEnabled (
> > + VOID
> > + )
> > +{
> > + return (((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) != 0) ?
> > + TRUE : FALSE);
> > +}
> > +
> > diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> > b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> > index 1957326caf..503cf88382 100644
> > --- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> > +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> > @@ -123,7 +123,9 @@ Create4GPageTablesIa32Pae (
> > PageDirectoryPointerEntry->Bits.Present = 1;
> >
> > for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512;
> > IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress +=
> > SIZE_2MB) {
> > - if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress +
> > SIZE_2MB) > StackBase)) {
> > + if ((IsNullDetectionEnabled () && PhysicalAddress == 0)
> > + || ((PhysicalAddress < StackBase + StackSize)
> > + && ((PhysicalAddress + SIZE_2MB) > StackBase))) {
> > //
> > // Need to split this 2M page that covers stack range.
> > //
> > @@ -240,6 +242,8 @@ HandOffToDxeCore (
> > EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
> > BOOLEAN BuildPageTablesIa32Pae;
> >
> > + ClearLegacyMemory (HobList.Raw);
> > +
> > Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES
> > (STACK_SIZE), &BaseOfStack);
> > ASSERT_EFI_ERROR (Status);
> >
> > @@ -379,7 +383,10 @@ HandOffToDxeCore (
> > TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER
> > (TopOfStack, CPU_STACK_ALIGNMENT);
> >
> > PageTables = 0;
> > - BuildPageTablesIa32Pae = (BOOLEAN) (PcdGetBool (PcdSetNxForStack) &&
> > IsIa32PaeSupport () && IsExecuteDisableBitAvailable ());
> > + BuildPageTablesIa32Pae = (BOOLEAN) (IsIa32PaeSupport ()
> > + && IsExecuteDisableBitAvailable
> > ()
> > + && (PcdGetBool
> > (PcdSetNxForStack)
> > + || IsNullDetectionEnabled
> > ()));
> > if (BuildPageTablesIa32Pae) {
> > PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE);
> > EnableExecuteDisableBit ();
> > diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
> > b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
> > index 6488880eab..d93a9c5a2d 100644
> > --- a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
> > +++ b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
> > @@ -42,6 +42,8 @@ HandOffToDxeCore (
> > EFI_VECTOR_HANDOFF_INFO *VectorInfo;
> > EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
> >
> > + ClearLegacyMemory (HobList.Raw);
> > +
> > //
> > // Get Vector Hand-off Info PPI and build Guided HOB
> > //
> > diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> > b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> > index 48150be4e1..80c1821eca 100644
> > --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> > +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> > @@ -90,8 +90,16 @@ Split2MPageTo4K (
> > //
> > PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;
> > PageTableEntry->Bits.ReadWrite = 1;
> > - PageTableEntry->Bits.Present = 1;
> > - if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase +
> > StackSize)) {
> > +
> > + if (IsNullDetectionEnabled () && PhysicalAddress4K == 0) {
> > + PageTableEntry->Bits.Present = 0;
> > + } else {
> > + PageTableEntry->Bits.Present = 1;
> > + }
> > +
> > + if (PcdGetBool (PcdSetNxForStack)
> > + && (PhysicalAddress4K >= StackBase)
> > + && (PhysicalAddress4K < StackBase + StackSize)) {
> > //
> > // Set Nx bit for stack.
> > //
> > @@ -137,9 +145,12 @@ Split1GPageTo2M (
> >
> > PhysicalAddress2M = PhysicalAddress;
> > for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512;
> > IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M +=
> > SIZE_2MB) {
> > - if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M +
> > SIZE_2MB) > StackBase)) {
> > + if ((IsNullDetectionEnabled () && PhysicalAddress2M == 0)
> > + || (PcdGetBool (PcdSetNxForStack)
> > + && (PhysicalAddress2M < StackBase + StackSize)
> > + && ((PhysicalAddress2M + SIZE_2MB) > StackBase))) {
> > //
> > - // Need to split this 2M page that covers stack range.
> > + // Need to split this 2M page that covers NULL or stack range.
> > //
> > Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry,
> > StackBase, StackSize);
> > } else {
> > @@ -279,7 +290,10 @@ CreateIdentityMappingPageTables (
> > PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
> >
> > for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512;
> > IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress +=
> > SIZE_1GB) {
> > - if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase +
> > StackSize) && ((PageAddress + SIZE_1GB) > StackBase)) {
> > + if ((IsNullDetectionEnabled () && PageAddress == 0)
> > + || (PcdGetBool (PcdSetNxForStack)
> > + && (PageAddress < StackBase + StackSize)
> > + && ((PageAddress + SIZE_1GB) > StackBase))) {
> > Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry,
> > StackBase, StackSize);
> > } else {
> > //
> > @@ -308,9 +322,12 @@ CreateIdentityMappingPageTables (
> > PageDirectoryPointerEntry->Bits.Present = 1;
> >
> > for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries <
> > 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress +=
> > SIZE_2MB) {
> > - if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase +
> > StackSize) && ((PageAddress + SIZE_2MB) > StackBase)) {
> > + if ((IsNullDetectionEnabled () && PageAddress == 0)
> > + || (PcdGetBool (PcdSetNxForStack)
> > + && (PageAddress < StackBase + StackSize)
> > + && ((PageAddress + SIZE_2MB) > StackBase))) {
> > //
> > - // Need to split this 2M page that covers stack range.
> > + // Need to split this 2M page that covers NULL or stack range.
> > //
> > Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry,
> > StackBase, StackSize);
> > } else {
> > --
> > 2.14.1.windows.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 3/6] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM code
2017-09-21 5:20 ` [PATCH v2 0/6] Add NULL pointer detection feature Jian J Wang
2017-09-21 5:20 ` [PATCH v2 1/6] MdeModulePkg/MdeModulePkg.dec: Add NULL pointer detection PCD Jian J Wang
2017-09-21 5:20 ` [PATCH v2 2/6] MdeModulePkg/DxeIpl: Implement NULL pointer detection Jian J Wang
@ 2017-09-21 5:20 ` Jian J Wang
2017-09-21 5:20 ` [PATCH v2 4/6] MdeModulePkg/Core/Dxe: Add EndOfDxe workaround for NULL pointer detection Jian J Wang
` (2 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Jian J Wang @ 2017-09-21 5:20 UTC (permalink / raw)
To: edk2-devel
Cc: Star Zeng, Eric Dong, Laszlo Ersek, Jiewen Yao, Michael Kinney,
Jordan Justen, Ayellet Wolman
The mechanism behind is the same as NULL pointer detection enabled in EDK-II
core. SMM has its own page table and we have to disable page 0 again in SMM
mode.
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ayellet Wolman <ayellet.wolman@intel.com>
Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
---
UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c | 12 ++++++++++++
UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c | 25 ++++++++++++++++++++++++-
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf | 1 +
UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c | 12 ++++++++++++
4 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
index f295c2ebf2..1c9e239a34 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
@@ -155,6 +155,18 @@ SmiPFHandler (
}
}
+ //
+ // If NULL pointer was just accessed
+ //
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0 &&
+ (PFAddress < EFI_PAGE_SIZE)) {
+ DEBUG ((DEBUG_ERROR, "!!! NULL pointer access !!!\n"));
+ DEBUG_CODE (
+ DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Rip);
+ );
+ CpuDeadLoop ();
+ }
+
if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
SmmProfilePFHandler (
SystemContext.SystemContextIa32->Eip,
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
index f086b97c30..ed2afadb21 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
@@ -855,10 +855,10 @@ Gen4GPageTable (
Pte[Index] = (Index << 21) | mAddressEncMask | IA32_PG_PS | PAGE_ATTRIBUTE_BITS;
}
+ Pdpte = (UINT64*)PageTable;
if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
Pages = (UINTN)PageTable + EFI_PAGES_TO_SIZE (5);
GuardPage = mSmmStackArrayBase + EFI_PAGE_SIZE;
- Pdpte = (UINT64*)PageTable;
for (PageIndex = Low2MBoundary; PageIndex <= High2MBoundary; PageIndex += SIZE_2MB) {
Pte = (UINT64*)(UINTN)(Pdpte[BitFieldRead32 ((UINT32)PageIndex, 30, 31)] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));
Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS;
@@ -886,6 +886,29 @@ Gen4GPageTable (
}
}
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) {
+ Pte = (UINT64*)(UINTN)(Pdpte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));
+ if ((Pte[0] & IA32_PG_PS) == 0) {
+ // 4K-page entries are already mapped. Just hide the first one anyway.
+ Pte = (UINT64*)(UINTN)(Pte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));
+ Pte[0] &= ~1; // Hide page 0
+ } else {
+ // Create 4K-page entries
+ Pages = (UINTN)AllocatePageTableMemory (1);
+ ASSERT (Pages != 0);
+
+ Pte[0] = (UINT64)(Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS);
+
+ Pte = (UINT64*)Pages;
+ PageAddress = 0;
+ Pte[0] = PageAddress | mAddressEncMask; // Hide page 0 but present left
+ for (Index = 1; Index < EFI_PAGE_SIZE / sizeof (*Pte); Index++) {
+ PageAddress += EFI_PAGE_SIZE;
+ Pte[Index] = PageAddress | mAddressEncMask | PAGE_ATTRIBUTE_BITS;
+ }
+ }
+ }
+
return (UINT32)(UINTN)PageTable;
}
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
index 099792e6ce..31cb215342 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -159,6 +159,7 @@
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStaticPageTable ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES
[Depex]
gEfiMpServiceProtocolGuid
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
index 3dde80f9ba..f3791ce897 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
@@ -872,6 +872,18 @@ SmiPFHandler (
}
}
+ //
+ // If NULL pointer was just accessed
+ //
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0 &&
+ (PFAddress < EFI_PAGE_SIZE)) {
+ DEBUG ((DEBUG_ERROR, "!!! NULL pointer access !!!\n"));
+ DEBUG_CODE (
+ DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextX64->Rip);
+ );
+ CpuDeadLoop ();
+ }
+
if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
SmmProfilePFHandler (
SystemContext.SystemContextX64->Rip,
--
2.14.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 4/6] MdeModulePkg/Core/Dxe: Add EndOfDxe workaround for NULL pointer detection
2017-09-21 5:20 ` [PATCH v2 0/6] Add NULL pointer detection feature Jian J Wang
` (2 preceding siblings ...)
2017-09-21 5:20 ` [PATCH v2 3/6] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM code Jian J Wang
@ 2017-09-21 5:20 ` Jian J Wang
2017-09-21 5:20 ` [PATCH v2 5/6] IntelFrameworkModulePkg/Csm: Add code to bypass " Jian J Wang
2017-09-21 5:20 ` [PATCH v2 6/6] OvmfPkg/QemuVideoDxe: Bypass NULL pointer detection during VBE SHIM installing Jian J Wang
5 siblings, 0 replies; 14+ messages in thread
From: Jian J Wang @ 2017-09-21 5:20 UTC (permalink / raw)
To: edk2-devel
Cc: Star Zeng, Eric Dong, Laszlo Ersek, Jiewen Yao, Michael Kinney,
Jordan Justen, Ayellet Wolman
One of issue caused by enabling NULL pointer detection is that some PCI
device OptionROM, binary drivers and binary OS boot loaders may have NULL
pointer access bugs, which will prevent BIOS from booting and is almost
impossible to fix. BIT7 of PCD PcdNullPointerDetectionPropertyMask is used
as a workaround to indicate BIOS to disable NULL pointer detection right
after event gEfiEndOfDxeEventGroupGuid, and then let boot continue.
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ayellet Wolman <ayellet.wolman@intel.com>
Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
---
MdeModulePkg/Core/Dxe/DxeMain.inf | 1 +
MdeModulePkg/Core/Dxe/Mem/Page.c | 4 ++-
MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c | 48 +++++++++++++++++++++++++++
3 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
index 30d5984f7c..0a161ffd71 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.inf
+++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -192,6 +192,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdPropertiesTableEnable ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES
# [Hob]
# RESOURCE_DESCRIPTOR ## CONSUMES
diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c
index a142c79ee2..0468df3171 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Page.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Page.c
@@ -188,7 +188,9 @@ CoreAddRange (
// used for other purposes.
//
if (Type == EfiConventionalMemory && Start == 0 && (End >= EFI_PAGE_SIZE - 1)) {
- SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) == 0) {
+ SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);
+ }
}
//
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
index a73c4ccd64..73e3b269f3 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
@@ -995,6 +995,36 @@ MemoryProtectionExitBootServicesCallback (
}
}
+/**
+ Disable NULL pointer detection after EndOfDxe. This is a workaround resort in
+ order to skip unfixable NULL pointer access issues detected in OptionROM or
+ boot loaders.
+
+ @param[in] Event The Event this notify function registered to.
+ @param[in] Context Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+DisableNullDetectionAtTheEndOfDxe (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): start\r\n"));
+ //
+ // Disable NULL pointer detection by enabling first 4K page
+ //
+ Status = gCpu->SetMemoryAttributes (gCpu, 0, EFI_PAGE_SIZE, 0);
+ ASSERT_EFI_ERROR (Status);
+
+ CoreCloseEvent (Event);
+ DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): end\r\n"));
+
+ return;
+}
+
/**
Initialize Memory Protection support.
**/
@@ -1006,6 +1036,7 @@ CoreInitializeMemoryProtection (
{
EFI_STATUS Status;
EFI_EVENT Event;
+ EFI_EVENT EndOfDxeEvent;
VOID *Registration;
mImageProtectionPolicy = PcdGet32(PcdImageProtectionPolicy);
@@ -1044,6 +1075,23 @@ CoreInitializeMemoryProtection (
);
ASSERT_EFI_ERROR(Status);
}
+
+ //
+ // Register a callback to disable NULL pointer detection at EndOfDxe
+ //
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7))
+ == (BIT0|BIT7)) {
+ Status = CoreCreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ DisableNullDetectionAtTheEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
return ;
}
--
2.14.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 5/6] IntelFrameworkModulePkg/Csm: Add code to bypass NULL pointer detection
2017-09-21 5:20 ` [PATCH v2 0/6] Add NULL pointer detection feature Jian J Wang
` (3 preceding siblings ...)
2017-09-21 5:20 ` [PATCH v2 4/6] MdeModulePkg/Core/Dxe: Add EndOfDxe workaround for NULL pointer detection Jian J Wang
@ 2017-09-21 5:20 ` Jian J Wang
2017-09-21 5:20 ` [PATCH v2 6/6] OvmfPkg/QemuVideoDxe: Bypass NULL pointer detection during VBE SHIM installing Jian J Wang
5 siblings, 0 replies; 14+ messages in thread
From: Jian J Wang @ 2017-09-21 5:20 UTC (permalink / raw)
To: edk2-devel
Cc: Star Zeng, Eric Dong, Laszlo Ersek, Jiewen Yao, Michael Kinney,
Jordan Justen, Ayellet Wolman
Legacy has to access interrupt vector, BDA, etc. located in memory between
0-4095. To allow as much code as possible to be monitered by NULL pointer
detection, we add code to temporarily disable this feature right before
those memory access and enable it again afterwards.
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ayellet Wolman <ayellet.wolman@intel.com>
Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
---
.../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c | 13 ++++
.../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h | 2 +
.../Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf | 2 +
.../Csm/LegacyBiosDxe/LegacyBda.c | 4 +
.../Csm/LegacyBiosDxe/LegacyBios.c | 90 ++++++++++++++++++++++
.../Csm/LegacyBiosDxe/LegacyBiosDxe.inf | 2 +
.../Csm/LegacyBiosDxe/LegacyBiosInterface.h | 18 +++++
.../Csm/LegacyBiosDxe/LegacyBootSupport.c | 23 +++++-
.../Csm/LegacyBiosDxe/LegacyPci.c | 17 +++-
IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c | 27 +++++--
10 files changed, 188 insertions(+), 10 deletions(-)
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
index 7308523ad8..91e50405fc 100644
--- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
@@ -1839,6 +1839,13 @@ BiosKeyboardTimerHandler (
// 0 Right Shift pressed
+ //
+ // Disable NULL pointer detection temporarily
+ //
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) != 0) {
+ gDS->SetMemorySpaceAttributes (0, EFI_PAGES_TO_SIZE(1), 0);
+ }
+
//
// Clear the CTRL and ALT BDA flag
//
@@ -1916,6 +1923,12 @@ BiosKeyboardTimerHandler (
KbFlag1 &= ~0x0C;
*((UINT8 *) (UINTN) 0x417) = KbFlag1;
+ //
+ // Restore NULL pointer detection
+ //
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) != 0) {
+ gDS->SetMemorySpaceAttributes (0, EFI_PAGES_TO_SIZE(1), EFI_MEMORY_RP);
+ }
//
// Output EFI input key and shift/toggle state
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h
index 0bf28ea140..c64ec0095e 100644
--- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h
@@ -18,6 +18,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <FrameworkDxe.h>
+#include <Pi/PiDxeCis.h>
#include <Guid/StatusCodeDataTypeId.h>
#include <Protocol/SimpleTextIn.h>
@@ -33,6 +34,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/ReportStatusCodeLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseLib.h>
#include <Library/PcdLib.h>
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf
index 4d4536466c..596f4ced44 100644
--- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf
@@ -60,6 +60,7 @@
DebugLib
BaseLib
PcdLib
+ DxeServicesTableLib
[Protocols]
gEfiIsaIoProtocolGuid ## TO_START
@@ -73,6 +74,7 @@
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFastPS2Detection ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES
[UserExtensions.TianoCore."ExtraFiles"]
KeyboardDxeExtra.uni
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c
index c45d5d4c3e..c6670febee 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c
@@ -34,6 +34,8 @@ LegacyBiosInitBda (
BDA_STRUC *Bda;
UINT8 *Ebda;
+ DisableNullDetection ();
+
Bda = (BDA_STRUC *) ((UINTN) 0x400);
Ebda = (UINT8 *) ((UINTN) 0x9fc00);
@@ -62,5 +64,7 @@ LegacyBiosInitBda (
*Ebda = 0x01;
+ EnableNullDetection ();
+
return EFI_SUCCESS;
}
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
index 3ead2d9828..e603f82d9e 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
@@ -40,6 +40,7 @@ VOID *mRuntimeSmbiosEntryPoint = NULL;
EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint = 0;
EFI_PHYSICAL_ADDRESS mStructureTableAddress = 0;
UINTN mStructureTablePages = 0;
+BOOLEAN mEndOfDxe = FALSE;
/**
Do an AllocatePages () of type AllocateMaxAddress for EfiBootServicesCode
@@ -765,6 +766,73 @@ InstallSmbiosEventCallback (
}
}
+/**
+ Callback function to toggle EndOfDxe status. NULL pointer detection needs
+ this status to decide if it's necessary to change attributes of page 0.
+
+ @param Event Event whose notification function is being invoked.
+ @param Context The pointer to the notification function's context,
+ which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+ToggleEndOfDxeStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ mEndOfDxe = TRUE;
+ return;
+}
+
+//
+// Legacy BIOS needs to access memory between 0-4095, which will cause page
+// fault exception if NULL pointer detection mechanism is enabled. Following
+// functions can be used to disable/enable NULL pointer detection before/after
+// accessing those memory.
+//
+
+/**
+ Enable NULL pointer detection
+*/
+VOID
+EnableNullDetection (
+ VOID
+ )
+{
+ if (((mEndOfDxe == FALSE) &&
+ ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) == BIT0))
+ ||
+ ((mEndOfDxe == TRUE) &&
+ ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0))
+ ) {
+
+ gDS->SetMemorySpaceAttributes (0, EFI_PAGES_TO_SIZE(1), EFI_MEMORY_RP);
+
+ }
+}
+
+/**
+ Disable NULL pointer detection
+*/
+VOID
+DisableNullDetection (
+ VOID
+ )
+{
+ if (((mEndOfDxe == FALSE) &&
+ ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) == BIT0))
+ ||
+ ((mEndOfDxe == TRUE) &&
+ ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0))
+ ) {
+
+ gDS->SetMemorySpaceAttributes (0, EFI_PAGES_TO_SIZE(1), 0);
+
+ }
+}
+
/**
Install Driver to produce Legacy BIOS protocol.
@@ -802,6 +870,7 @@ LegacyBiosInstall (
UINT64 Length;
UINT8 *SecureBoot;
EFI_EVENT InstallSmbiosEvent;
+ EFI_EVENT EndOfDxeEvent;
//
// Load this driver's image to memory
@@ -964,8 +1033,10 @@ LegacyBiosInstall (
// Initialize region from 0x0000 to 4k. This initializes interrupt vector
// range.
//
+ DisableNullDetection ();
gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K);
ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00);
+ EnableNullDetection ();
//
// Allocate pages for OPROM usage
@@ -1104,12 +1175,17 @@ LegacyBiosInstall (
//
// Save Unexpected interrupt vector so can restore it just prior to boot
//
+ DisableNullDetection ();
+
BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);
Private->BiosUnexpectedInt = BaseVectorMaster[0];
IntRedirCode = (UINT32) (UINTN) Private->IntThunk->InterruptRedirectionCode;
for (Index = 0; Index < 8; Index++) {
BaseVectorMaster[Index] = (EFI_SEGMENT (IntRedirCode + Index * 4) << 16) | EFI_OFFSET (IntRedirCode + Index * 4);
}
+
+ EnableNullDetection ();
+
//
// Save EFI value
//
@@ -1133,6 +1209,20 @@ LegacyBiosInstall (
);
ASSERT_EFI_ERROR (Status);
+ //
+ // Create callback to update status of EndOfDxe, which is needed by NULL
+ // pointer detection
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ ToggleEndOfDxeStatus,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
//
// Make a new handle and install the protocol
//
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf
index 48473a0713..6efc7f36ae 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf
@@ -108,6 +108,7 @@
gEfiDiskInfoIdeInterfaceGuid ## SOMETIMES_CONSUMES ##GUID #Used in LegacyBiosBuildIdeData() to assure device is a disk
gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ##SystemTable
gEfiLegacyBiosGuid ## SOMETIMES_CONSUMES ##GUID #Used in LegacyBiosInstallVgaRom() to locate handle buffer
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES
[Guids.IA32]
gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ##SystemTable
@@ -147,6 +148,7 @@
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHighPmmMemorySize ## CONSUMES
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemoryBase ## CONSUMES
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemorySize ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES
[Depex]
gEfiLegacyRegion2ProtocolGuid AND gEfiLegacyInterruptProtocolGuid AND gEfiLegacyBiosPlatformProtocolGuid AND gEfiLegacy8259ProtocolGuid AND gEfiGenericMemTestProtocolGuid AND gEfiCpuArchProtocolGuid AND gEfiTimerArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h
index fe9dd7463a..20dfef3fec 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h
@@ -509,6 +509,8 @@ extern BBS_TABLE *mBbsTable;
extern EFI_GENERIC_MEMORY_TEST_PROTOCOL *gGenMemoryTest;
+extern BOOLEAN mEndOfDxe;
+
#define PORT_70 0x70
#define PORT_71 0x71
@@ -1542,4 +1544,20 @@ LegacyBiosInstallVgaRom (
IN LEGACY_BIOS_INSTANCE *Private
);
+/**
+ Enable NULL pointer detection
+*/
+VOID
+EnableNullDetection (
+ VOID
+ );
+
+/**
+ Disable NULL pointer detection
+*/
+VOID
+DisableNullDetection (
+ VOID
+ );
+
#endif
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c
index 1e098b3726..c2ac69ce69 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c
@@ -1073,8 +1073,10 @@ GenericLegacyBoot (
// Use 182/10 to avoid floating point math.
//
LocalTime = (LocalTime * 182) / 10;
+ DisableNullDetection ();
BdaPtr = (UINT32 *) (UINTN)0x46C;
*BdaPtr = LocalTime;
+ EnableNullDetection ();
//
// Shadow PCI ROMs. We must do this near the end since this will kick
@@ -1320,6 +1322,7 @@ GenericLegacyBoot (
// set of TIANO vectors) or takes it over.
//
//
+ DisableNullDetection ();
BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);
for (Index = 0; Index < 8; Index++) {
Private->ThunkSavedInt[Index] = BaseVectorMaster[Index];
@@ -1327,6 +1330,7 @@ GenericLegacyBoot (
BaseVectorMaster[Index] = (UINT32) (Private->BiosUnexpectedInt);
}
}
+ EnableNullDetection ();
ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
Regs.X.AX = Legacy16Boot;
@@ -1340,10 +1344,12 @@ GenericLegacyBoot (
0
);
+ DisableNullDetection ();
BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);
for (Index = 0; Index < 8; Index++) {
BaseVectorMaster[Index] = Private->ThunkSavedInt[Index];
}
+ EnableNullDetection ();
}
Private->LegacyBootEntered = TRUE;
if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {
@@ -1731,9 +1737,11 @@ LegacyBiosBuildE820 (
//
// First entry is 0 to (640k - EBDA)
//
+ DisableNullDetection ();
E820Table[0].BaseAddr = 0;
E820Table[0].Length = (UINT64) ((*(UINT16 *) (UINTN)0x40E) << 4);
E820Table[0].Type = EfiAcpiAddressRangeMemory;
+ EnableNullDetection ();
//
// Second entry is (640k - EBDA) to 640k
@@ -1967,6 +1975,8 @@ LegacyBiosCompleteBdaBeforeBoot (
UINT16 MachineConfig;
DEVICE_PRODUCER_DATA_HEADER *SioPtr;
+ DisableNullDetection ();
+
Bda = (BDA_STRUC *) ((UINTN) 0x400);
MachineConfig = 0;
@@ -2025,6 +2035,8 @@ LegacyBiosCompleteBdaBeforeBoot (
MachineConfig = (UINT16) (MachineConfig + 0x00 + 0x02 + (SioPtr->MousePresent * 0x04));
Bda->MachineConfig = MachineConfig;
+ EnableNullDetection ();
+
return EFI_SUCCESS;
}
@@ -2049,15 +2061,20 @@ LegacyBiosUpdateKeyboardLedStatus (
UINT8 LocalLeds;
EFI_IA32_REGISTER_SET Regs;
- Bda = (BDA_STRUC *) ((UINTN) 0x400);
-
Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
+
+ DisableNullDetection ();
+
+ Bda = (BDA_STRUC *) ((UINTN) 0x400);
LocalLeds = Leds;
Bda->LedStatus = (UINT8) ((Bda->LedStatus &~0x07) | LocalLeds);
LocalLeds = (UINT8) (LocalLeds << 4);
Bda->ShiftStatus = (UINT8) ((Bda->ShiftStatus &~0x70) | LocalLeds);
LocalLeds = (UINT8) (Leds & 0x20);
Bda->KeyboardStatus = (UINT8) ((Bda->KeyboardStatus &~0x20) | LocalLeds);
+
+ EnableNullDetection ();
+
//
// Call into Legacy16 code to allow it to do any processing
//
@@ -2102,7 +2119,9 @@ LegacyBiosCompleteStandardCmosBeforeBoot (
// to large capacity drives
// CMOS 14 = BDA 40:10 plus bit 3(display enabled)
//
+ DisableNullDetection ();
Bda = (UINT8)(*((UINT8 *)((UINTN)0x410)) | BIT3);
+ EnableNullDetection ();
//
// Force display enabled
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c
index 8ffdf0c1ff..d38cef3e33 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c
@@ -2279,6 +2279,7 @@ LegacyBiosInstallRom (
UINTN Function;
EFI_IA32_REGISTER_SET Regs;
UINT8 VideoMode;
+ UINT8 OldVideoMode;
EFI_TIME BootTime;
UINT32 *BdaPtr;
UINT32 LocalTime;
@@ -2299,6 +2300,7 @@ LegacyBiosInstallRom (
Device = 0;
Function = 0;
VideoMode = 0;
+ OldVideoMode = 0;
PhysicalAddress = 0;
MaxRomAddr = PcdGet32 (PcdEndOpromShadowAddress);
@@ -2401,6 +2403,8 @@ LegacyBiosInstallRom (
// 2. BBS compliants drives will not change 40:75 until boot time.
// 3. Onboard IDE controllers will change 40:75
//
+ DisableNullDetection ();
+
LocalDiskStart = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);
if ((Private->Disk4075 + 0x80) < LocalDiskStart) {
//
@@ -2426,6 +2430,9 @@ LegacyBiosInstallRom (
//
VideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));
}
+
+ EnableNullDetection ();
+
//
// Notify the platform that we are about to scan the ROM
//
@@ -2466,9 +2473,11 @@ LegacyBiosInstallRom (
// Multiply result by 18.2 for number of ticks since midnight.
// Use 182/10 to avoid floating point math.
//
+ DisableNullDetection ();
LocalTime = (LocalTime * 182) / 10;
BdaPtr = (UINT32 *) ((UINTN) 0x46C);
*BdaPtr = LocalTime;
+ EnableNullDetection ();
//
// Pass in handoff data
@@ -2564,7 +2573,11 @@ LegacyBiosInstallRom (
//
// Set mode settings since PrepareToScanRom may change mode
//
- if (VideoMode != *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE))) {
+ DisableNullDetection ();
+ OldVideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));
+ EnableNullDetection ();
+
+ if (VideoMode != OldVideoMode) {
//
// The active video mode is changed, restore it to original mode.
//
@@ -2604,7 +2617,9 @@ LegacyBiosInstallRom (
}
}
+ DisableNullDetection ();
LocalDiskEnd = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);
+ EnableNullDetection ();
//
// Allow platform to perform any required actions after the
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c
index 3d9a8b9649..f42c13cd89 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c
@@ -57,7 +57,11 @@ LegacyBiosInt86 (
IN EFI_IA32_REGISTER_SET *Regs
)
{
- UINT32 *VectorBase;
+ UINT16 Segment;
+ UINT16 Offset;
+ LEGACY_BIOS_INSTANCE *Private;
+
+ Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
Regs->X.Flags.Reserved1 = 1;
Regs->X.Flags.Reserved2 = 0;
@@ -72,12 +76,15 @@ LegacyBiosInt86 (
// The base address of legacy interrupt vector table is 0.
// We use this base address to get the legacy interrupt handler.
//
- VectorBase = 0;
+ DisableNullDetection ();
+ Segment = (UINT16)(((UINT32 *)0)[BiosInt] >> 16);
+ Offset = (UINT16)((UINT32 *)0)[BiosInt];
+ EnableNullDetection ();
return InternalLegacyBiosFarCall (
This,
- (UINT16) ((VectorBase)[BiosInt] >> 16),
- (UINT16) (VectorBase)[BiosInt],
+ Segment,
+ Offset,
Regs,
&Regs->X.Flags,
sizeof (Regs->X.Flags)
@@ -293,9 +300,15 @@ InternalLegacyBiosFarCall (
UINTN EbdaBaseAddress;
UINTN ReservedEbdaBaseAddress;
- EbdaBaseAddress = (*(UINT16 *) (UINTN) 0x40E) << 4;
- ReservedEbdaBaseAddress = CONVENTIONAL_MEMORY_TOP - PcdGet32 (PcdEbdaReservedMemorySize);
- ASSERT (ReservedEbdaBaseAddress <= EbdaBaseAddress);
+ //
+ // Skip this part of debug code if NULL pointer detection is enabled
+ //
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) == 0) {
+ EbdaBaseAddress = (*(UINT16 *) (UINTN) 0x40E) << 4;
+ ReservedEbdaBaseAddress = CONVENTIONAL_MEMORY_TOP
+ - PcdGet32 (PcdEbdaReservedMemorySize);
+ ASSERT (ReservedEbdaBaseAddress <= EbdaBaseAddress);
+ }
}
);
--
2.14.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 6/6] OvmfPkg/QemuVideoDxe: Bypass NULL pointer detection during VBE SHIM installing
2017-09-21 5:20 ` [PATCH v2 0/6] Add NULL pointer detection feature Jian J Wang
` (4 preceding siblings ...)
2017-09-21 5:20 ` [PATCH v2 5/6] IntelFrameworkModulePkg/Csm: Add code to bypass " Jian J Wang
@ 2017-09-21 5:20 ` Jian J Wang
2017-09-22 11:50 ` Laszlo Ersek
5 siblings, 1 reply; 14+ messages in thread
From: Jian J Wang @ 2017-09-21 5:20 UTC (permalink / raw)
To: edk2-devel
Cc: Star Zeng, Eric Dong, Laszlo Ersek, Jiewen Yao, Michael Kinney,
Jordan Justen, Ayellet Wolman
QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
detection is enabled, this driver will fail to load. NULL pointer detection
bypassing code is added to prevent such problem during boot.
Please note that Windows 7 will try to access VBE SHIM during boot if it's
installed, and then cause boot failure. This can be fixed by setting BIT7
of PcdNullPointerDetectionPropertyMask to disable NULL pointer detection
after EndOfDxe. As far as we know, there's no other OSs has such issue.
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ayellet Wolman <ayellet.wolman@intel.com>
Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
---
OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf | 2 ++
OvmfPkg/QemuVideoDxe/VbeShim.c | 22 ++++++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
index 577e07b0a8..8078232ded 100644
--- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
@@ -67,6 +67,7 @@
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiLib
+ DxeServicesTableLib
[Protocols]
gEfiDriverSupportedEfiVersionProtocolGuid # PROTOCOL ALWAYS_PRODUCED
@@ -77,3 +78,4 @@
[Pcd]
gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.c b/OvmfPkg/QemuVideoDxe/VbeShim.c
index e45a08e887..c3fb6d8d3c 100644
--- a/OvmfPkg/QemuVideoDxe/VbeShim.c
+++ b/OvmfPkg/QemuVideoDxe/VbeShim.c
@@ -21,10 +21,13 @@
WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
+#include <Pi/PiDxeCis.h>
#include <IndustryStandard/LegacyVgaBios.h>
#include <Library/DebugLib.h>
#include <Library/PciLib.h>
#include <Library/PrintLib.h>
+#include <Library/DxeServicesTableLib.h>
+
#include <OvmfPlatforms.h>
#include "Qemu.h"
@@ -74,11 +77,21 @@ InstallVbeShim (
UINT8 *Ptr;
UINTN Printed;
VBE_MODE_INFO *VbeModeInfo;
+ EFI_STATUS Status;
Segment0 = 0x00000;
SegmentC = 0xC0000;
SegmentF = 0xF0000;
+ //
+ // Disable NULL pointer detection temporarily. Otherwise the installation
+ // will fail due to the lack of memory access right.
+ //
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0) {
+ Status = gDS->SetMemorySpaceAttributes (0, EFI_PAGES_TO_SIZE (1), 0);
+ ASSERT_EFI_ERROR (Status);
+ }
+
//
// Attempt to cover the real mode IVT with an allocation. This is a UEFI
// driver, hence the arch protocols have been installed previously. Among
@@ -304,5 +317,14 @@ InstallVbeShim (
Int0x10->Segment = (UINT16) ((UINT32)SegmentC >> 4);
Int0x10->Offset = (UINT16) ((UINTN) (VbeModeInfo + 1) - SegmentC);
+ //
+ // Get NULL pointer detection back
+ //
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0) {
+ Status = gDS->SetMemorySpaceAttributes (0, EFI_PAGES_TO_SIZE(1),
+ EFI_MEMORY_RP);
+ ASSERT_EFI_ERROR (Status);
+ }
+
DEBUG ((EFI_D_INFO, "%a: VBE shim installed\n", __FUNCTION__));
}
--
2.14.1.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 6/6] OvmfPkg/QemuVideoDxe: Bypass NULL pointer detection during VBE SHIM installing
2017-09-21 5:20 ` [PATCH v2 6/6] OvmfPkg/QemuVideoDxe: Bypass NULL pointer detection during VBE SHIM installing Jian J Wang
@ 2017-09-22 11:50 ` Laszlo Ersek
2017-09-22 15:29 ` Laszlo Ersek
0 siblings, 1 reply; 14+ messages in thread
From: Laszlo Ersek @ 2017-09-22 11:50 UTC (permalink / raw)
To: Jian J Wang, edk2-devel
Cc: Star Zeng, Eric Dong, Jiewen Yao, Michael Kinney, Jordan Justen,
Ayellet Wolman
This patch looks great to me, I would like to request a few small updates:
On 09/21/17 07:20, Jian J Wang wrote:
> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
(1) please replace the word "install" with "link".
The VBE Shim is technically installed into the "real-mode" C segment,
only the int 0x10 vector lives in page 0.
> detection is enabled, this driver will fail to load. NULL pointer detection
> bypassing code is added to prevent such problem during boot.
>
> Please note that Windows 7 will try to access VBE SHIM during boot if it's
> installed, and then cause boot failure. This can be fixed by setting BIT7
> of PcdNullPointerDetectionPropertyMask to disable NULL pointer detection
> after EndOfDxe. As far as we know, there's no other OSs has such issue.
This is not a request, just a comment: I verified the default value in
the .dec, and I see it is 0. So there's no need to post an additional
patch for the OVMF DSC files, in order to set BIT7.
>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Michael Kinney <michael.d.kinney@intel.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ayellet Wolman <ayellet.wolman@intel.com>
> Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
> ---
> OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf | 2 ++
> OvmfPkg/QemuVideoDxe/VbeShim.c | 22 ++++++++++++++++++++++
> 2 files changed, 24 insertions(+)
>
> diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> index 577e07b0a8..8078232ded 100644
> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> @@ -67,6 +67,7 @@
> UefiBootServicesTableLib
> UefiDriverEntryPoint
> UefiLib
> + DxeServicesTableLib
>
> [Protocols]
> gEfiDriverSupportedEfiVersionProtocolGuid # PROTOCOL ALWAYS_PRODUCED
> @@ -77,3 +78,4 @@
> [Pcd]
> gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
> gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
> + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
> diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.c b/OvmfPkg/QemuVideoDxe/VbeShim.c
> index e45a08e887..c3fb6d8d3c 100644
> --- a/OvmfPkg/QemuVideoDxe/VbeShim.c
> +++ b/OvmfPkg/QemuVideoDxe/VbeShim.c
> @@ -21,10 +21,13 @@
> WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> **/
>
> +#include <Pi/PiDxeCis.h>
(2) Question: what exactly is this necessary for?
(I would think that "DxeServicesTableLib.h" gave you everything you
needed, but I could be wrong.)
> #include <IndustryStandard/LegacyVgaBios.h>
> #include <Library/DebugLib.h>
> #include <Library/PciLib.h>
> #include <Library/PrintLib.h>
> +#include <Library/DxeServicesTableLib.h>
> +
> #include <OvmfPlatforms.h>
>
> #include "Qemu.h"
> @@ -74,11 +77,21 @@ InstallVbeShim (
> UINT8 *Ptr;
> UINTN Printed;
> VBE_MODE_INFO *VbeModeInfo;
> + EFI_STATUS Status;
>
> Segment0 = 0x00000;
> SegmentC = 0xC0000;
> SegmentF = 0xF0000;
>
> + //
> + // Disable NULL pointer detection temporarily. Otherwise the installation
> + // will fail due to the lack of memory access right.
> + //
> + if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0) {
> + Status = gDS->SetMemorySpaceAttributes (0, EFI_PAGES_TO_SIZE (1), 0);
> + ASSERT_EFI_ERROR (Status);
> + }
> +
(3) Please hoist the
Segment0Pages = 1;
assignment from below, and use it in the SetMemorySpaceAttributes()
call, for the "Length" argument.
(4) Please use the variable "Segment0" as the "BaseAddress" argument.
(5) The Attributes=0 argument surprises me, and the end of this patch
seems to confirm that I'm right to be surprised :)
Instead of setting 0, can you please
- first get the original attributes with GetMemorySpaceDescriptor(),
- then clear only the attributes here that prevent read/write access,
- and at the end of the function, restore the original attributes?
I think this can be done without dynamic memory allocation, you just
need a local EFI_GCD_MEMORY_SPACE_DESCRIPTOR object.
> //
> // Attempt to cover the real mode IVT with an allocation. This is a UEFI
> // driver, hence the arch protocols have been installed previously. Among
> @@ -304,5 +317,14 @@ InstallVbeShim (
> Int0x10->Segment = (UINT16) ((UINT32)SegmentC >> 4);
> Int0x10->Offset = (UINT16) ((UINTN) (VbeModeInfo + 1) - SegmentC);
>
> + //
> + // Get NULL pointer detection back
> + //
> + if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0) {
> + Status = gDS->SetMemorySpaceAttributes (0, EFI_PAGES_TO_SIZE(1),
> + EFI_MEMORY_RP);
> + ASSERT_EFI_ERROR (Status);
> + }
> +
> DEBUG ((EFI_D_INFO, "%a: VBE shim installed\n", __FUNCTION__));
> }
>
(6) The InstallVbeShim() function actually contains *two* earlier exits
than this. Please search the function for "return" statements.
I suggest the following:
- put the restoration of the original page attributes at the very end of
the function,
- put a label called "RestoreSegment0Attributes" between the DEBUG
message and the page attributes restoration,
- replace the "return" statements with "goto RestoreSegment0Attributes".
Thanks!
Laszlo
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 6/6] OvmfPkg/QemuVideoDxe: Bypass NULL pointer detection during VBE SHIM installing
2017-09-22 11:50 ` Laszlo Ersek
@ 2017-09-22 15:29 ` Laszlo Ersek
2017-09-25 1:04 ` Wang, Jian J
0 siblings, 1 reply; 14+ messages in thread
From: Laszlo Ersek @ 2017-09-22 15:29 UTC (permalink / raw)
To: Jian J Wang, edk2-devel
Cc: Star Zeng, Eric Dong, Jiewen Yao, Michael Kinney, Jordan Justen,
Ayellet Wolman
On 09/22/17 13:50, Laszlo Ersek wrote:
> This patch looks great to me, I would like to request a few small
> updates:
>
> On 09/21/17 07:20, Jian J Wang wrote:
>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
>
> (1) please replace the word "install" with "link".
>
> The VBE Shim is technically installed into the "real-mode" C segment,
> only the int 0x10 vector lives in page 0.
>
>> detection is enabled, this driver will fail to load. NULL pointer detection
>> bypassing code is added to prevent such problem during boot.
>>
>> Please note that Windows 7 will try to access VBE SHIM during boot if it's
>> installed, and then cause boot failure. This can be fixed by setting BIT7
>> of PcdNullPointerDetectionPropertyMask to disable NULL pointer detection
>> after EndOfDxe. As far as we know, there's no other OSs has such issue.
>
> This is not a request, just a comment: I verified the default value in
> the .dec, and I see it is 0. So there's no need to post an additional
> patch for the OVMF DSC files, in order to set BIT7.
Actually, let me take a step back, and re-think the necessity of all
this work for QemuVideoDxe!
The facts are:
(1) The *only* purpose of the VBE Shim is to allow Windows 7 to boot in
pure UEFI mode (i.e. without a CSM).
(2) If I understand correctly, you guys have verified that Windows 7
cannot boot with the page0 protection enabled, *regardless* of what we
do in QemuVideoDxe. Can you confirm this please?
With the above in mind, let's consider the effects of the
"PcdNullPointerDetectionPropertyMask" bits:
* BIT0 clear:
- The page0 protection is completely disabled.
- This patch does nothing, in effect.
- The VBE Shim works.
- Windows 7 boots.
* BIT0 set, BIT7 also set:
- The page0 protection is disabled in the DXE core at the end of DXE.
- This patch does nothing, in effect.
- The VBE Shim works, because it is a UEFI driver, and it connects its
devices (and installs the shim) after End-of-Dxe, at which point
page0 protection is no longer in effect.
- Windows 7 boots fine, again because it is loaded after End-of-Dxe.
* BIT0 set, BIT7 clear:
- The page0 protection is never disabled until the OS (loader)
installs its own page tables.
- This patch enables the VBE Shim to work, by temporarily disabling
page0 protection.
- However, Windows 7 will fail to boot nonetheless, because it cannot
cope with page0 protection. (This is fact (2).)
Now, if you consider fact (1) as well: given that Windows 7 cannot boot
with page0 protection enabled *anyway*, why mess with the VBE Shim at
all?
How about the following patch instead:
> diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.c b/OvmfPkg/QemuVideoDxe/VbeShim.c
> index e45a08e8873f..8ba5522cde3c 100644
> --- a/OvmfPkg/QemuVideoDxe/VbeShim.c
> +++ b/OvmfPkg/QemuVideoDxe/VbeShim.c
> @@ -75,6 +75,20 @@ InstallVbeShim (
> UINTN Printed;
> VBE_MODE_INFO *VbeModeInfo;
>
> + if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0) {
> + DEBUG ((
> + DEBUG_WARN,
> + "%a: page 0 protected, not installing VBE shim\n",
> + __FUNCTION__
> + ));
> + DEBUG ((
> + DEBUG_WARN,
> + "%a: page 0 protection prevents Windows 7 from booting anyway\n",
> + __FUNCTION__
> + ));
> + return;
> + }
> +
> Segment0 = 0x00000;
> SegmentC = 0xC0000;
> SegmentF = 0xF0000;
Thanks!
Laszlo
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 6/6] OvmfPkg/QemuVideoDxe: Bypass NULL pointer detection during VBE SHIM installing
2017-09-22 15:29 ` Laszlo Ersek
@ 2017-09-25 1:04 ` Wang, Jian J
0 siblings, 0 replies; 14+ messages in thread
From: Wang, Jian J @ 2017-09-25 1:04 UTC (permalink / raw)
To: Laszlo Ersek, edk2-devel@lists.01.org
Cc: Zeng, Star, Dong, Eric, Yao, Jiewen, Kinney, Michael D,
Justen, Jordan L, Wolman, Ayellet
You're right that there's no such need. I just saw that this driver is loaded
before EndOfDxe but missed the fact that it's actually started after that.
So BIT7 of PcdNullPointerDetectionPropertyMask is enough.
And thanks a lot for other feedbacks in another emails, especially for the
catching of potential attributes overridden issue, which also exists in other
part of code.
> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Friday, September 22, 2017 11:29 PM
> To: Wang, Jian J <jian.j.wang@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>; Dong, Eric <eric.dong@intel.com>; Yao,
> Jiewen <jiewen.yao@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>;
> Wolman, Ayellet <ayellet.wolman@intel.com>
> Subject: Re: [PATCH v2 6/6] OvmfPkg/QemuVideoDxe: Bypass NULL pointer
> detection during VBE SHIM installing
>
> On 09/22/17 13:50, Laszlo Ersek wrote:
> > This patch looks great to me, I would like to request a few small
> > updates:
> >
> > On 09/21/17 07:20, Jian J Wang wrote:
> >> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
> >
> > (1) please replace the word "install" with "link".
> >
> > The VBE Shim is technically installed into the "real-mode" C segment,
> > only the int 0x10 vector lives in page 0.
> >
> >> detection is enabled, this driver will fail to load. NULL pointer detection
> >> bypassing code is added to prevent such problem during boot.
> >>
> >> Please note that Windows 7 will try to access VBE SHIM during boot if it's
> >> installed, and then cause boot failure. This can be fixed by setting BIT7
> >> of PcdNullPointerDetectionPropertyMask to disable NULL pointer detection
> >> after EndOfDxe. As far as we know, there's no other OSs has such issue.
> >
> > This is not a request, just a comment: I verified the default value in
> > the .dec, and I see it is 0. So there's no need to post an additional
> > patch for the OVMF DSC files, in order to set BIT7.
>
> Actually, let me take a step back, and re-think the necessity of all
> this work for QemuVideoDxe!
>
> The facts are:
>
> (1) The *only* purpose of the VBE Shim is to allow Windows 7 to boot in
> pure UEFI mode (i.e. without a CSM).
>
> (2) If I understand correctly, you guys have verified that Windows 7
> cannot boot with the page0 protection enabled, *regardless* of what we
> do in QemuVideoDxe. Can you confirm this please?
>
> With the above in mind, let's consider the effects of the
> "PcdNullPointerDetectionPropertyMask" bits:
>
> * BIT0 clear:
> - The page0 protection is completely disabled.
> - This patch does nothing, in effect.
> - The VBE Shim works.
> - Windows 7 boots.
>
> * BIT0 set, BIT7 also set:
> - The page0 protection is disabled in the DXE core at the end of DXE.
> - This patch does nothing, in effect.
> - The VBE Shim works, because it is a UEFI driver, and it connects its
> devices (and installs the shim) after End-of-Dxe, at which point
> page0 protection is no longer in effect.
> - Windows 7 boots fine, again because it is loaded after End-of-Dxe.
>
> * BIT0 set, BIT7 clear:
> - The page0 protection is never disabled until the OS (loader)
> installs its own page tables.
> - This patch enables the VBE Shim to work, by temporarily disabling
> page0 protection.
> - However, Windows 7 will fail to boot nonetheless, because it cannot
> cope with page0 protection. (This is fact (2).)
>
> Now, if you consider fact (1) as well: given that Windows 7 cannot boot
> with page0 protection enabled *anyway*, why mess with the VBE Shim at
> all?
>
> How about the following patch instead:
>
> > diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.c
> b/OvmfPkg/QemuVideoDxe/VbeShim.c
> > index e45a08e8873f..8ba5522cde3c 100644
> > --- a/OvmfPkg/QemuVideoDxe/VbeShim.c
> > +++ b/OvmfPkg/QemuVideoDxe/VbeShim.c
> > @@ -75,6 +75,20 @@ InstallVbeShim (
> > UINTN Printed;
> > VBE_MODE_INFO *VbeModeInfo;
> >
> > + if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
> {
> > + DEBUG ((
> > + DEBUG_WARN,
> > + "%a: page 0 protected, not installing VBE shim\n",
> > + __FUNCTION__
> > + ));
> > + DEBUG ((
> > + DEBUG_WARN,
> > + "%a: page 0 protection prevents Windows 7 from booting anyway\n",
> > + __FUNCTION__
> > + ));
> > + return;
> > + }
> > +
> > Segment0 = 0x00000;
> > SegmentC = 0xC0000;
> > SegmentF = 0xF0000;
>
> Thanks!
> Laszlo
^ permalink raw reply [flat|nested] 14+ messages in thread