public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
@ 2017-09-13  8:07 Wang, Jian J
  0 siblings, 0 replies; 37+ messages in thread
From: Wang, Jian J @ 2017-09-13  8:07 UTC (permalink / raw)
  To: edk2-devel

QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer detection is enabled, page 0 must be enabled temporarily before installing and disabled again afterwards. For Windows 7 boot, BIT7 of PcdNullPointerDetectionPropertyMask must still be set to avoid hang.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Justen, Jordan L <jordan.l.justen@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
---
 OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
 OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
 OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
index 0dce80e59b..ee0eed7214 100644
--- a/OvmfPkg/QemuVideoDxe/Driver.c
+++ b/OvmfPkg/QemuVideoDxe/Driver.c
@@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
   PCI_TYPE00                        Pci;
   QEMU_VIDEO_CARD                   *Card;
   EFI_PCI_IO_PROTOCOL               *ChildPciIo;
+  EFI_CPU_ARCH_PROTOCOL             *Cpu;
 
   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 
@@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
 #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
   if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
       Private->Variant == QEMU_VIDEO_BOCHS) {
-    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
+    //
+    // Prepare CPU arch protocol for NULL pointer detection
+    //
+    Status = gBS->LocateProtocol (
+                    &gEfiCpuArchProtocolGuid,
+                    NULL, 
+                    (VOID **) &Cpu
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    DISABLE_NULL_DETECTION(Cpu);
+      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
+    ENABLE_NULL_DETECTION(Cpu);
   }
 #endif
 
diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
index 7fbb25b3ef..bb3bc6eb0f 100644
--- a/OvmfPkg/QemuVideoDxe/Qemu.h
+++ b/OvmfPkg/QemuVideoDxe/Qemu.h
@@ -25,6 +25,7 @@
 #include <Protocol/PciIo.h>
 #include <Protocol/DriverSupportedEfiVersion.h>
 #include <Protocol/DevicePath.h>
+#include <Protocol/Cpu.h>
 
 #include <Library/DebugLib.h>
 #include <Library/UefiDriverEntryPoint.h>
@@ -82,6 +83,21 @@ typedef struct {
 
 #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
 
+//
+// VBE code will access memory between 0-4095 which will cause page fault exception 
+// if NULL pointer detection mechanism is enabled. Following macros can be used to 
+// disable/enable NULL pointer detection before/after accessing those memory.
+//
+#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
+#define DISABLE_NULL_DETECTION(Cpu)                                             \
+  if (NULL_DETECTION_ENABLED) {                                                 \
+    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
+  }
+#define ENABLE_NULL_DETECTION(Cpu)                                              \
+  if (NULL_DETECTION_ENABLED) {                                                 \
+    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
+  }
+
 //
 // QEMU Video Private Data Structure
 //
diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
index 7c7d429bca..5d166eb99c 100644
--- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
@@ -72,7 +72,9 @@
   gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
   gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
   gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
+  gEfiCpuArchProtocolGuid
 
 [Pcd]
   gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
+  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
 
-- 
2.14.1.windows.1




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

* [PATCH 0/4] Implement NULL pointer detection feature for special pool
       [not found] <Implement NULL pointer detection feature>
@ 2017-09-13  9:25 ` Wang, Jian J
  2017-09-13  9:25   ` [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core Wang, Jian J
                     ` (3 more replies)
  0 siblings, 4 replies; 37+ messages in thread
From: Wang, Jian J @ 2017-09-13  9:25 UTC (permalink / raw)
  To: edk2-devel

The mechanism behind is to trigger a page fault exception at address 0. This can be made by disabling page 0 (0-4095) during page table setup. So this feature can only be available on platform with paging enabled. Once this feature is enabled, any code, like CSM, which has to access memory in page 0 needs to enable this page temporarily in advance and disable it afterwards. PcdNullPointerDetectionPropertyMask is used to control and elaborate the use cases. For example, BIT7 of this PCD must be set for Windows 7 boot on Qemu if BIT0 set; or boot will fail.

Wang, Jian J (4):
  Implement NULL pointer detection in EDK-II Core.
  Implement NULL pointer detection for SMM mode code.
  Update CSM code to temporarily bypass NULL pointer detection if
    enabled.
  Update QemuVideoDxe driver to bypass NULL pointer detection if
    enabled.

 .../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c       | 10 +++-
 .../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h       | 18 +++++++
 .../Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf      |  2 +
 .../Csm/LegacyBiosDxe/LegacyBda.c                  |  4 ++
 .../Csm/LegacyBiosDxe/LegacyBios.c                 | 55 ++++++++++++++++++----
 .../Csm/LegacyBiosDxe/LegacyBiosDxe.inf            |  2 +
 .../Csm/LegacyBiosDxe/LegacyBiosInterface.h        | 23 +++++++++
 .../Csm/LegacyBiosDxe/LegacyBootSupport.c          | 33 ++++++++++---
 .../Csm/LegacyBiosDxe/LegacyPci.c                  | 17 ++++++-
 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c  | 41 ++++++++++------
 MdeModulePkg/Core/Dxe/DxeMain.inf                  |  3 +-
 MdeModulePkg/Core/Dxe/Mem/Page.c                   | 21 +++++----
 MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c      | 47 ++++++++++++++++++
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.h              | 15 ++++++
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf            |  3 +-
 MdeModulePkg/Core/DxeIplPeim/DxeLoad.c             | 53 +++++++++++++++++++++
 MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c    |  8 +++-
 MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c     |  2 +
 MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c   | 23 ++++++---
 MdeModulePkg/MdeModulePkg.dec                      | 12 +++++
 OvmfPkg/QemuVideoDxe/Driver.c                      | 15 +++++-
 OvmfPkg/QemuVideoDxe/Qemu.h                        | 16 +++++++
 OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf              |  2 +
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c           | 11 +++++
 UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c              | 25 +++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h         |  2 +
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf       | 17 +++----
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c            | 11 +++++
 28 files changed, 429 insertions(+), 62 deletions(-)

-- 
2.14.1.windows.1



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

* [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.
  2017-09-13  9:25 ` [PATCH 0/4] Implement NULL pointer detection feature for special pool Wang, Jian J
@ 2017-09-13  9:25   ` Wang, Jian J
  2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
  2017-09-13 17:28     ` Jordan Justen
  2017-09-13  9:25   ` [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code Wang, Jian J
                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 37+ messages in thread
From: Wang, Jian J @ 2017-09-13  9:25 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jiewen Yao, Eric Dong, Star Zeng, Laszlo Ersek, Justen, Jordan L,
	Kinney, Michael D, Wolman, Ayellet

The mechanism behind is to trigger a page fault exception at address 0. This can be made by disabling page 0 (0-4095) during page table setup. So this feature can only be available on platform with paging enabled. Once this feature is enabled, any code, like CSM, which has to access memory in page 0 needs to enable this page temporarily in advance and disable it afterwards. PcdNullPointerDetectionPropertyMask is used to control and elaborate the use cases.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Justen, Jordan L <jordan.l.justen@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
---
 MdeModulePkg/Core/Dxe/DxeMain.inf                |  3 +-
 MdeModulePkg/Core/Dxe/Mem/Page.c                 | 21 ++++++----
 MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c    | 47 +++++++++++++++++++++
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.h            | 15 +++++++
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf          |  3 +-
 MdeModulePkg/Core/DxeIplPeim/DxeLoad.c           | 53 ++++++++++++++++++++++++
 MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c  |  8 +++-
 MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c   |  2 +
 MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 23 ++++++----
 MdeModulePkg/MdeModulePkg.dec                    | 12 ++++++
 10 files changed, 167 insertions(+), 20 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
index 30d5984f7c..273b8b7c0e 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.inf
+++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -179,7 +179,7 @@
   gEfiWatchdogTimerArchProtocolGuid             ## CONSUMES
 
 [FeaturePcd]
-  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport	   ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport          ## CONSUMES
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber    ## SOMETIMES_CONSUMES
@@ -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..2e0b72f864 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Page.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Page.c
@@ -170,6 +170,7 @@ CoreAddRange (
 {
   LIST_ENTRY        *Link;
   MEMORY_MAP        *Entry;
+  EFI_STATUS        Status;
 
   ASSERT ((Start & EFI_PAGE_MASK) == 0);
   ASSERT (End > Start) ;
@@ -188,7 +189,17 @@ 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);
+    } else if (gCpu != NULL) {
+      Status = gCpu->SetMemoryAttributes(gCpu, 0, EFI_PAGE_SIZE, 0);
+      ASSERT_EFI_ERROR(Status);
+
+      SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);
+
+      Status = gCpu->SetMemoryAttributes(gCpu, 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);
+      ASSERT_EFI_ERROR(Status);
+    }
   }
   
   //
@@ -1972,11 +1983,3 @@ Done:
   return Status;
 }
 
-
-
-
-
-
-
-
-
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
index a73c4ccd64..2367d674e1 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,22 @@ 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 ;
 }
 
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
index 72d2532f50..104599156c 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
@@ -52,6 +52,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define STACK_SIZE      0x20000
 #define BSP_STORE_SIZE  0x4000
 
+#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT0) != 0)
 
 //
 // This PPI is installed to indicate the end of the PEI usage of memory
@@ -240,4 +241,18 @@ 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
+  );
+
 #endif
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
index c54afe4aa6..fde70f94bb 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
@@ -110,11 +110,12 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables       ## CONSUMES
 
 [FeaturePcd]
-  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress         ## CONSUMES
 
 [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..b5f9d92f5b 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
@@ -825,3 +825,56 @@ 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          RscDescHob;
+  EFI_PEI_HOB_POINTERS          MemAllocHob;
+  BOOLEAN                       DoClear;
+
+  RscDescHob.Raw = HobStart;
+  MemAllocHob.Raw = HobStart;
+  DoClear = FALSE;
+
+  //
+  // Check if page 0 exists and free
+  //
+  while ((RscDescHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, RscDescHob.Raw)) != NULL) {
+    if (RscDescHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && 
+        RscDescHob.ResourceDescriptor->PhysicalStart == 0) {
+      DoClear = TRUE;
+      // 
+      // Make sure memory at 0-4095 has not been allocated.
+      //
+      while ((MemAllocHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, MemAllocHob.Raw)) != NULL) {
+        if (MemAllocHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress < EFI_PAGE_SIZE) {
+          DoClear = FALSE;
+          break;
+        }
+        MemAllocHob.Raw = GET_NEXT_HOB (MemAllocHob);
+      }
+      break;
+    }
+    RscDescHob.Raw = GET_NEXT_HOB (RscDescHob);
+  }
+
+  if (DoClear) {
+    DEBUG((DEBUG_INFO, "Clearing first 4K-page!\r\n"));
+    SetMem(NULL, EFI_PAGE_SIZE, 0);
+  }
+
+  return;
+}
+
diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
index 1957326caf..a8aa0d5d1b 100644
--- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
+++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
@@ -123,7 +123,8 @@ Create4GPageTablesIa32Pae (
     PageDirectoryPointerEntry->Bits.Present = 1;
 
     for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {
-      if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase)) {
+      if ((NULL_DETECTION_ENABLED && PhysicalAddress == 0)
+          || ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase))) {
         //
         // Need to split this 2M page that covers stack range.
         //
@@ -240,6 +241,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 +382,8 @@ 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) || NULL_DETECTION_ENABLED));
     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..50a8d77a5b 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..ccd6e10cb2 100644
--- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
+++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
@@ -90,8 +90,14 @@ Split2MPageTo4K (
     //
     PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;
     PageTableEntry->Bits.ReadWrite = 1;
-    PageTableEntry->Bits.Present = 1;
-    if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + StackSize)) {
+
+    if (NULL_DETECTION_ENABLED && 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 +143,10 @@ Split1GPageTo2M (
 
   PhysicalAddress2M = PhysicalAddress;
   for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {
-    if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + SIZE_2MB) > StackBase)) {
+    if ((NULL_DETECTION_ENABLED && 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 +286,8 @@ 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 ((NULL_DETECTION_ENABLED && PageAddress == 0)
+            || (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_1GB) > StackBase))) {
           Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize);
         } else {
           //
@@ -308,9 +316,10 @@ 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 ((NULL_DETECTION_ENABLED && 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 {
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 593bff357a..1cc84894af 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -860,6 +860,18 @@
   # @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] 37+ messages in thread

* [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code.
  2017-09-13  9:25 ` [PATCH 0/4] Implement NULL pointer detection feature for special pool Wang, Jian J
  2017-09-13  9:25   ` [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core Wang, Jian J
@ 2017-09-13  9:25   ` Wang, Jian J
  2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
  2017-09-13 17:31     ` Jordan Justen
  2017-09-13  9:25   ` [PATCH 3/4] IntelFrameworkModulePkg/Csm: Update CSM code to temporarily bypass NULL pointer detection if enabled Wang, Jian J
  2017-09-13  9:25   ` [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to " Wang, Jian J
  3 siblings, 2 replies; 37+ messages in thread
From: Wang, Jian J @ 2017-09-13  9:25 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jiewen Yao, Eric Dong, Star Zeng, Laszlo Ersek, Justen, Jordan L,
	Kinney, Michael D, Wolman, Ayellet

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: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Justen, Jordan L <jordan.l.justen@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
---
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c     | 11 +++++++++++
 UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c        | 25 ++++++++++++++++++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h   |  2 ++
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf | 17 +++++++++--------
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c      | 11 +++++++++++
 5 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
index f295c2ebf2..d423958783 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
@@ -155,6 +155,17 @@ SmiPFHandler (
     }
   }
 
+  //
+  // If NULL pointer was just accessed
+  //
+  if (NULL_DETECTION_ENABLED && (PFAddress >= 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..81c5ac9d11 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 (NULL_DETECTION_ENABLED) {
+    Pte = (UINT64*)(UINT64)(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*)(UINT64)(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.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
index 1cf85c1481..bcb3032db8 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -153,6 +153,8 @@ typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;
 #define ARRIVAL_EXCEPTION_DELAYED           0x2
 #define ARRIVAL_EXCEPTION_SMI_DISABLED      0x4
 
+#define NULL_DETECTION_ENABLED    ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT1) != 0)
+
 //
 // Private structure for the SMM CPU module that is stored in DXE Runtime memory
 // Contains the SMM Configuration Protocols that is produced.
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
index 099792e6ce..57a14d9f24 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -138,14 +138,14 @@
   gEdkiiPiSmmMemoryAttributesTableGuid     ## CONSUMES ## SystemTable
 
 [FeaturePcd]
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                         ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp            ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection             ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport                   ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                    ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable                 ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer             ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock         ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                           ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp              ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection               ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport                     ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                      ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable                   ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer               ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock           ## CONSUMES
 
 [Pcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber        ## SOMETIMES_CONSUMES
@@ -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..e67bcfe0f6 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
@@ -872,6 +872,17 @@ SmiPFHandler (
     }
   }
 
+  //
+  // If NULL pointer was just accessed
+  //
+  if (NULL_DETECTION_ENABLED && (PFAddress >= 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] 37+ messages in thread

* [PATCH 3/4] IntelFrameworkModulePkg/Csm: Update CSM code to temporarily bypass NULL pointer detection if enabled.
  2017-09-13  9:25 ` [PATCH 0/4] Implement NULL pointer detection feature for special pool Wang, Jian J
  2017-09-13  9:25   ` [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core Wang, Jian J
  2017-09-13  9:25   ` [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code Wang, Jian J
@ 2017-09-13  9:25   ` Wang, Jian J
  2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
  2017-09-13  9:25   ` [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to " Wang, Jian J
  3 siblings, 1 reply; 37+ messages in thread
From: Wang, Jian J @ 2017-09-13  9:25 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jiewen Yao, Eric Dong, Star Zeng, Laszlo Ersek, Justen, Jordan L,
	Kinney, Michael D, Wolman, Ayellet

CSM code has to access memory below 4096 (BDA, int vector, etc.). If NULL pointer detection is enabled, the page 0 must be enabled temporarily before accessing it and disabled again afterwards. Otherwise page fault will be triggered.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Justen, Jordan L <jordan.l.justen@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
---
 .../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c       | 10 +++-
 .../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h       | 18 +++++++
 .../Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf      |  2 +
 .../Csm/LegacyBiosDxe/LegacyBda.c                  |  4 ++
 .../Csm/LegacyBiosDxe/LegacyBios.c                 | 55 ++++++++++++++++++----
 .../Csm/LegacyBiosDxe/LegacyBiosDxe.inf            |  2 +
 .../Csm/LegacyBiosDxe/LegacyBiosInterface.h        | 23 +++++++++
 .../Csm/LegacyBiosDxe/LegacyBootSupport.c          | 33 ++++++++++---
 .../Csm/LegacyBiosDxe/LegacyPci.c                  | 17 ++++++-
 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c  | 41 ++++++++++------
 10 files changed, 173 insertions(+), 32 deletions(-)

diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
index 7308523ad8..96148ae367 100644
--- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
@@ -248,7 +248,7 @@ BiosKeyboardDriverBindingStart (
   //
   // Allocate the private device structure
   //
-    BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_DEV));
+  BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_DEV));
   if (NULL == BiosKeyboardPrivate) {
     Status = EFI_OUT_OF_RESOURCES;
     goto Done;
@@ -281,6 +281,9 @@ BiosKeyboardDriverBindingStart (
   BiosKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify;    
   InitializeListHead (&BiosKeyboardPrivate->NotifyList);
 
+  Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &BiosKeyboardPrivate->Cpu);
+  ASSERT_EFI_ERROR(Status);
+
   //
   // Report that the keyboard is being enabled
   //
@@ -1842,7 +1845,9 @@ BiosKeyboardTimerHandler (
   //
   // Clear the CTRL and ALT BDA flag
   //
-  KbFlag1 = *((UINT8 *) (UINTN) 0x417);  // read the STATUS FLAGS 1
+  DISABLE_NULL_DETECTION(BiosKeyboardPrivate);
+
+  KbFlag1 = *((UINT8 *) (UINTN) 0x417); // read the STATUS FLAGS 1
   KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2
 
   DEBUG_CODE (
@@ -1916,6 +1921,7 @@ BiosKeyboardTimerHandler (
   KbFlag1 &= ~0x0C;                      
   *((UINT8 *) (UINTN) 0x417) = KbFlag1; 
 
+  ENABLE_NULL_DETECTION(BiosKeyboardPrivate);
   
   //
   // 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..b717ef676b 100644
--- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h
@@ -26,6 +26,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/IsaIo.h>
 #include <Protocol/DevicePath.h>
 #include <Protocol/Ps2Policy.h>
+#include <Protocol/Cpu.h>
 
 #include <Library/DebugLib.h>
 #include <Library/UefiLib.h>
@@ -212,6 +213,7 @@ typedef struct {
   EFI_HANDLE                                  Handle;
   EFI_LEGACY_BIOS_PROTOCOL                    *LegacyBios;
   EFI_ISA_IO_PROTOCOL                         *IsaIo;
+  EFI_CPU_ARCH_PROTOCOL                       *Cpu;
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL              SimpleTextIn;
   EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL           SimpleTextInputEx;
   UINT16                                      DataRegisterAddress;
@@ -242,6 +244,22 @@ typedef struct {
       BIOS_KEYBOARD_DEV_SIGNATURE \
       )
 
+//
+// CSM needs to access memory between 0-4095, which will cause page fault exception 
+// if NULL pointer detection mechanism is enabled. Following macros can be used
+// to disable/enable NULL pointer detection before/after accessing those memory.
+//
+#define NULL_POINTER_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT0) != 0)
+#define DISABLE_NULL_DETECTION(Instance)                                        \
+  if (NULL_POINTER_DETECTION_ENABLED && (Instance)->Cpu != NULL) {              \
+    (Instance)->Cpu->SetMemoryAttributes((Instance)->Cpu, 0, EFI_PAGE_SIZE, 0); \
+  }
+  
+#define ENABLE_NULL_DETECTION(Instance)                                                     \
+  if (NULL_POINTER_DETECTION_ENABLED && (Instance)->Cpu != NULL) {                          \
+    (Instance)->Cpu->SetMemoryAttributes((Instance)->Cpu, 0, EFI_PAGE_SIZE, EFI_MEMORY_RP); \
+  }
+
 //
 // Global Variables
 //
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf
index 4d4536466c..4291a10123 100644
--- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf
@@ -67,12 +67,14 @@
   gEfiSimpleTextInputExProtocolGuid             ## BY_START
   gEfiLegacyBiosProtocolGuid                    ## CONSUMES
   gEfiPs2PolicyProtocolGuid                     ## SOMETIMES_CONSUMES
+  gEfiCpuArchProtocolGuid                       ## SOMETIMES_CONSUMES
 
 [FeaturePcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification|FALSE  ## CONSUMES
 
 [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..e7cee4b8a3 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c
@@ -34,6 +34,8 @@ LegacyBiosInitBda (
   BDA_STRUC *Bda;
   UINT8     *Ebda;
 
+  DISABLE_NULL_DETECTION(Private);
+
   Bda   = (BDA_STRUC *) ((UINTN) 0x400);
   Ebda  = (UINT8 *) ((UINTN) 0x9fc00);
 
@@ -62,5 +64,7 @@ LegacyBiosInitBda (
 
   *Ebda               = 0x01;
 
+  ENABLE_NULL_DETECTION(Private);
+
   return EFI_SUCCESS;
 }
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
index 3ead2d9828..c3ef542ea3 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,26 @@ 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;
+}
+
 /**
   Install Driver to produce Legacy BIOS protocol.
 
@@ -802,6 +823,7 @@ LegacyBiosInstall (
   UINT64                             Length;
   UINT8                              *SecureBoot;
   EFI_EVENT                          InstallSmbiosEvent;
+  EFI_EVENT                          EndOfDxeEvent;
 
   //
   // Load this driver's image to memory
@@ -964,8 +986,10 @@ LegacyBiosInstall (
   // Initialize region from 0x0000 to 4k. This initializes interrupt vector
   // range.
   //
-  gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K);
-  ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00);
+  DISABLE_NULL_DETECTION(Private);
+    gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K);
+    ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00);
+  ENABLE_NULL_DETECTION(Private);
 
   //
   // Allocate pages for OPROM usage
@@ -1104,12 +1128,14 @@ LegacyBiosInstall (
   //
   // Save Unexpected interrupt vector so can restore it just prior to boot
   //
-  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);
-  }
+  DISABLE_NULL_DETECTION(Private);
+    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);
+    }
+  ENABLE_NULL_DETECTION(Private);
   //
   // Save EFI value
   //
@@ -1133,6 +1159,19 @@ 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..10dc392800 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
 
 [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..9d479309a4 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h
@@ -108,6 +108,27 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define NORMALIZE_EFI_SEGMENT(_Adr)      (UINT16) (((UINTN) (_Adr)) >> 4)
 #define NORMALIZE_EFI_OFFSET(_Adr)       (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xf)
 
+//
+// CSM needs to access memory between 0-4095, which will cause page fault exception 
+// if NULL pointer detection mechanism is enabled. Following macros can be used
+// to disable/enable NULL pointer detection before/after accessing those memory.
+//
+#define NULL_DETECTION_ENABLED                                                                        \
+  (  ((mEndOfDxe == FALSE) && ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT0) == BIT0))        \
+  || ((mEndOfDxe == TRUE)  && ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)) \
+  )
+#define DISABLE_NULL_DETECTION(Instance)                                        \
+  if (NULL_DETECTION_ENABLED) {                                                 \
+    DEBUG((DEBUG_INFO, "%a(): disable NULL detection\r\n",  __func__));         \
+    (Instance)->Cpu->SetMemoryAttributes((Instance)->Cpu, 0, EFI_PAGE_SIZE, 0); \
+  }
+  
+#define ENABLE_NULL_DETECTION(Instance)                                                     \
+  if (NULL_DETECTION_ENABLED) {                                                             \
+    (Instance)->Cpu->SetMemoryAttributes((Instance)->Cpu, 0, EFI_PAGE_SIZE, EFI_MEMORY_RP); \
+    DEBUG((DEBUG_INFO, "%a(): enable NULL detection\r\n",  __func__));                      \
+  }
+
 //
 // Trace defines
 //
@@ -509,6 +530,8 @@ extern BBS_TABLE           *mBbsTable;
 
 extern EFI_GENERIC_MEMORY_TEST_PROTOCOL *gGenMemoryTest;
 
+extern BOOLEAN mEndOfDxe;
+
 #define PORT_70 0x70
 #define PORT_71 0x71
 
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c
index 1e098b3726..d381c2f735 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;
-  BdaPtr    = (UINT32 *) (UINTN)0x46C;
-  *BdaPtr   = LocalTime;
+  DISABLE_NULL_DETECTION(Private);
+    BdaPtr    = (UINT32 *) (UINTN)0x46C;
+    *BdaPtr   = LocalTime;
+  ENABLE_NULL_DETECTION(Private);
 
   //
   // 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.
     //
     //
+    DISABLE_NULL_DETECTION(Private);
     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);
       }
     }
+    ENABLE_NULL_DETECTION(Private);
 
     ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
     Regs.X.AX = Legacy16Boot;
@@ -1340,10 +1344,12 @@ GenericLegacyBoot (
       0
       );
 
+    DISABLE_NULL_DETECTION(Private);
     BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);
     for (Index = 0; Index < 8; Index++) {
       BaseVectorMaster[Index] = Private->ThunkSavedInt[Index];
     }
+    ENABLE_NULL_DETECTION(Private);
   }
   Private->LegacyBootEntered = TRUE;
   if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {
@@ -1731,9 +1737,11 @@ LegacyBiosBuildE820 (
   //
   // First entry is 0 to (640k - EBDA)
   //
-  E820Table[0].BaseAddr  = 0;
-  E820Table[0].Length    = (UINT64) ((*(UINT16 *) (UINTN)0x40E) << 4);
-  E820Table[0].Type      = EfiAcpiAddressRangeMemory;
+  DISABLE_NULL_DETECTION(Private);
+    E820Table[0].BaseAddr  = 0;
+    E820Table[0].Length    = (UINT64) ((*(UINT16 *) (UINTN)0x40E) << 4);
+    E820Table[0].Type      = EfiAcpiAddressRangeMemory;
+  ENABLE_NULL_DETECTION(Private);
 
   //
   // Second entry is (640k - EBDA) to 640k
@@ -1967,6 +1975,8 @@ LegacyBiosCompleteBdaBeforeBoot (
   UINT16                      MachineConfig;
   DEVICE_PRODUCER_DATA_HEADER *SioPtr;
 
+  DISABLE_NULL_DETECTION(Private);
+
   Bda           = (BDA_STRUC *) ((UINTN) 0x400);
   MachineConfig = 0;
 
@@ -2025,6 +2035,8 @@ LegacyBiosCompleteBdaBeforeBoot (
   MachineConfig       = (UINT16) (MachineConfig + 0x00 + 0x02 + (SioPtr->MousePresent * 0x04));
   Bda->MachineConfig  = MachineConfig;
 
+  ENABLE_NULL_DETECTION(Private);
+
   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);
+
+  DISABLE_NULL_DETECTION(Private);
+
+  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);
+
+  ENABLE_NULL_DETECTION(Private);
+
   //
   // 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)
   //
+  DISABLE_NULL_DETECTION(Private);
   Bda = (UINT8)(*((UINT8 *)((UINTN)0x410)) | BIT3);
+  ENABLE_NULL_DETECTION(Private);
 
   //
   // Force display enabled
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c
index 8ffdf0c1ff..2ca5dddf00 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
   //
+  DISABLE_NULL_DETECTION(Private);
+
   LocalDiskStart = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);
   if ((Private->Disk4075 + 0x80) < LocalDiskStart) {
     //
@@ -2426,6 +2430,9 @@ LegacyBiosInstallRom (
     //
     VideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));
   }
+
+  ENABLE_NULL_DETECTION(Private);
+
   //
   // 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.
   //
+  DISABLE_NULL_DETECTION(Private);
   LocalTime = (LocalTime * 182) / 10;
   BdaPtr    = (UINT32 *) ((UINTN) 0x46C);
   *BdaPtr   = LocalTime;
+  ENABLE_NULL_DETECTION(Private);
   
   //
   // 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))) {
+    DISABLE_NULL_DETECTION(Private);
+    OldVideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));
+    ENABLE_NULL_DETECTION(Private);
+
+    if (VideoMode != OldVideoMode) {
       //
       // The active video mode is changed, restore it to original mode.
       //
@@ -2604,7 +2617,9 @@ LegacyBiosInstallRom (
     }
   }
 
+  DISABLE_NULL_DETECTION(Private);
   LocalDiskEnd = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);
+  ENABLE_NULL_DETECTION(Private);
   
   //
   // 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..50f6247a99 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;
+  DISABLE_NULL_DETECTION(Private);
+    Segment               = (UINT16)(((UINT32 *)0)[BiosInt] >> 16);
+    Offset                = (UINT16)((UINT32 *)0)[BiosInt];
+  ENABLE_NULL_DETECTION(Private);
   
   return InternalLegacyBiosFarCall (
            This,
-           (UINT16) ((VectorBase)[BiosInt] >> 16),
-           (UINT16) (VectorBase)[BiosInt],
+           Segment,
+           Offset,
            Regs,
            &Regs->X.Flags,
            sizeof (Regs->X.Flags)
@@ -288,16 +295,22 @@ InternalLegacyBiosFarCall (
   // EBDA base address, if the current EBDA base address is smaller, it indicates
   // PcdEbdaReservedMemorySize should be adjusted to larger for more OPROMs.
   //
-  DEBUG_CODE (
-    {
-      UINTN                 EbdaBaseAddress;
-      UINTN                 ReservedEbdaBaseAddress;
-
-      EbdaBaseAddress = (*(UINT16 *) (UINTN) 0x40E) << 4;
-      ReservedEbdaBaseAddress = CONVENTIONAL_MEMORY_TOP - PcdGet32 (PcdEbdaReservedMemorySize);
-      ASSERT (ReservedEbdaBaseAddress <= EbdaBaseAddress);
-    }
-  );
+  if (!NULL_DETECTION_ENABLED) {
+    // 
+    // Only do following if NULL pointer detection is not enabled, because it cannot 
+    // be disabled at this time due to current TPL(=TPL_HIGH_LEVEL).
+    //
+    DEBUG_CODE (
+      {
+        UINTN                 EbdaBaseAddress;
+        UINTN                 ReservedEbdaBaseAddress;
+
+        EbdaBaseAddress = (*(UINT16 *) (UINTN) 0x40E) << 4;
+        ReservedEbdaBaseAddress = CONVENTIONAL_MEMORY_TOP - PcdGet32 (PcdEbdaReservedMemorySize);
+        ASSERT (ReservedEbdaBaseAddress <= EbdaBaseAddress);
+      }
+    );
+  }
 
   if (Stack != NULL && StackSize != 0) {
     //
-- 
2.14.1.windows.1



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

* [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-13  9:25 ` [PATCH 0/4] Implement NULL pointer detection feature for special pool Wang, Jian J
                     ` (2 preceding siblings ...)
  2017-09-13  9:25   ` [PATCH 3/4] IntelFrameworkModulePkg/Csm: Update CSM code to temporarily bypass NULL pointer detection if enabled Wang, Jian J
@ 2017-09-13  9:25   ` Wang, Jian J
  2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
  2017-09-13 23:34     ` Laszlo Ersek
  3 siblings, 2 replies; 37+ messages in thread
From: Wang, Jian J @ 2017-09-13  9:25 UTC (permalink / raw)
  To: edk2-devel
  Cc: Jiewen Yao, Eric Dong, Star Zeng, Laszlo Ersek, Justen, Jordan L,
	Kinney, Michael D, Wolman, Ayellet

QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer detection is enabled, page 0 must be enabled temporarily before installing and disabled again afterwards. For Windows 7 boot, BIT7 of PcdNullPointerDetectionPropertyMask must still be set to avoid hang.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Justen, Jordan L <jordan.l.justen@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
---
 OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
 OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
 OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
index 0dce80e59b..ee0eed7214 100644
--- a/OvmfPkg/QemuVideoDxe/Driver.c
+++ b/OvmfPkg/QemuVideoDxe/Driver.c
@@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
   PCI_TYPE00                        Pci;
   QEMU_VIDEO_CARD                   *Card;
   EFI_PCI_IO_PROTOCOL               *ChildPciIo;
+  EFI_CPU_ARCH_PROTOCOL             *Cpu;
 
   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 
@@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
 #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
   if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
       Private->Variant == QEMU_VIDEO_BOCHS) {
-    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
+    //
+    // Prepare CPU arch protocol for NULL pointer detection
+    //
+    Status = gBS->LocateProtocol (
+                    &gEfiCpuArchProtocolGuid,
+                    NULL, 
+                    (VOID **) &Cpu
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    DISABLE_NULL_DETECTION(Cpu);
+      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
+    ENABLE_NULL_DETECTION(Cpu);
   }
 #endif
 
diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
index 7fbb25b3ef..bb3bc6eb0f 100644
--- a/OvmfPkg/QemuVideoDxe/Qemu.h
+++ b/OvmfPkg/QemuVideoDxe/Qemu.h
@@ -25,6 +25,7 @@
 #include <Protocol/PciIo.h>
 #include <Protocol/DriverSupportedEfiVersion.h>
 #include <Protocol/DevicePath.h>
+#include <Protocol/Cpu.h>
 
 #include <Library/DebugLib.h>
 #include <Library/UefiDriverEntryPoint.h>
@@ -82,6 +83,21 @@ typedef struct {
 
 #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
 
+//
+// VBE code will access memory between 0-4095 which will cause page fault exception 
+// if NULL pointer detection mechanism is enabled. Following macros can be used to 
+// disable/enable NULL pointer detection before/after accessing those memory.
+//
+#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
+#define DISABLE_NULL_DETECTION(Cpu)                                             \
+  if (NULL_DETECTION_ENABLED) {                                                 \
+    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
+  }
+#define ENABLE_NULL_DETECTION(Cpu)                                              \
+  if (NULL_DETECTION_ENABLED) {                                                 \
+    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
+  }
+
 //
 // QEMU Video Private Data Structure
 //
diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
index 7c7d429bca..5d166eb99c 100644
--- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
@@ -72,7 +72,9 @@
   gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
   gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
   gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
+  gEfiCpuArchProtocolGuid
 
 [Pcd]
   gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
+  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
 
-- 
2.14.1.windows.1



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

* Re: [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.
  2017-09-13  9:25   ` [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core Wang, Jian J
@ 2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
  2017-09-14  1:37       ` Wang, Jian J
  2017-09-13 17:28     ` Jordan Justen
  1 sibling, 1 reply; 37+ messages in thread
From: Johnson, Brian (EXL - Eagan) @ 2017-09-13 16:33 UTC (permalink / raw)
  To: Wang, Jian J, edk2-devel@lists.01.org
  Cc: Justen@ml01.01.org, Eric Dong, Kinney@ml01.01.org, Jordan L,
	Wolman@ml01.01.org, Jiewen Yao, Ayellet, Michael D, Laszlo Ersek,
	Star Zeng

ClearLegacyMemory() assumes that the memory allocation HOB comes after the resource descriptor HOB in the HOB list.  Is that guaranteed?  I'd think that the memory allocation HOB traversal should be a separate loop, after the resource descriptor HOB traversal loop.

Other than that:
Reviewed-by: Brian J. Johnson <brian.johnson@hpe.com>

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
Sent: Wednesday, September 13, 2017 4:25 AM
To: edk2-devel@lists.01.org
Cc: Justen@ml01.01.org; Eric Dong <eric.dong@intel.com>; Kinney@ml01.01.org; Jordan L <jordan.l.justen@intel.com>; Wolman@ml01.01.org; Jiewen Yao <jiewen.yao@intel.com>; Ayellet <ayellet.wolman@intel.com>; Michael D <michael.d.kinney@intel.com>; Laszlo Ersek <lersek@redhat.com>; Star Zeng <star.zeng@intel.com>
Subject: [edk2] [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.

The mechanism behind is to trigger a page fault exception at address 0. This can be made by disabling page 0 (0-4095) during page table setup. So this feature can only be available on platform with paging enabled. Once this feature is enabled, any code, like CSM, which has to access memory in page 0 needs to enable this page temporarily in advance and disable it afterwards. PcdNullPointerDetectionPropertyMask is used to control and elaborate the use cases.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Justen, Jordan L <jordan.l.justen@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
---
 MdeModulePkg/Core/Dxe/DxeMain.inf                |  3 +-
 MdeModulePkg/Core/Dxe/Mem/Page.c                 | 21 ++++++----
 MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c    | 47 +++++++++++++++++++++
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.h            | 15 +++++++
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf          |  3 +-
 MdeModulePkg/Core/DxeIplPeim/DxeLoad.c           | 53 ++++++++++++++++++++++++
 MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c  |  8 +++-
 MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c   |  2 +
 MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 23 ++++++----
 MdeModulePkg/MdeModulePkg.dec                    | 12 ++++++
 10 files changed, 167 insertions(+), 20 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
index 30d5984f7c..273b8b7c0e 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.inf
+++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -179,7 +179,7 @@
   gEfiWatchdogTimerArchProtocolGuid             ## CONSUMES
 
 [FeaturePcd]
-  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport	   ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport          ## CONSUMES
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber    ## SOMETIMES_CONSUMES
@@ -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..2e0b72f864 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Page.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Page.c
@@ -170,6 +170,7 @@ CoreAddRange (
 {
   LIST_ENTRY        *Link;
   MEMORY_MAP        *Entry;
+  EFI_STATUS        Status;
 
   ASSERT ((Start & EFI_PAGE_MASK) == 0);
   ASSERT (End > Start) ;
@@ -188,7 +189,17 @@ 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);
+    } else if (gCpu != NULL) {
+      Status = gCpu->SetMemoryAttributes(gCpu, 0, EFI_PAGE_SIZE, 0);
+      ASSERT_EFI_ERROR(Status);
+
+      SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);
+
+      Status = gCpu->SetMemoryAttributes(gCpu, 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);
+      ASSERT_EFI_ERROR(Status);
+    }
   }
   
   //
@@ -1972,11 +1983,3 @@ Done:
   return Status;
 }
 
-
-
-
-
-
-
-
-
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
index a73c4ccd64..2367d674e1 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,22 @@ 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 ;
 }
 
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
index 72d2532f50..104599156c 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
@@ -52,6 +52,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define STACK_SIZE      0x20000
 #define BSP_STORE_SIZE  0x4000
 
+#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT0) != 0)
 
 //
 // This PPI is installed to indicate the end of the PEI usage of memory
@@ -240,4 +241,18 @@ 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
+  );
+
 #endif
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
index c54afe4aa6..fde70f94bb 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
@@ -110,11 +110,12 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables       ## CONSUMES
 
 [FeaturePcd]
-  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress         ## CONSUMES
 
 [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..b5f9d92f5b 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
@@ -825,3 +825,56 @@ 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          RscDescHob;
+  EFI_PEI_HOB_POINTERS          MemAllocHob;
+  BOOLEAN                       DoClear;
+
+  RscDescHob.Raw = HobStart;
+  MemAllocHob.Raw = HobStart;
+  DoClear = FALSE;
+
+  //
+  // Check if page 0 exists and free
+  //
+  while ((RscDescHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, RscDescHob.Raw)) != NULL) {
+    if (RscDescHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && 
+        RscDescHob.ResourceDescriptor->PhysicalStart == 0) {
+      DoClear = TRUE;
+      // 
+      // Make sure memory at 0-4095 has not been allocated.
+      //
+      while ((MemAllocHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, MemAllocHob.Raw)) != NULL) {
+        if (MemAllocHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress < EFI_PAGE_SIZE) {
+          DoClear = FALSE;
+          break;
+        }
+        MemAllocHob.Raw = GET_NEXT_HOB (MemAllocHob);
+      }
+      break;
+    }
+    RscDescHob.Raw = GET_NEXT_HOB (RscDescHob);
+  }
+
+  if (DoClear) {
+    DEBUG((DEBUG_INFO, "Clearing first 4K-page!\r\n"));
+    SetMem(NULL, EFI_PAGE_SIZE, 0);
+  }
+
+  return;
+}
+
diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
index 1957326caf..a8aa0d5d1b 100644
--- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
+++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
@@ -123,7 +123,8 @@ Create4GPageTablesIa32Pae (
     PageDirectoryPointerEntry->Bits.Present = 1;
 
     for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {
-      if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase)) {
+      if ((NULL_DETECTION_ENABLED && PhysicalAddress == 0)
+          || ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase))) {
         //
         // Need to split this 2M page that covers stack range.
         //
@@ -240,6 +241,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 +382,8 @@ 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) || NULL_DETECTION_ENABLED));
     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..50a8d77a5b 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..ccd6e10cb2 100644
--- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
+++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
@@ -90,8 +90,14 @@ Split2MPageTo4K (
     //
     PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;
     PageTableEntry->Bits.ReadWrite = 1;
-    PageTableEntry->Bits.Present = 1;
-    if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + StackSize)) {
+
+    if (NULL_DETECTION_ENABLED && 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 +143,10 @@ Split1GPageTo2M (
 
   PhysicalAddress2M = PhysicalAddress;
   for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {
-    if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + SIZE_2MB) > StackBase)) {
+    if ((NULL_DETECTION_ENABLED && 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 +286,8 @@ 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 ((NULL_DETECTION_ENABLED && PageAddress == 0)
+            || (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_1GB) > StackBase))) {
           Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize);
         } else {
           //
@@ -308,9 +316,10 @@ 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 ((NULL_DETECTION_ENABLED && 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 {
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 593bff357a..1cc84894af 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -860,6 +860,18 @@
   # @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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code.
  2017-09-13  9:25   ` [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code Wang, Jian J
@ 2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
  2017-09-14  1:31       ` Wang, Jian J
  2017-09-13 17:31     ` Jordan Justen
  1 sibling, 1 reply; 37+ messages in thread
From: Johnson, Brian (EXL - Eagan) @ 2017-09-13 16:33 UTC (permalink / raw)
  To: Wang, Jian J, edk2-devel@lists.01.org
  Cc: Justen@ml01.01.org, Eric Dong, Kinney@ml01.01.org, Jordan L,
	Wolman@ml01.01.org, Jiewen Yao, Ayellet, Michael D, Laszlo Ersek,
	Star Zeng

Comments below.

Brian

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
Sent: Wednesday, September 13, 2017 4:25 AM
To: edk2-devel@lists.01.org
Cc: Justen@ml01.01.org; Eric Dong <eric.dong@intel.com>; Kinney@ml01.01.org; Jordan L <jordan.l.justen@intel.com>; Wolman@ml01.01.org; Jiewen Yao <jiewen.yao@intel.com>; Ayellet <ayellet.wolman@intel.com>; Michael D <michael.d.kinney@intel.com>; Laszlo Ersek <lersek@redhat.com>; Star Zeng <star.zeng@intel.com>
Subject: [edk2] [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code.

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: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Justen, Jordan L <jordan.l.justen@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
---
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c     | 11 +++++++++++
 UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c        | 25 ++++++++++++++++++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h   |  2 ++
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf | 17 +++++++++--------
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c      | 11 +++++++++++
 5 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
index f295c2ebf2..d423958783 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
@@ -155,6 +155,17 @@ SmiPFHandler (
     }
   }
 
+  //
+  // If NULL pointer was just accessed
+  //
+  if (NULL_DETECTION_ENABLED && (PFAddress >= 0 && PFAddress < EFI_PAGE_SIZE)) {

[Brian] PFAddress is unsigned, so it will always be >= 0.  Some compilers complain about this....  Should probably remove that part of the test.

+    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..81c5ac9d11 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 (NULL_DETECTION_ENABLED) {
+    Pte = (UINT64*)(UINT64)(Pdpte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));

[Brian] Shouldn't the inner cast be (UINTN), not (UINT64)?  That would match the PcdCpuSmmStackGuard section above.

+    if ((Pte[0] & IA32_PG_PS) == 0) {
+      // 4K-page entries are already mapped. Just hide the first one anyway.
+      Pte = (UINT64*)(UINT64)(Pte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));

[Brian] Same comment re. the inner cast.

+      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.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
index 1cf85c1481..bcb3032db8 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -153,6 +153,8 @@ typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;
 #define ARRIVAL_EXCEPTION_DELAYED           0x2
 #define ARRIVAL_EXCEPTION_SMI_DISABLED      0x4
 
+#define NULL_DETECTION_ENABLED    ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT1) != 0)
+
 //
 // Private structure for the SMM CPU module that is stored in DXE Runtime memory
 // Contains the SMM Configuration Protocols that is produced.
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
index 099792e6ce..57a14d9f24 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -138,14 +138,14 @@
   gEdkiiPiSmmMemoryAttributesTableGuid     ## CONSUMES ## SystemTable
 
 [FeaturePcd]
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                         ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp            ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection             ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport                   ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                    ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable                 ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer             ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock         ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                           ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp              ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection               ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport                     ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                      ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable                   ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer               ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock           ## CONSUMES
 
 [Pcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber        ## SOMETIMES_CONSUMES
@@ -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..e67bcfe0f6 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
@@ -872,6 +872,17 @@ SmiPFHandler (
     }
   }
 
+  //
+  // If NULL pointer was just accessed
+  //
+  if (NULL_DETECTION_ENABLED && (PFAddress >= 0 && PFAddress < EFI_PAGE_SIZE)) {

[Brian] PFAddress is unsigned, so it will always be >= 0.  Some compilers complain about this....  Should probably remove that part of the test.

+    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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 3/4] IntelFrameworkModulePkg/Csm: Update CSM code to temporarily bypass NULL pointer detection if enabled.
  2017-09-13  9:25   ` [PATCH 3/4] IntelFrameworkModulePkg/Csm: Update CSM code to temporarily bypass NULL pointer detection if enabled Wang, Jian J
@ 2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
  0 siblings, 0 replies; 37+ messages in thread
From: Johnson, Brian (EXL - Eagan) @ 2017-09-13 16:33 UTC (permalink / raw)
  To: Wang, Jian J, edk2-devel@lists.01.org
  Cc: Justen@ml01.01.org, Eric Dong, Kinney@ml01.01.org, Jordan L,
	Wolman@ml01.01.org, Jiewen Yao, Ayellet, Michael D, Laszlo Ersek,
	Star Zeng

Acked-by: Brian J. Johnson <brian.johnson@hpe.com>

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
Sent: Wednesday, September 13, 2017 4:25 AM
To: edk2-devel@lists.01.org
Cc: Justen@ml01.01.org; Eric Dong <eric.dong@intel.com>; Kinney@ml01.01.org; Jordan L <jordan.l.justen@intel.com>; Wolman@ml01.01.org; Jiewen Yao <jiewen.yao@intel.com>; Ayellet <ayellet.wolman@intel.com>; Michael D <michael.d.kinney@intel.com>; Laszlo Ersek <lersek@redhat.com>; Star Zeng <star.zeng@intel.com>
Subject: [edk2] [PATCH 3/4] IntelFrameworkModulePkg/Csm: Update CSM code to temporarily bypass NULL pointer detection if enabled.

CSM code has to access memory below 4096 (BDA, int vector, etc.). If NULL pointer detection is enabled, the page 0 must be enabled temporarily before accessing it and disabled again afterwards. Otherwise page fault will be triggered.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Justen, Jordan L <jordan.l.justen@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
---
 .../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c       | 10 +++-
 .../Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h       | 18 +++++++
 .../Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf      |  2 +
 .../Csm/LegacyBiosDxe/LegacyBda.c                  |  4 ++
 .../Csm/LegacyBiosDxe/LegacyBios.c                 | 55 ++++++++++++++++++----
 .../Csm/LegacyBiosDxe/LegacyBiosDxe.inf            |  2 +
 .../Csm/LegacyBiosDxe/LegacyBiosInterface.h        | 23 +++++++++
 .../Csm/LegacyBiosDxe/LegacyBootSupport.c          | 33 ++++++++++---
 .../Csm/LegacyBiosDxe/LegacyPci.c                  | 17 ++++++-
 IntelFrameworkModulePkg/Csm/LegacyBiosDxe/Thunk.c  | 41 ++++++++++------
 10 files changed, 173 insertions(+), 32 deletions(-)

diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
index 7308523ad8..96148ae367 100644
--- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
@@ -248,7 +248,7 @@ BiosKeyboardDriverBindingStart (
   //
   // Allocate the private device structure
   //
-    BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_DEV));
+  BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_DEV));
   if (NULL == BiosKeyboardPrivate) {
     Status = EFI_OUT_OF_RESOURCES;
     goto Done;
@@ -281,6 +281,9 @@ BiosKeyboardDriverBindingStart (
   BiosKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify;    
   InitializeListHead (&BiosKeyboardPrivate->NotifyList);
 
+  Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &BiosKeyboardPrivate->Cpu);
+  ASSERT_EFI_ERROR(Status);
+
   //
   // Report that the keyboard is being enabled
   //
@@ -1842,7 +1845,9 @@ BiosKeyboardTimerHandler (
   //
   // Clear the CTRL and ALT BDA flag
   //
-  KbFlag1 = *((UINT8 *) (UINTN) 0x417);  // read the STATUS FLAGS 1
+  DISABLE_NULL_DETECTION(BiosKeyboardPrivate);
+
+  KbFlag1 = *((UINT8 *) (UINTN) 0x417); // read the STATUS FLAGS 1
   KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2
 
   DEBUG_CODE (
@@ -1916,6 +1921,7 @@ BiosKeyboardTimerHandler (
   KbFlag1 &= ~0x0C;                      
   *((UINT8 *) (UINTN) 0x417) = KbFlag1; 
 
+  ENABLE_NULL_DETECTION(BiosKeyboardPrivate);
   
   //
   // 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..b717ef676b 100644
--- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.h
@@ -26,6 +26,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/IsaIo.h>
 #include <Protocol/DevicePath.h>
 #include <Protocol/Ps2Policy.h>
+#include <Protocol/Cpu.h>
 
 #include <Library/DebugLib.h>
 #include <Library/UefiLib.h>
@@ -212,6 +213,7 @@ typedef struct {
   EFI_HANDLE                                  Handle;
   EFI_LEGACY_BIOS_PROTOCOL                    *LegacyBios;
   EFI_ISA_IO_PROTOCOL                         *IsaIo;
+  EFI_CPU_ARCH_PROTOCOL                       *Cpu;
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL              SimpleTextIn;
   EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL           SimpleTextInputEx;
   UINT16                                      DataRegisterAddress;
@@ -242,6 +244,22 @@ typedef struct {
       BIOS_KEYBOARD_DEV_SIGNATURE \
       )
 
+//
+// CSM needs to access memory between 0-4095, which will cause page fault exception 
+// if NULL pointer detection mechanism is enabled. Following macros can be used
+// to disable/enable NULL pointer detection before/after accessing those memory.
+//
+#define NULL_POINTER_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT0) != 0)
+#define DISABLE_NULL_DETECTION(Instance)                                        \
+  if (NULL_POINTER_DETECTION_ENABLED && (Instance)->Cpu != NULL) {              \
+    (Instance)->Cpu->SetMemoryAttributes((Instance)->Cpu, 0, EFI_PAGE_SIZE, 0); \
+  }
+  
+#define ENABLE_NULL_DETECTION(Instance)                                                     \
+  if (NULL_POINTER_DETECTION_ENABLED && (Instance)->Cpu != NULL) {                          \
+    (Instance)->Cpu->SetMemoryAttributes((Instance)->Cpu, 0, EFI_PAGE_SIZE, EFI_MEMORY_RP); \
+  }
+
 //
 // Global Variables
 //
diff --git a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf
index 4d4536466c..4291a10123 100644
--- a/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf
+++ b/IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/KeyboardDxe.inf
@@ -67,12 +67,14 @@
   gEfiSimpleTextInputExProtocolGuid             ## BY_START
   gEfiLegacyBiosProtocolGuid                    ## CONSUMES
   gEfiPs2PolicyProtocolGuid                     ## SOMETIMES_CONSUMES
+  gEfiCpuArchProtocolGuid                       ## SOMETIMES_CONSUMES
 
 [FeaturePcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification|FALSE  ## CONSUMES
 
 [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..e7cee4b8a3 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBda.c
@@ -34,6 +34,8 @@ LegacyBiosInitBda (
   BDA_STRUC *Bda;
   UINT8     *Ebda;
 
+  DISABLE_NULL_DETECTION(Private);
+
   Bda   = (BDA_STRUC *) ((UINTN) 0x400);
   Ebda  = (UINT8 *) ((UINTN) 0x9fc00);
 
@@ -62,5 +64,7 @@ LegacyBiosInitBda (
 
   *Ebda               = 0x01;
 
+  ENABLE_NULL_DETECTION(Private);
+
   return EFI_SUCCESS;
 }
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c
index 3ead2d9828..c3ef542ea3 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,26 @@ 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;
+}
+
 /**
   Install Driver to produce Legacy BIOS protocol.
 
@@ -802,6 +823,7 @@ LegacyBiosInstall (
   UINT64                             Length;
   UINT8                              *SecureBoot;
   EFI_EVENT                          InstallSmbiosEvent;
+  EFI_EVENT                          EndOfDxeEvent;
 
   //
   // Load this driver's image to memory
@@ -964,8 +986,10 @@ LegacyBiosInstall (
   // Initialize region from 0x0000 to 4k. This initializes interrupt vector
   // range.
   //
-  gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K);
-  ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00);
+  DISABLE_NULL_DETECTION(Private);
+    gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K);
+    ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00);
+  ENABLE_NULL_DETECTION(Private);
 
   //
   // Allocate pages for OPROM usage
@@ -1104,12 +1128,14 @@ LegacyBiosInstall (
   //
   // Save Unexpected interrupt vector so can restore it just prior to boot
   //
-  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);
-  }
+  DISABLE_NULL_DETECTION(Private);
+    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);
+    }
+  ENABLE_NULL_DETECTION(Private);
   //
   // Save EFI value
   //
@@ -1133,6 +1159,19 @@ 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..10dc392800 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
 
 [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..9d479309a4 100644
--- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h
+++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h
@@ -108,6 +108,27 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define NORMALIZE_EFI_SEGMENT(_Adr)      (UINT16) (((UINTN) (_Adr)) >> 4)
 #define NORMALIZE_EFI_OFFSET(_Adr)       (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xf)
 
+//
+// CSM needs to access memory between 0-4095, which will cause page fault exception 
+// if NULL pointer detection mechanism is enabled. Following macros can be used
+// to disable/enable NULL pointer detection before/after accessing those memory.
+//
+#define NULL_DETECTION_ENABLED                                                                        \
+  (  ((mEndOfDxe == FALSE) && ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT0) == BIT0))        \
+  || ((mEndOfDxe == TRUE)  && ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)) \
+  )
+#define DISABLE_NULL_DETECTION(Instance)                                        \
+  if (NULL_DETECTION_ENABLED) {                                                 \
+    DEBUG((DEBUG_INFO, "%a(): disable NULL detection\r\n",  __func__));         \
+    (Instance)->Cpu->SetMemoryAttributes((Instance)->Cpu, 0, EFI_PAGE_SIZE, 0); \
+  }
+  
+#define ENABLE_NULL_DETECTION(Instance)                                                     \
+  if (NULL_DETECTION_ENABLED) {                                                             \
+    (Instance)->Cpu->SetMemoryAttributes((Instance)->Cpu, 0, EFI_PAGE_SIZE, EFI_MEMORY_RP); \
+    DEBUG((DEBUG_INFO, "%a(): enable NULL detection\r\n",  __func__));                      \
+  }
+
 //
 // Trace defines
 //
@@ -509,6 +530,8 @@ extern BBS_TABLE           *mBbsTable;
 
 extern EFI_GENERIC_MEMORY_TEST_PROTOCOL *gGenMemoryTest;
 
+extern BOOLEAN mEndOfDxe;
+
 #define PORT_70 0x70
 #define PORT_71 0x71
 
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c
index 1e098b3726..d381c2f735 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;
-  BdaPtr    = (UINT32 *) (UINTN)0x46C;
-  *BdaPtr   = LocalTime;
+  DISABLE_NULL_DETECTION(Private);
+    BdaPtr    = (UINT32 *) (UINTN)0x46C;
+    *BdaPtr   = LocalTime;
+  ENABLE_NULL_DETECTION(Private);
 
   //
   // 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.
     //
     //
+    DISABLE_NULL_DETECTION(Private);
     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);
       }
     }
+    ENABLE_NULL_DETECTION(Private);
 
     ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
     Regs.X.AX = Legacy16Boot;
@@ -1340,10 +1344,12 @@ GenericLegacyBoot (
       0
       );
 
+    DISABLE_NULL_DETECTION(Private);
     BaseVectorMaster = (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE_VECTOR_MASTER);
     for (Index = 0; Index < 8; Index++) {
       BaseVectorMaster[Index] = Private->ThunkSavedInt[Index];
     }
+    ENABLE_NULL_DETECTION(Private);
   }
   Private->LegacyBootEntered = TRUE;
   if ((mBootMode == BOOT_LEGACY_OS) || (mBootMode == BOOT_UNCONVENTIONAL_DEVICE)) {
@@ -1731,9 +1737,11 @@ LegacyBiosBuildE820 (
   //
   // First entry is 0 to (640k - EBDA)
   //
-  E820Table[0].BaseAddr  = 0;
-  E820Table[0].Length    = (UINT64) ((*(UINT16 *) (UINTN)0x40E) << 4);
-  E820Table[0].Type      = EfiAcpiAddressRangeMemory;
+  DISABLE_NULL_DETECTION(Private);
+    E820Table[0].BaseAddr  = 0;
+    E820Table[0].Length    = (UINT64) ((*(UINT16 *) (UINTN)0x40E) << 4);
+    E820Table[0].Type      = EfiAcpiAddressRangeMemory;
+  ENABLE_NULL_DETECTION(Private);
 
   //
   // Second entry is (640k - EBDA) to 640k
@@ -1967,6 +1975,8 @@ LegacyBiosCompleteBdaBeforeBoot (
   UINT16                      MachineConfig;
   DEVICE_PRODUCER_DATA_HEADER *SioPtr;
 
+  DISABLE_NULL_DETECTION(Private);
+
   Bda           = (BDA_STRUC *) ((UINTN) 0x400);
   MachineConfig = 0;
 
@@ -2025,6 +2035,8 @@ LegacyBiosCompleteBdaBeforeBoot (
   MachineConfig       = (UINT16) (MachineConfig + 0x00 + 0x02 + (SioPtr->MousePresent * 0x04));
   Bda->MachineConfig  = MachineConfig;
 
+  ENABLE_NULL_DETECTION(Private);
+
   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);
+
+  DISABLE_NULL_DETECTION(Private);
+
+  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);
+
+  ENABLE_NULL_DETECTION(Private);
+
   //
   // 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)
   //
+  DISABLE_NULL_DETECTION(Private);
   Bda = (UINT8)(*((UINT8 *)((UINTN)0x410)) | BIT3);
+  ENABLE_NULL_DETECTION(Private);
 
   //
   // Force display enabled
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c
index 8ffdf0c1ff..2ca5dddf00 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
   //
+  DISABLE_NULL_DETECTION(Private);
+
   LocalDiskStart = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);
   if ((Private->Disk4075 + 0x80) < LocalDiskStart) {
     //
@@ -2426,6 +2430,9 @@ LegacyBiosInstallRom (
     //
     VideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));
   }
+
+  ENABLE_NULL_DETECTION(Private);
+
   //
   // 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.
   //
+  DISABLE_NULL_DETECTION(Private);
   LocalTime = (LocalTime * 182) / 10;
   BdaPtr    = (UINT32 *) ((UINTN) 0x46C);
   *BdaPtr   = LocalTime;
+  ENABLE_NULL_DETECTION(Private);
   
   //
   // 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))) {
+    DISABLE_NULL_DETECTION(Private);
+    OldVideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));
+    ENABLE_NULL_DETECTION(Private);
+
+    if (VideoMode != OldVideoMode) {
       //
       // The active video mode is changed, restore it to original mode.
       //
@@ -2604,7 +2617,9 @@ LegacyBiosInstallRom (
     }
   }
 
+  DISABLE_NULL_DETECTION(Private);
   LocalDiskEnd = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);
+  ENABLE_NULL_DETECTION(Private);
   
   //
   // 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..50f6247a99 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;
+  DISABLE_NULL_DETECTION(Private);
+    Segment               = (UINT16)(((UINT32 *)0)[BiosInt] >> 16);
+    Offset                = (UINT16)((UINT32 *)0)[BiosInt];
+  ENABLE_NULL_DETECTION(Private);
   
   return InternalLegacyBiosFarCall (
            This,
-           (UINT16) ((VectorBase)[BiosInt] >> 16),
-           (UINT16) (VectorBase)[BiosInt],
+           Segment,
+           Offset,
            Regs,
            &Regs->X.Flags,
            sizeof (Regs->X.Flags)
@@ -288,16 +295,22 @@ InternalLegacyBiosFarCall (
   // EBDA base address, if the current EBDA base address is smaller, it indicates
   // PcdEbdaReservedMemorySize should be adjusted to larger for more OPROMs.
   //
-  DEBUG_CODE (
-    {
-      UINTN                 EbdaBaseAddress;
-      UINTN                 ReservedEbdaBaseAddress;
-
-      EbdaBaseAddress = (*(UINT16 *) (UINTN) 0x40E) << 4;
-      ReservedEbdaBaseAddress = CONVENTIONAL_MEMORY_TOP - PcdGet32 (PcdEbdaReservedMemorySize);
-      ASSERT (ReservedEbdaBaseAddress <= EbdaBaseAddress);
-    }
-  );
+  if (!NULL_DETECTION_ENABLED) {
+    // 
+    // Only do following if NULL pointer detection is not enabled, because it cannot 
+    // be disabled at this time due to current TPL(=TPL_HIGH_LEVEL).
+    //
+    DEBUG_CODE (
+      {
+        UINTN                 EbdaBaseAddress;
+        UINTN                 ReservedEbdaBaseAddress;
+
+        EbdaBaseAddress = (*(UINT16 *) (UINTN) 0x40E) << 4;
+        ReservedEbdaBaseAddress = CONVENTIONAL_MEMORY_TOP - PcdGet32 (PcdEbdaReservedMemorySize);
+        ASSERT (ReservedEbdaBaseAddress <= EbdaBaseAddress);
+      }
+    );
+  }
 
   if (Stack != NULL && StackSize != 0) {
     //
-- 
2.14.1.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-13  9:25   ` [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to " Wang, Jian J
@ 2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
  2017-09-13 23:34     ` Laszlo Ersek
  1 sibling, 0 replies; 37+ messages in thread
From: Johnson, Brian (EXL - Eagan) @ 2017-09-13 16:33 UTC (permalink / raw)
  To: Wang, Jian J, edk2-devel@lists.01.org
  Cc: Justen@ml01.01.org, Eric Dong, Kinney@ml01.01.org, Jordan L,
	Wolman@ml01.01.org, Jiewen Yao, Ayellet, Michael D, Laszlo Ersek,
	Star Zeng

Acked-by: Brian J. Johnson <brian.johnson@hpe.com>

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
Sent: Wednesday, September 13, 2017 4:25 AM
To: edk2-devel@lists.01.org
Cc: Justen@ml01.01.org; Eric Dong <eric.dong@intel.com>; Kinney@ml01.01.org; Jordan L <jordan.l.justen@intel.com>; Wolman@ml01.01.org; Jiewen Yao <jiewen.yao@intel.com>; Ayellet <ayellet.wolman@intel.com>; Michael D <michael.d.kinney@intel.com>; Laszlo Ersek <lersek@redhat.com>; Star Zeng <star.zeng@intel.com>
Subject: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer detection is enabled, page 0 must be enabled temporarily before installing and disabled again afterwards. For Windows 7 boot, BIT7 of PcdNullPointerDetectionPropertyMask must still be set to avoid hang.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Justen, Jordan L <jordan.l.justen@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
---
 OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
 OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
 OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
index 0dce80e59b..ee0eed7214 100644
--- a/OvmfPkg/QemuVideoDxe/Driver.c
+++ b/OvmfPkg/QemuVideoDxe/Driver.c
@@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
   PCI_TYPE00                        Pci;
   QEMU_VIDEO_CARD                   *Card;
   EFI_PCI_IO_PROTOCOL               *ChildPciIo;
+  EFI_CPU_ARCH_PROTOCOL             *Cpu;
 
   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 
@@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
 #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
   if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
       Private->Variant == QEMU_VIDEO_BOCHS) {
-    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
+    //
+    // Prepare CPU arch protocol for NULL pointer detection
+    //
+    Status = gBS->LocateProtocol (
+                    &gEfiCpuArchProtocolGuid,
+                    NULL, 
+                    (VOID **) &Cpu
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    DISABLE_NULL_DETECTION(Cpu);
+      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
+    ENABLE_NULL_DETECTION(Cpu);
   }
 #endif
 
diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
index 7fbb25b3ef..bb3bc6eb0f 100644
--- a/OvmfPkg/QemuVideoDxe/Qemu.h
+++ b/OvmfPkg/QemuVideoDxe/Qemu.h
@@ -25,6 +25,7 @@
 #include <Protocol/PciIo.h>
 #include <Protocol/DriverSupportedEfiVersion.h>
 #include <Protocol/DevicePath.h>
+#include <Protocol/Cpu.h>
 
 #include <Library/DebugLib.h>
 #include <Library/UefiDriverEntryPoint.h>
@@ -82,6 +83,21 @@ typedef struct {
 
 #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
 
+//
+// VBE code will access memory between 0-4095 which will cause page fault exception 
+// if NULL pointer detection mechanism is enabled. Following macros can be used to 
+// disable/enable NULL pointer detection before/after accessing those memory.
+//
+#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
+#define DISABLE_NULL_DETECTION(Cpu)                                             \
+  if (NULL_DETECTION_ENABLED) {                                                 \
+    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
+  }
+#define ENABLE_NULL_DETECTION(Cpu)                                              \
+  if (NULL_DETECTION_ENABLED) {                                                 \
+    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
+  }
+
 //
 // QEMU Video Private Data Structure
 //
diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
index 7c7d429bca..5d166eb99c 100644
--- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
@@ -72,7 +72,9 @@
   gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
   gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
   gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
+  gEfiCpuArchProtocolGuid
 
 [Pcd]
   gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
+  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
 
-- 
2.14.1.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.
  2017-09-13  9:25   ` [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core Wang, Jian J
  2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
@ 2017-09-13 17:28     ` Jordan Justen
  2017-09-14  1:25       ` Wang, Jian J
  1 sibling, 1 reply; 37+ messages in thread
From: Jordan Justen @ 2017-09-13 17:28 UTC (permalink / raw)
  To: Wang, Jian J, edk2-devel
  Cc: Jiewen Yao, Eric Dong, Star Zeng, Laszlo Ersek, Kinney, Michael D,
	Wolman, Ayellet

On 2017-09-13 02:25:04, Wang, Jian J wrote:
> The mechanism behind is to trigger a page fault exception at address 0. This can be made by disabling page 0 (0-4095) during page table setup. So this feature can only be available on platform with paging enabled. Once this feature is enabled, any code, like CSM, which has to access memory in page 0 needs to enable this page temporarily in advance and disable it afterwards. PcdNullPointerDetectionPropertyMask is used to control and elaborate the use cases.
>

Your commit message line is > 450 columns.

https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format

I think BaseTools/Scripts/PatchCheck.py can help detect this issue.

(more below...)

> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Justen, Jordan L <jordan.l.justen@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
> ---
>  MdeModulePkg/Core/Dxe/DxeMain.inf                |  3 +-
>  MdeModulePkg/Core/Dxe/Mem/Page.c                 | 21 ++++++----
>  MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c    | 47 +++++++++++++++++++++
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.h            | 15 +++++++
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf          |  3 +-
>  MdeModulePkg/Core/DxeIplPeim/DxeLoad.c           | 53 ++++++++++++++++++++++++
>  MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c  |  8 +++-
>  MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c   |  2 +
>  MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 23 ++++++----
>  MdeModulePkg/MdeModulePkg.dec                    | 12 ++++++
>  10 files changed, 167 insertions(+), 20 deletions(-)
> 
> diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
> index 30d5984f7c..273b8b7c0e 100644
> --- a/MdeModulePkg/Core/Dxe/DxeMain.inf
> +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
> @@ -179,7 +179,7 @@
>    gEfiWatchdogTimerArchProtocolGuid             ## CONSUMES
>  
>  [FeaturePcd]
> -  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport         ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport          ## CONSUMES

Why is this line changed?

>  
>  [Pcd]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber    ## SOMETIMES_CONSUMES
> @@ -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..2e0b72f864 100644
> --- a/MdeModulePkg/Core/Dxe/Mem/Page.c
> +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c
> @@ -170,6 +170,7 @@ CoreAddRange (
>  {
>    LIST_ENTRY        *Link;
>    MEMORY_MAP        *Entry;
> +  EFI_STATUS        Status;
>  
>    ASSERT ((Start & EFI_PAGE_MASK) == 0);
>    ASSERT (End > Start) ;
> @@ -188,7 +189,17 @@ 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);
> +    } else if (gCpu != NULL) {
> +      Status = gCpu->SetMemoryAttributes(gCpu, 0, EFI_PAGE_SIZE, 0);
> +      ASSERT_EFI_ERROR(Status);
> +
> +      SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);
> +
> +      Status = gCpu->SetMemoryAttributes(gCpu, 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);
> +      ASSERT_EFI_ERROR(Status);
> +    }
>    }
>    
>    //
> @@ -1972,11 +1983,3 @@ Done:
>    return Status;
>  }
>  
> -
> -
> -
> -
> -
> -
> -
> -
> diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
> index a73c4ccd64..2367d674e1 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,22 @@ 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 ;
>  }
>  
> diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> index 72d2532f50..104599156c 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> @@ -52,6 +52,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>  #define STACK_SIZE      0x20000
>  #define BSP_STORE_SIZE  0x4000
>  
> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT0) != 0)

I think maybe the code style would look better if you defined a
function for this rather than using a macro. What do you think?

>  
>  //
>  // This PPI is installed to indicate the end of the PEI usage of memory
> @@ -240,4 +241,18 @@ 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
> +  );
> +
>  #endif
> diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> index c54afe4aa6..fde70f94bb 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> @@ -110,11 +110,12 @@
>    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables       ## CONSUMES
>  
>  [FeaturePcd]
> -  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress         ## CONSUMES
>  
>  [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..b5f9d92f5b 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> @@ -825,3 +825,56 @@ 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          RscDescHob;
> +  EFI_PEI_HOB_POINTERS          MemAllocHob;
> +  BOOLEAN                       DoClear;
> +
> +  RscDescHob.Raw = HobStart;
> +  MemAllocHob.Raw = HobStart;
> +  DoClear = FALSE;
> +
> +  //
> +  // Check if page 0 exists and free
> +  //
> +  while ((RscDescHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, RscDescHob.Raw)) != NULL) {

This code line is longer than 80 columns. There are more cases of this
in your patchset.

-Jordan

> +    if (RscDescHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && 
> +        RscDescHob.ResourceDescriptor->PhysicalStart == 0) {
> +      DoClear = TRUE;
> +      // 
> +      // Make sure memory at 0-4095 has not been allocated.
> +      //
> +      while ((MemAllocHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, MemAllocHob.Raw)) != NULL) {
> +        if (MemAllocHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress < EFI_PAGE_SIZE) {
> +          DoClear = FALSE;
> +          break;
> +        }
> +        MemAllocHob.Raw = GET_NEXT_HOB (MemAllocHob);
> +      }
> +      break;
> +    }
> +    RscDescHob.Raw = GET_NEXT_HOB (RscDescHob);
> +  }
> +
> +  if (DoClear) {
> +    DEBUG((DEBUG_INFO, "Clearing first 4K-page!\r\n"));
> +    SetMem(NULL, EFI_PAGE_SIZE, 0);
> +  }
> +
> +  return;
> +}
> +
> diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> index 1957326caf..a8aa0d5d1b 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> @@ -123,7 +123,8 @@ Create4GPageTablesIa32Pae (
>      PageDirectoryPointerEntry->Bits.Present = 1;
>  
>      for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {
> -      if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase)) {
> +      if ((NULL_DETECTION_ENABLED && PhysicalAddress == 0)
> +          || ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase))) {
>          //
>          // Need to split this 2M page that covers stack range.
>          //
> @@ -240,6 +241,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 +382,8 @@ 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) || NULL_DETECTION_ENABLED));
>      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..50a8d77a5b 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..ccd6e10cb2 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> @@ -90,8 +90,14 @@ Split2MPageTo4K (
>      //
>      PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;
>      PageTableEntry->Bits.ReadWrite = 1;
> -    PageTableEntry->Bits.Present = 1;
> -    if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + StackSize)) {
> +
> +    if (NULL_DETECTION_ENABLED && 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 +143,10 @@ Split1GPageTo2M (
>  
>    PhysicalAddress2M = PhysicalAddress;
>    for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {
> -    if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + SIZE_2MB) > StackBase)) {
> +    if ((NULL_DETECTION_ENABLED && 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 +286,8 @@ 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 ((NULL_DETECTION_ENABLED && PageAddress == 0)
> +            || (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_1GB) > StackBase))) {
>            Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize);
>          } else {
>            //
> @@ -308,9 +316,10 @@ 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 ((NULL_DETECTION_ENABLED && 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 {
> diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
> index 593bff357a..1cc84894af 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -860,6 +860,18 @@
>    # @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] 37+ messages in thread

* Re: [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code.
  2017-09-13  9:25   ` [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code Wang, Jian J
  2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
@ 2017-09-13 17:31     ` Jordan Justen
  2017-09-14  1:20       ` Wang, Jian J
  1 sibling, 1 reply; 37+ messages in thread
From: Jordan Justen @ 2017-09-13 17:31 UTC (permalink / raw)
  To: Wang, Jian J, edk2-devel
  Cc: Jiewen Yao, Eric Dong, Star Zeng, Laszlo Ersek, Justen, Kinney,
	Michael D, Wolman, Ayellet

On 2017-09-13 02:25:05, Wang, Jian J wrote:
> 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: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Justen, Jordan L <jordan.l.justen@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
> ---
>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c     | 11 +++++++++++
>  UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c        | 25 ++++++++++++++++++++++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h   |  2 ++
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf | 17 +++++++++--------
>  UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c      | 11 +++++++++++
>  5 files changed, 57 insertions(+), 9 deletions(-)
> 
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
> index f295c2ebf2..d423958783 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
> @@ -155,6 +155,17 @@ SmiPFHandler (
>      }
>    }
>  
> +  //
> +  // If NULL pointer was just accessed
> +  //
> +  if (NULL_DETECTION_ENABLED && (PFAddress >= 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..81c5ac9d11 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 (NULL_DETECTION_ENABLED) {
> +    Pte = (UINT64*)(UINT64)(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*)(UINT64)(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.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> index 1cf85c1481..bcb3032db8 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> @@ -153,6 +153,8 @@ typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;
>  #define ARRIVAL_EXCEPTION_DELAYED           0x2
>  #define ARRIVAL_EXCEPTION_SMI_DISABLED      0x4
>  
> +#define NULL_DETECTION_ENABLED    ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT1) != 0)
> +

Again, I think the NULL_DETECTION_ENABLED macro code style looks odd.
Maybe it is just better to include the duplicated code directly in the
3 places?

The commit message for this patch has a long line length.

-Jordan

>  //
>  // Private structure for the SMM CPU module that is stored in DXE Runtime memory
>  // Contains the SMM Configuration Protocols that is produced.
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
> index 099792e6ce..57a14d9f24 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
> @@ -138,14 +138,14 @@
>    gEdkiiPiSmmMemoryAttributesTableGuid     ## CONSUMES ## SystemTable
>  
>  [FeaturePcd]
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                         ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp            ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection             ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport                   ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                    ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable                 ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer             ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock         ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                           ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp              ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection               ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport                     ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                      ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable                   ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer               ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock           ## CONSUMES
>  
>  [Pcd]
>    gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber        ## SOMETIMES_CONSUMES
> @@ -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..e67bcfe0f6 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
> @@ -872,6 +872,17 @@ SmiPFHandler (
>      }
>    }
>  
> +  //
> +  // If NULL pointer was just accessed
> +  //
> +  if (NULL_DETECTION_ENABLED && (PFAddress >= 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	[flat|nested] 37+ messages in thread

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-13  9:25   ` [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to " Wang, Jian J
  2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
@ 2017-09-13 23:34     ` Laszlo Ersek
  2017-09-14  1:17       ` Wang, Jian J
  1 sibling, 1 reply; 37+ messages in thread
From: Laszlo Ersek @ 2017-09-13 23:34 UTC (permalink / raw)
  To: Jian J Wang
  Cc: edk2-devel, Jordan Justen (Intel address), Eric Dong,
	Michael Kinney, Ayellet Wolman, Jiewen Yao, Star Zeng

Hi,

some of the points I'm going to make have already been pointed out by
Jordan:

(1) When posting a patch series, please collect the Cc: tags from all of
the patches, and add them *all* to the cover letter. This way everyone
will get a personal copy of the general description.


(2) The subject line is too long. One possible simplification:

OvmfPkg/QemuVideoDxe: bypass NULL pointer detection


On 09/13/17 11:25, Wang, Jian J wrote:
> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
> detection is enabled, page 0 must be enabled temporarily before
> installing and disabled again afterwards. For Windows 7 boot, BIT7 of
> PcdNullPointerDetectionPropertyMask must still be set to avoid hang.

(3) Subject line and commit message both should not exceed 74 characters
line length. (Not sure how many chars PatchCheck.py actually enforces, I
always stick with 74, following the Linux kernel tradition.)

I rewrapped the commit message here for readability.


>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Justen, Jordan L <jordan.l.justen@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>

(4) I think this is also something that Jordan had pointed out a long
time ago (apologies if I mis-remember):

The strings after the tags should form correct email addresses, and if
there are various email meta-characters in them, like "." (dot) and ","
(comma), then they should be quoted, like this:

Cc: "Justen, Jordan L" <jordan.l.justen@intel.com>
Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>
Cc: "Wolman, Ayellet" <ayellet.wolman@intel.com>
Suggested-by: "Wolman, Ayellet" <ayellet.wolman@intel.com>
Signed-off-by: "Wang, Jian J" <jian.j.wang@intel.com>

If you look at the actual addresses on the emails that have been sent
out, you can see they are all malformed. For example, I have:

"Jordan L <jordan.l.justen@intel.com>" for Jordan -- the part before the
comma was taken to be a separate email address (a malformed one).

At least for my reply, I have fixed up the email addresses.


(5) The commit message mentions BIT7 of the new PCD.

First, thanks for checking Windows 7 boot (and I'm happy that I got
suspicious of the feature with regard to Windows 7). I think BIT7 is a
good feature.

However, please include the short description of that feature in the
commit message -- it is one sentence; "Disable NULL pointer detection
just after EndOfDxe."

(I think BIT7 is a really smart feature, and I like *how* it is used in
"NULL_DETECTION_ENABLED" below. The check means, "if the protection is
enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".

This doesn't mean that I like the NULL_DETECTION_ENABLED macro itself;
more on that below.)


> ---
>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>  3 files changed, 32 insertions(+), 1 deletion(-)
>
> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
> index 0dce80e59b..ee0eed7214 100644
> --- a/OvmfPkg/QemuVideoDxe/Driver.c
> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>    PCI_TYPE00                        Pci;
>    QEMU_VIDEO_CARD                   *Card;
>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;

(6) I believe I mentioned this in the earlier discussion, in some form,
but now I'll say it again:

A UEFI driver has no business poking at the CPU Arch protocol. The PI
spec (1.6) states,

  12.3 CPU Architectural Protocol
  EFI_CPU_ARCH_PROTOCOL

  Summary

  Abstracts the processor services that are required to implement some
  of the DXE services. This protocol must be produced by a boot service
  or runtime DXE driver and may only be consumed by the DXE Foundation
  and DXE drivers that produce architectural protocols.

The DXE core is obviously free to use the CPU Arch protocol, but a UEFI
driver is forbidden from it, *even if* we say that, in this UEFI driver,
we are going to use DXE services. (Which come from the PI spec, and not
the UEFI spec.)

Therefore, here we have to use gDS->SetMemorySpaceAttributes().

The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch
protocol, by the PI spec. It is not easy to see, because the PI spec has
a formatting error in this area. If you look under
GetMemorySpaceDescriptor(), there is an error code

  EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
                         architectural protocol is not available yet.

Obviously this error code belongs to SetMemorySpaceAttributes(), not
GetMemorySpaceDescriptor().

Anyway, gDS should be used, architectural protocols shouldn't be.


>
>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>
> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
>  #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>        Private->Variant == QEMU_VIDEO_BOCHS) {
> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
> +    //
> +    // Prepare CPU arch protocol for NULL pointer detection
> +    //
> +    Status = gBS->LocateProtocol (
> +                    &gEfiCpuArchProtocolGuid,
> +                    NULL,
> +                    (VOID **) &Cpu
> +                    );
> +    ASSERT_EFI_ERROR (Status);
> +
> +    DISABLE_NULL_DETECTION(Cpu);
> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
> +    ENABLE_NULL_DETECTION(Cpu);

(7) The NULL detection disabling and enabling should bracket the
affected code as tightly as possible.

So please move this into InstallVbeShim() accordingly.


>    }
>  #endif
>
> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
> index 7fbb25b3ef..bb3bc6eb0f 100644
> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
> @@ -25,6 +25,7 @@
>  #include <Protocol/PciIo.h>
>  #include <Protocol/DriverSupportedEfiVersion.h>
>  #include <Protocol/DevicePath.h>
> +#include <Protocol/Cpu.h>
>
>  #include <Library/DebugLib.h>
>  #include <Library/UefiDriverEntryPoint.h>
> @@ -82,6 +83,21 @@ typedef struct {
>
>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>
> +//
> +// VBE code will access memory between 0-4095 which will cause page fault exception
> +// if NULL pointer detection mechanism is enabled. Following macros can be used to
> +// disable/enable NULL pointer detection before/after accessing those memory.
> +//
> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
> +  if (NULL_DETECTION_ENABLED) {                                                 \
> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
> +  }
> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
> +  if (NULL_DETECTION_ENABLED) {                                                 \
> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
> +  }
> +

(8) I believe Jordan too commented on these macros elsewhere (under
patch 1/4).

In my opinion, this functionality should be extracted into a library
class, with a library instance that is suitable for at least UEFI_DRIVER
modules. (Maybe even for DXE_DRIVER modules.)

You could add a separate library instance for SMM drivers, if that were
necessary.


(9) Style comment: please put one space character between the function
designator and the opening parenthesis.


>  //
>  // QEMU Video Private Data Structure
>  //
> diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> index 7c7d429bca..5d166eb99c 100644
> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> @@ -72,7 +72,9 @@
>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
> +  gEfiCpuArchProtocolGuid
>
>  [Pcd]
>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask

(10) Instead of these, the library class that I described under (8)
should be added here.

Any further dependencies like PCDs, protocols etc should be inherited by
the driver through the library instance that the platform DSC file
resolves the library class to.

Bonus: should you realize that the feature is impossible to implement
without accessing the CPU Arch protocol directly, you could hide the
protocol GUID dependency in the library instance INF file, and I'd be
none the wiser.

... Well, I could at least pretend that. :)

Thanks,
Laszlo


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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-13 23:34     ` Laszlo Ersek
@ 2017-09-14  1:17       ` Wang, Jian J
  2017-09-14  3:17         ` Wang, Jian J
                           ` (2 more replies)
  0 siblings, 3 replies; 37+ messages in thread
From: Wang, Jian J @ 2017-09-14  1:17 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: edk2-devel@lists.01.org, Justen, Jordan L, Dong, Eric,
	Kinney, Michael D, Wolman, Ayellet, Yao, Jiewen, Zeng, Star

Thanks for the comments and good advices. Sorry the format issues.
This is my first patch for this project. Too many details for me to get 
familiar with. 

(1) Sure.
(2) I'll change that.
(3) I'll use the tool to ensure the patch format.
(4) I'll remove the ',' in name
(5) I'll add more description about it.
(6) You're right. I should use SetMemorySpaceAttributes() of DXE service
     instead. The only reason I didn't do it is that I found 
      GetMemorySpaceDescriptor() doesn't return the same information
     which SetMemorySpaceAttributes() just changed. So I feel using CPU
    arch protocol is a bit safer. Anyway, I'll change it.
(7) I did put those macros in the install function before. To reduce the
     number of changed files, I made current changes. You're right it's
     not worthy.
(8) Using macro can help the readability, which is more important to me.
    I know function can do the same. But it looks a bit heavy in this situation.
    I have to admit replacing  the macros with a library is a very good idea,  
    which brings the same readability. I didn't think of that before. Although 
    Library is still a little bit heavy to me but it's in a different way, I think it 
    worth a trying.
(9) Putting a space before open parenthesis is forced style? If so, I'll add it.
(10) You're right. Using library can reduce the disturbs to affected drivers
       by this feature to the minimum.

-----Original Message-----
From: Laszlo Ersek [mailto:lersek@redhat.com] 
Sent: Thursday, September 14, 2017 7:35 AM
To: Wang, Jian J <jian.j.wang@intel.com>
Cc: edk2-devel@lists.01.org; Justen, Jordan L <jordan.l.justen@intel.com>; Dong, Eric <eric.dong@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

Hi,

some of the points I'm going to make have already been pointed out by
Jordan:

(1) When posting a patch series, please collect the Cc: tags from all of
the patches, and add them *all* to the cover letter. This way everyone
will get a personal copy of the general description.


(2) The subject line is too long. One possible simplification:

OvmfPkg/QemuVideoDxe: bypass NULL pointer detection


On 09/13/17 11:25, Wang, Jian J wrote:
> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
> detection is enabled, page 0 must be enabled temporarily before
> installing and disabled again afterwards. For Windows 7 boot, BIT7 of
> PcdNullPointerDetectionPropertyMask must still be set to avoid hang.

(3) Subject line and commit message both should not exceed 74 characters
line length. (Not sure how many chars PatchCheck.py actually enforces, I
always stick with 74, following the Linux kernel tradition.)

I rewrapped the commit message here for readability.


>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Justen, Jordan L <jordan.l.justen@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>

(4) I think this is also something that Jordan had pointed out a long
time ago (apologies if I mis-remember):

The strings after the tags should form correct email addresses, and if
there are various email meta-characters in them, like "." (dot) and ","
(comma), then they should be quoted, like this:

Cc: "Justen, Jordan L" <jordan.l.justen@intel.com>
Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>
Cc: "Wolman, Ayellet" <ayellet.wolman@intel.com>
Suggested-by: "Wolman, Ayellet" <ayellet.wolman@intel.com>
Signed-off-by: "Wang, Jian J" <jian.j.wang@intel.com>

If you look at the actual addresses on the emails that have been sent
out, you can see they are all malformed. For example, I have:

"Jordan L <jordan.l.justen@intel.com>" for Jordan -- the part before the
comma was taken to be a separate email address (a malformed one).

At least for my reply, I have fixed up the email addresses.


(5) The commit message mentions BIT7 of the new PCD.

First, thanks for checking Windows 7 boot (and I'm happy that I got
suspicious of the feature with regard to Windows 7). I think BIT7 is a
good feature.

However, please include the short description of that feature in the
commit message -- it is one sentence; "Disable NULL pointer detection
just after EndOfDxe."

(I think BIT7 is a really smart feature, and I like *how* it is used in
"NULL_DETECTION_ENABLED" below. The check means, "if the protection is
enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".

This doesn't mean that I like the NULL_DETECTION_ENABLED macro itself;
more on that below.)


> ---
>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>  3 files changed, 32 insertions(+), 1 deletion(-)
>
> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
> index 0dce80e59b..ee0eed7214 100644
> --- a/OvmfPkg/QemuVideoDxe/Driver.c
> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>    PCI_TYPE00                        Pci;
>    QEMU_VIDEO_CARD                   *Card;
>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;

(6) I believe I mentioned this in the earlier discussion, in some form,
but now I'll say it again:

A UEFI driver has no business poking at the CPU Arch protocol. The PI
spec (1.6) states,

  12.3 CPU Architectural Protocol
  EFI_CPU_ARCH_PROTOCOL

  Summary

  Abstracts the processor services that are required to implement some
  of the DXE services. This protocol must be produced by a boot service
  or runtime DXE driver and may only be consumed by the DXE Foundation
  and DXE drivers that produce architectural protocols.

The DXE core is obviously free to use the CPU Arch protocol, but a UEFI
driver is forbidden from it, *even if* we say that, in this UEFI driver,
we are going to use DXE services. (Which come from the PI spec, and not
the UEFI spec.)

Therefore, here we have to use gDS->SetMemorySpaceAttributes().

The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch
protocol, by the PI spec. It is not easy to see, because the PI spec has
a formatting error in this area. If you look under
GetMemorySpaceDescriptor(), there is an error code

  EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
                         architectural protocol is not available yet.

Obviously this error code belongs to SetMemorySpaceAttributes(), not
GetMemorySpaceDescriptor().

Anyway, gDS should be used, architectural protocols shouldn't be.


>
>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>
> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
>  #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>        Private->Variant == QEMU_VIDEO_BOCHS) {
> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
> +    //
> +    // Prepare CPU arch protocol for NULL pointer detection
> +    //
> +    Status = gBS->LocateProtocol (
> +                    &gEfiCpuArchProtocolGuid,
> +                    NULL,
> +                    (VOID **) &Cpu
> +                    );
> +    ASSERT_EFI_ERROR (Status);
> +
> +    DISABLE_NULL_DETECTION(Cpu);
> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
> +    ENABLE_NULL_DETECTION(Cpu);

(7) The NULL detection disabling and enabling should bracket the
affected code as tightly as possible.

So please move this into InstallVbeShim() accordingly.


>    }
>  #endif
>
> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
> index 7fbb25b3ef..bb3bc6eb0f 100644
> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
> @@ -25,6 +25,7 @@
>  #include <Protocol/PciIo.h>
>  #include <Protocol/DriverSupportedEfiVersion.h>
>  #include <Protocol/DevicePath.h>
> +#include <Protocol/Cpu.h>
>
>  #include <Library/DebugLib.h>
>  #include <Library/UefiDriverEntryPoint.h>
> @@ -82,6 +83,21 @@ typedef struct {
>
>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>
> +//
> +// VBE code will access memory between 0-4095 which will cause page fault exception
> +// if NULL pointer detection mechanism is enabled. Following macros can be used to
> +// disable/enable NULL pointer detection before/after accessing those memory.
> +//
> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
> +  if (NULL_DETECTION_ENABLED) {                                                 \
> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
> +  }
> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
> +  if (NULL_DETECTION_ENABLED) {                                                 \
> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
> +  }
> +

(8) I believe Jordan too commented on these macros elsewhere (under
patch 1/4).

In my opinion, this functionality should be extracted into a library
class, with a library instance that is suitable for at least UEFI_DRIVER
modules. (Maybe even for DXE_DRIVER modules.)

You could add a separate library instance for SMM drivers, if that were
necessary.


(9) Style comment: please put one space character between the function
designator and the opening parenthesis.


>  //
>  // QEMU Video Private Data Structure
>  //
> diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> index 7c7d429bca..5d166eb99c 100644
> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> @@ -72,7 +72,9 @@
>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
> +  gEfiCpuArchProtocolGuid
>
>  [Pcd]
>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask

(10) Instead of these, the library class that I described under (8)
should be added here.

Any further dependencies like PCDs, protocols etc should be inherited by
the driver through the library instance that the platform DSC file
resolves the library class to.

Bonus: should you realize that the feature is impossible to implement
without accessing the CPU Arch protocol directly, you could hide the
protocol GUID dependency in the library instance INF file, and I'd be
none the wiser.

... Well, I could at least pretend that. :)

Thanks,
Laszlo

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

* Re: [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code.
  2017-09-13 17:31     ` Jordan Justen
@ 2017-09-14  1:20       ` Wang, Jian J
  0 siblings, 0 replies; 37+ messages in thread
From: Wang, Jian J @ 2017-09-14  1:20 UTC (permalink / raw)
  To: Justen, Jordan L, edk2-devel@lists.01.org
  Cc: Yao, Jiewen, Dong, Eric, Zeng, Star, Laszlo Ersek,
	Kinney, Michael D, Wolman, Ayellet, Wolman, Ayellet

I'll use the tool to check the format. For the macro, it's for readability purpose. How's the library replacement suggestion from Laszlo? 

-----Original Message-----
From: Justen, Jordan L 
Sent: Thursday, September 14, 2017 1:32 AM
To: Wang, Jian J <jian.j.wang@intel.com>; edk2-devel@lists.01.org
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Dong, Eric <eric.dong@intel.com>; Zeng, Star <star.zeng@intel.com>; Laszlo Ersek <lersek@redhat.com>; Justen; Kinney; Kinney, Michael D <michael.d.kinney@intel.com>; Wolman; Wolman, Ayellet <ayellet.wolman@intel.com>
Subject: Re: [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code.

On 2017-09-13 02:25:05, Wang, Jian J wrote:
> 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: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Justen, Jordan L <jordan.l.justen@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
> ---
>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c     | 11 +++++++++++
>  UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c        | 25 ++++++++++++++++++++++++-
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h   |  2 ++
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf | 17 +++++++++--------
>  UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c      | 11 +++++++++++
>  5 files changed, 57 insertions(+), 9 deletions(-)
> 
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
> index f295c2ebf2..d423958783 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
> @@ -155,6 +155,17 @@ SmiPFHandler (
>      }
>    }
>  
> +  //
> +  // If NULL pointer was just accessed
> +  //
> +  if (NULL_DETECTION_ENABLED && (PFAddress >= 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..81c5ac9d11 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 (NULL_DETECTION_ENABLED) {
> +    Pte = (UINT64*)(UINT64)(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*)(UINT64)(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.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> index 1cf85c1481..bcb3032db8 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> @@ -153,6 +153,8 @@ typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;
>  #define ARRIVAL_EXCEPTION_DELAYED           0x2
>  #define ARRIVAL_EXCEPTION_SMI_DISABLED      0x4
>  
> +#define NULL_DETECTION_ENABLED    ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT1) != 0)
> +

Again, I think the NULL_DETECTION_ENABLED macro code style looks odd.
Maybe it is just better to include the duplicated code directly in the
3 places?

The commit message for this patch has a long line length.

-Jordan

>  //
>  // Private structure for the SMM CPU module that is stored in DXE Runtime memory
>  // Contains the SMM Configuration Protocols that is produced.
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
> index 099792e6ce..57a14d9f24 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
> @@ -138,14 +138,14 @@
>    gEdkiiPiSmmMemoryAttributesTableGuid     ## CONSUMES ## SystemTable
>  
>  [FeaturePcd]
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                         ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp            ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection             ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport                   ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                    ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable                 ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer             ## CONSUMES
> -  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock         ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                           ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp              ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection               ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport                     ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                      ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable                   ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer               ## CONSUMES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock           ## CONSUMES
>  
>  [Pcd]
>    gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber        ## SOMETIMES_CONSUMES
> @@ -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..e67bcfe0f6 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
> @@ -872,6 +872,17 @@ SmiPFHandler (
>      }
>    }
>  
> +  //
> +  // If NULL pointer was just accessed
> +  //
> +  if (NULL_DETECTION_ENABLED && (PFAddress >= 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	[flat|nested] 37+ messages in thread

* Re: [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.
  2017-09-13 17:28     ` Jordan Justen
@ 2017-09-14  1:25       ` Wang, Jian J
  2017-09-14  6:33         ` Jordan Justen
  0 siblings, 1 reply; 37+ messages in thread
From: Wang, Jian J @ 2017-09-14  1:25 UTC (permalink / raw)
  To: Justen, Jordan L, edk2-devel@lists.01.org
  Cc: Yao, Jiewen, Dong, Eric, Zeng, Star, Laszlo Ersek,
	Kinney, Michael D, Wolman, Ayellet

See my comments start with [Jian] below.

-----Original Message-----
From: Justen, Jordan L 
Sent: Thursday, September 14, 2017 1:28 AM
To: Wang, Jian J <jian.j.wang@intel.com>; edk2-devel@lists.01.org
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Dong, Eric <eric.dong@intel.com>; Zeng, Star <star.zeng@intel.com>; Laszlo Ersek <lersek@redhat.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
Subject: Re: [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.

On 2017-09-13 02:25:04, Wang, Jian J wrote:
> The mechanism behind is to trigger a page fault exception at address 0. This can be made by disabling page 0 (0-4095) during page table setup. So this feature can only be available on platform with paging enabled. Once this feature is enabled, any code, like CSM, which has to access memory in page 0 needs to enable this page temporarily in advance and disable it afterwards. PcdNullPointerDetectionPropertyMask is used to control and elaborate the use cases.
>

Your commit message line is > 450 columns.

https://github.com/tianocore/tianocore.github.io/wiki/Commit-Message-Format

I think BaseTools/Scripts/PatchCheck.py can help detect this issue.

(more below...)

[Jian] Sure.

> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Justen, Jordan L <jordan.l.justen@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
> ---
>  MdeModulePkg/Core/Dxe/DxeMain.inf                |  3 +-
>  MdeModulePkg/Core/Dxe/Mem/Page.c                 | 21 ++++++----
>  MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c    | 47 +++++++++++++++++++++
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.h            | 15 +++++++
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf          |  3 +-
>  MdeModulePkg/Core/DxeIplPeim/DxeLoad.c           | 53 ++++++++++++++++++++++++
>  MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c  |  8 +++-
>  MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c   |  2 +
>  MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 23 ++++++----
>  MdeModulePkg/MdeModulePkg.dec                    | 12 ++++++
>  10 files changed, 167 insertions(+), 20 deletions(-)
> 
> diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
> index 30d5984f7c..273b8b7c0e 100644
> --- a/MdeModulePkg/Core/Dxe/DxeMain.inf
> +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
> @@ -179,7 +179,7 @@
>    gEfiWatchdogTimerArchProtocolGuid             ## CONSUMES
>  
>  [FeaturePcd]
> -  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport         ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport          ## CONSUMES

Why is this line changed?
[Jian] Just align the comment followed because the new one added

>  
>  [Pcd]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber    ## SOMETIMES_CONSUMES
> @@ -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..2e0b72f864 100644
> --- a/MdeModulePkg/Core/Dxe/Mem/Page.c
> +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c
> @@ -170,6 +170,7 @@ CoreAddRange (
>  {
>    LIST_ENTRY        *Link;
>    MEMORY_MAP        *Entry;
> +  EFI_STATUS        Status;
>  
>    ASSERT ((Start & EFI_PAGE_MASK) == 0);
>    ASSERT (End > Start) ;
> @@ -188,7 +189,17 @@ 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);
> +    } else if (gCpu != NULL) {
> +      Status = gCpu->SetMemoryAttributes(gCpu, 0, EFI_PAGE_SIZE, 0);
> +      ASSERT_EFI_ERROR(Status);
> +
> +      SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);
> +
> +      Status = gCpu->SetMemoryAttributes(gCpu, 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);
> +      ASSERT_EFI_ERROR(Status);
> +    }
>    }
>    
>    //
> @@ -1972,11 +1983,3 @@ Done:
>    return Status;
>  }
>  
> -
> -
> -
> -
> -
> -
> -
> -
> diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
> index a73c4ccd64..2367d674e1 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,22 @@ 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 ;
>  }
>  
> diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> index 72d2532f50..104599156c 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> @@ -52,6 +52,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
>  #define STACK_SIZE      0x20000
>  #define BSP_STORE_SIZE  0x4000
>  
> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT0) != 0)

I think maybe the code style would look better if you defined a
function for this rather than using a macro. What do you think?

[Jian] Ok. I'll add a function instead.

>  
>  //
>  // This PPI is installed to indicate the end of the PEI usage of memory
> @@ -240,4 +241,18 @@ 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
> +  );
> +
>  #endif
> diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> index c54afe4aa6..fde70f94bb 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> @@ -110,11 +110,12 @@
>    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables       ## CONSUMES
>  
>  [FeaturePcd]
> -  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress         ## CONSUMES
>  
>  [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..b5f9d92f5b 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> @@ -825,3 +825,56 @@ 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          RscDescHob;
> +  EFI_PEI_HOB_POINTERS          MemAllocHob;
> +  BOOLEAN                       DoClear;
> +
> +  RscDescHob.Raw = HobStart;
> +  MemAllocHob.Raw = HobStart;
> +  DoClear = FALSE;
> +
> +  //
> +  // Check if page 0 exists and free
> +  //
> +  while ((RscDescHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, RscDescHob.Raw)) != NULL) {

This code line is longer than 80 columns. There are more cases of this
in your patchset.

-Jordan

> +    if (RscDescHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && 
> +        RscDescHob.ResourceDescriptor->PhysicalStart == 0) {
> +      DoClear = TRUE;
> +      // 
> +      // Make sure memory at 0-4095 has not been allocated.
> +      //
> +      while ((MemAllocHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, MemAllocHob.Raw)) != NULL) {
> +        if (MemAllocHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress < EFI_PAGE_SIZE) {
> +          DoClear = FALSE;
> +          break;
> +        }
> +        MemAllocHob.Raw = GET_NEXT_HOB (MemAllocHob);
> +      }
> +      break;
> +    }
> +    RscDescHob.Raw = GET_NEXT_HOB (RscDescHob);
> +  }
> +
> +  if (DoClear) {
> +    DEBUG((DEBUG_INFO, "Clearing first 4K-page!\r\n"));
> +    SetMem(NULL, EFI_PAGE_SIZE, 0);
> +  }
> +
> +  return;
> +}
> +
> diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> index 1957326caf..a8aa0d5d1b 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
> @@ -123,7 +123,8 @@ Create4GPageTablesIa32Pae (
>      PageDirectoryPointerEntry->Bits.Present = 1;
>  
>      for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {
> -      if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase)) {
> +      if ((NULL_DETECTION_ENABLED && PhysicalAddress == 0)
> +          || ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase))) {
>          //
>          // Need to split this 2M page that covers stack range.
>          //
> @@ -240,6 +241,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 +382,8 @@ 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) || NULL_DETECTION_ENABLED));
>      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..50a8d77a5b 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..ccd6e10cb2 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> @@ -90,8 +90,14 @@ Split2MPageTo4K (
>      //
>      PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;
>      PageTableEntry->Bits.ReadWrite = 1;
> -    PageTableEntry->Bits.Present = 1;
> -    if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + StackSize)) {
> +
> +    if (NULL_DETECTION_ENABLED && 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 +143,10 @@ Split1GPageTo2M (
>  
>    PhysicalAddress2M = PhysicalAddress;
>    for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {
> -    if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + SIZE_2MB) > StackBase)) {
> +    if ((NULL_DETECTION_ENABLED && 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 +286,8 @@ 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 ((NULL_DETECTION_ENABLED && PageAddress == 0)
> +            || (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_1GB) > StackBase))) {
>            Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize);
>          } else {
>            //
> @@ -308,9 +316,10 @@ 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 ((NULL_DETECTION_ENABLED && 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 {
> diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
> index 593bff357a..1cc84894af 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -860,6 +860,18 @@
>    # @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] 37+ messages in thread

* Re: [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code.
  2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
@ 2017-09-14  1:31       ` Wang, Jian J
  0 siblings, 0 replies; 37+ messages in thread
From: Wang, Jian J @ 2017-09-14  1:31 UTC (permalink / raw)
  To: Johnson, Brian (EXL - Eagan), edk2-devel@lists.01.org
  Cc: Justen@ml01.01.org, Dong, Eric, Kinney@ml01.01.org,
	Justen, Jordan L, Wolman@ml01.01.org, Yao, Jiewen,
	Wolman, Ayellet, Kinney, Michael D, Laszlo Ersek, Zeng, Star

Thanks for the comments. See my comment start with [Jian] below.

-----Original Message-----
From: Johnson, Brian (EXL - Eagan) [mailto:brian.johnson@hpe.com] 
Sent: Thursday, September 14, 2017 12:34 AM
To: Wang, Jian J <jian.j.wang@intel.com>; edk2-devel@lists.01.org
Cc: Justen@ml01.01.org; Dong, Eric <eric.dong@intel.com>; Kinney@ml01.01.org; Justen, Jordan L <jordan.l.justen@intel.com>; Wolman@ml01.01.org; Yao, Jiewen <jiewen.yao@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Laszlo Ersek <lersek@redhat.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [edk2] [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code.

Comments below.

Brian

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
Sent: Wednesday, September 13, 2017 4:25 AM
To: edk2-devel@lists.01.org
Cc: Justen@ml01.01.org; Eric Dong <eric.dong@intel.com>; Kinney@ml01.01.org; Jordan L <jordan.l.justen@intel.com>; Wolman@ml01.01.org; Jiewen Yao <jiewen.yao@intel.com>; Ayellet <ayellet.wolman@intel.com>; Michael D <michael.d.kinney@intel.com>; Laszlo Ersek <lersek@redhat.com>; Star Zeng <star.zeng@intel.com>
Subject: [edk2] [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code.

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: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Justen, Jordan L <jordan.l.justen@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
---
 UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c     | 11 +++++++++++
 UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c        | 25 ++++++++++++++++++++++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h   |  2 ++
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf | 17 +++++++++--------
 UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c      | 11 +++++++++++
 5 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
index f295c2ebf2..d423958783 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
@@ -155,6 +155,17 @@ SmiPFHandler (
     }
   }
 
+  //
+  // If NULL pointer was just accessed
+  //
+  if (NULL_DETECTION_ENABLED && (PFAddress >= 0 && PFAddress < EFI_PAGE_SIZE)) {

[Brian] PFAddress is unsigned, so it will always be >= 0.  Some compilers complain about this....  Should probably remove that part of the test.
[Jian] You're right. The first test is not necessary.

+    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..81c5ac9d11 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 (NULL_DETECTION_ENABLED) {
+    Pte = (UINT64*)(UINT64)(Pdpte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));

[Brian] Shouldn't the inner cast be (UINTN), not (UINT64)?  That would match the PcdCpuSmmStackGuard section above.
[Jian] You're right. Inner cast should be UINTN.

+    if ((Pte[0] & IA32_PG_PS) == 0) {
+      // 4K-page entries are already mapped. Just hide the first one anyway.
+      Pte = (UINT64*)(UINT64)(Pte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));

[Brian] Same comment re. the inner cast.

+      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.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
index 1cf85c1481..bcb3032db8 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -153,6 +153,8 @@ typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;
 #define ARRIVAL_EXCEPTION_DELAYED           0x2
 #define ARRIVAL_EXCEPTION_SMI_DISABLED      0x4
 
+#define NULL_DETECTION_ENABLED    ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT1) != 0)
+
 //
 // Private structure for the SMM CPU module that is stored in DXE Runtime memory
 // Contains the SMM Configuration Protocols that is produced.
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
index 099792e6ce..57a14d9f24 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -138,14 +138,14 @@
   gEdkiiPiSmmMemoryAttributesTableGuid     ## CONSUMES ## SystemTable
 
 [FeaturePcd]
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                         ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp            ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection             ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport                   ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                    ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable                 ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer             ## CONSUMES
-  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock         ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                           ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp              ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection               ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport                     ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard                      ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable                   ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer               ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock           ## CONSUMES
 
 [Pcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber        ## SOMETIMES_CONSUMES
@@ -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..e67bcfe0f6 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
@@ -872,6 +872,17 @@ SmiPFHandler (
     }
   }
 
+  //
+  // If NULL pointer was just accessed
+  //
+  if (NULL_DETECTION_ENABLED && (PFAddress >= 0 && PFAddress < EFI_PAGE_SIZE)) {

[Brian] PFAddress is unsigned, so it will always be >= 0.  Some compilers complain about this....  Should probably remove that part of the test.

+    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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel



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

* Re: [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.
  2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
@ 2017-09-14  1:37       ` Wang, Jian J
  0 siblings, 0 replies; 37+ messages in thread
From: Wang, Jian J @ 2017-09-14  1:37 UTC (permalink / raw)
  To: Johnson, Brian (EXL - Eagan), edk2-devel@lists.01.org
  Cc: Justen@ml01.01.org, Dong, Eric, Kinney@ml01.01.org,
	Justen, Jordan L, Wolman@ml01.01.org, Yao, Jiewen,
	Wolman, Ayellet, Kinney, Michael D, Laszlo Ersek, Zeng, Star

Thanks for the comment. I think there's no problem here because I'm using two separate HOB pointers (RscDescHob and MemAllocHob) to do the traversal. One won't interfere with another. 

-----Original Message-----
From: Johnson, Brian (EXL - Eagan) [mailto:brian.johnson@hpe.com] 
Sent: Thursday, September 14, 2017 12:33 AM
To: Wang, Jian J <jian.j.wang@intel.com>; edk2-devel@lists.01.org
Cc: Justen@ml01.01.org; Dong, Eric <eric.dong@intel.com>; Kinney@ml01.01.org; Justen, Jordan L <jordan.l.justen@intel.com>; Wolman@ml01.01.org; Yao, Jiewen <jiewen.yao@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Laszlo Ersek <lersek@redhat.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [edk2] [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.

ClearLegacyMemory() assumes that the memory allocation HOB comes after the resource descriptor HOB in the HOB list.  Is that guaranteed?  I'd think that the memory allocation HOB traversal should be a separate loop, after the resource descriptor HOB traversal loop.

Other than that:
Reviewed-by: Brian J. Johnson <brian.johnson@hpe.com>

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
Sent: Wednesday, September 13, 2017 4:25 AM
To: edk2-devel@lists.01.org
Cc: Justen@ml01.01.org; Eric Dong <eric.dong@intel.com>; Kinney@ml01.01.org; Jordan L <jordan.l.justen@intel.com>; Wolman@ml01.01.org; Jiewen Yao <jiewen.yao@intel.com>; Ayellet <ayellet.wolman@intel.com>; Michael D <michael.d.kinney@intel.com>; Laszlo Ersek <lersek@redhat.com>; Star Zeng <star.zeng@intel.com>
Subject: [edk2] [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.

The mechanism behind is to trigger a page fault exception at address 0. This can be made by disabling page 0 (0-4095) during page table setup. So this feature can only be available on platform with paging enabled. Once this feature is enabled, any code, like CSM, which has to access memory in page 0 needs to enable this page temporarily in advance and disable it afterwards. PcdNullPointerDetectionPropertyMask is used to control and elaborate the use cases.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Justen, Jordan L <jordan.l.justen@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
---
 MdeModulePkg/Core/Dxe/DxeMain.inf                |  3 +-
 MdeModulePkg/Core/Dxe/Mem/Page.c                 | 21 ++++++----
 MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c    | 47 +++++++++++++++++++++
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.h            | 15 +++++++
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf          |  3 +-
 MdeModulePkg/Core/DxeIplPeim/DxeLoad.c           | 53 ++++++++++++++++++++++++
 MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c  |  8 +++-
 MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c   |  2 +
 MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 23 ++++++----
 MdeModulePkg/MdeModulePkg.dec                    | 12 ++++++
 10 files changed, 167 insertions(+), 20 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
index 30d5984f7c..273b8b7c0e 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.inf
+++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -179,7 +179,7 @@
   gEfiWatchdogTimerArchProtocolGuid             ## CONSUMES
 
 [FeaturePcd]
-  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport   ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport          ## CONSUMES
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber    ## SOMETIMES_CONSUMES
@@ -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..2e0b72f864 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Page.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Page.c
@@ -170,6 +170,7 @@ CoreAddRange (
 {
   LIST_ENTRY        *Link;
   MEMORY_MAP        *Entry;
+  EFI_STATUS        Status;
 
   ASSERT ((Start & EFI_PAGE_MASK) == 0);
   ASSERT (End > Start) ;
@@ -188,7 +189,17 @@ 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);
+    } else if (gCpu != NULL) {
+      Status = gCpu->SetMemoryAttributes(gCpu, 0, EFI_PAGE_SIZE, 0);
+      ASSERT_EFI_ERROR(Status);
+
+      SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);
+
+      Status = gCpu->SetMemoryAttributes(gCpu, 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);
+      ASSERT_EFI_ERROR(Status);
+    }
   }
   
   //
@@ -1972,11 +1983,3 @@ Done:
   return Status;
 }
 
-
-
-
-
-
-
-
-
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
index a73c4ccd64..2367d674e1 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,22 @@ 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 ;
 }
 
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
index 72d2532f50..104599156c 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
@@ -52,6 +52,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define STACK_SIZE      0x20000
 #define BSP_STORE_SIZE  0x4000
 
+#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & BIT0) != 0)
 
 //
 // This PPI is installed to indicate the end of the PEI usage of memory
@@ -240,4 +241,18 @@ 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
+  );
+
 #endif
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
index c54afe4aa6..fde70f94bb 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
@@ -110,11 +110,12 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables       ## CONSUMES
 
 [FeaturePcd]
-  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress         ## CONSUMES
 
 [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..b5f9d92f5b 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
@@ -825,3 +825,56 @@ 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          RscDescHob;
+  EFI_PEI_HOB_POINTERS          MemAllocHob;
+  BOOLEAN                       DoClear;
+
+  RscDescHob.Raw = HobStart;
+  MemAllocHob.Raw = HobStart;
+  DoClear = FALSE;
+
+  //
+  // Check if page 0 exists and free
+  //
+  while ((RscDescHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, RscDescHob.Raw)) != NULL) {
+    if (RscDescHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && 
+        RscDescHob.ResourceDescriptor->PhysicalStart == 0) {
+      DoClear = TRUE;
+      // 
+      // Make sure memory at 0-4095 has not been allocated.
+      //
+      while ((MemAllocHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, MemAllocHob.Raw)) != NULL) {
+        if (MemAllocHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress < EFI_PAGE_SIZE) {
+          DoClear = FALSE;
+          break;
+        }
+        MemAllocHob.Raw = GET_NEXT_HOB (MemAllocHob);
+      }
+      break;
+    }
+    RscDescHob.Raw = GET_NEXT_HOB (RscDescHob);
+  }
+
+  if (DoClear) {
+    DEBUG((DEBUG_INFO, "Clearing first 4K-page!\r\n"));
+    SetMem(NULL, EFI_PAGE_SIZE, 0);
+  }
+
+  return;
+}
+
diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
index 1957326caf..a8aa0d5d1b 100644
--- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
+++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
@@ -123,7 +123,8 @@ Create4GPageTablesIa32Pae (
     PageDirectoryPointerEntry->Bits.Present = 1;
 
     for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {
-      if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase)) {
+      if ((NULL_DETECTION_ENABLED && PhysicalAddress == 0)
+          || ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase))) {
         //
         // Need to split this 2M page that covers stack range.
         //
@@ -240,6 +241,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 +382,8 @@ 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) || NULL_DETECTION_ENABLED));
     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..50a8d77a5b 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..ccd6e10cb2 100644
--- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
+++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
@@ -90,8 +90,14 @@ Split2MPageTo4K (
     //
     PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;
     PageTableEntry->Bits.ReadWrite = 1;
-    PageTableEntry->Bits.Present = 1;
-    if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + StackSize)) {
+
+    if (NULL_DETECTION_ENABLED && 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 +143,10 @@ Split1GPageTo2M (
 
   PhysicalAddress2M = PhysicalAddress;
   for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {
-    if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + SIZE_2MB) > StackBase)) {
+    if ((NULL_DETECTION_ENABLED && 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 +286,8 @@ 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 ((NULL_DETECTION_ENABLED && PageAddress == 0)
+            || (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_1GB) > StackBase))) {
           Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize);
         } else {
           //
@@ -308,9 +316,10 @@ 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 ((NULL_DETECTION_ENABLED && 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 {
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 593bff357a..1cc84894af 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -860,6 +860,18 @@
   # @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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel



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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  1:17       ` Wang, Jian J
@ 2017-09-14  3:17         ` Wang, Jian J
  2017-09-14  8:30           ` Laszlo Ersek
  2017-09-14  5:50         ` Jordan Justen
  2017-09-14  8:26         ` Laszlo Ersek
  2 siblings, 1 reply; 37+ messages in thread
From: Wang, Jian J @ 2017-09-14  3:17 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Dong, Eric, Justen, Jordan L, edk2-devel@lists.01.org,
	Yao, Jiewen, Wolman, Ayellet, Kinney, Michael D, Zeng, Star

For the use of arch protocol, there's one thing I mentioned is not accurate. I actually tried gDS->SetMemorySpaceAttributes() but it cannot change page attributes. That's why I have to turn to cpu arch protocol.

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
Sent: Thursday, September 14, 2017 9:17 AM
To: Laszlo Ersek <lersek@redhat.com>
Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Yao, Jiewen <jiewen.yao@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

Thanks for the comments and good advices. Sorry the format issues.
This is my first patch for this project. Too many details for me to get 
familiar with. 

(1) Sure.
(2) I'll change that.
(3) I'll use the tool to ensure the patch format.
(4) I'll remove the ',' in name
(5) I'll add more description about it.
(6) You're right. I should use SetMemorySpaceAttributes() of DXE service
     instead. The only reason I didn't do it is that I found 
      GetMemorySpaceDescriptor() doesn't return the same information
     which SetMemorySpaceAttributes() just changed. So I feel using CPU
    arch protocol is a bit safer. Anyway, I'll change it.
(7) I did put those macros in the install function before. To reduce the
     number of changed files, I made current changes. You're right it's
     not worthy.
(8) Using macro can help the readability, which is more important to me.
    I know function can do the same. But it looks a bit heavy in this situation.
    I have to admit replacing  the macros with a library is a very good idea,  
    which brings the same readability. I didn't think of that before. Although 
    Library is still a little bit heavy to me but it's in a different way, I think it 
    worth a trying.
(9) Putting a space before open parenthesis is forced style? If so, I'll add it.
(10) You're right. Using library can reduce the disturbs to affected drivers
       by this feature to the minimum.

-----Original Message-----
From: Laszlo Ersek [mailto:lersek@redhat.com] 
Sent: Thursday, September 14, 2017 7:35 AM
To: Wang, Jian J <jian.j.wang@intel.com>
Cc: edk2-devel@lists.01.org; Justen, Jordan L <jordan.l.justen@intel.com>; Dong, Eric <eric.dong@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

Hi,

some of the points I'm going to make have already been pointed out by
Jordan:

(1) When posting a patch series, please collect the Cc: tags from all of
the patches, and add them *all* to the cover letter. This way everyone
will get a personal copy of the general description.


(2) The subject line is too long. One possible simplification:

OvmfPkg/QemuVideoDxe: bypass NULL pointer detection


On 09/13/17 11:25, Wang, Jian J wrote:
> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
> detection is enabled, page 0 must be enabled temporarily before
> installing and disabled again afterwards. For Windows 7 boot, BIT7 of
> PcdNullPointerDetectionPropertyMask must still be set to avoid hang.

(3) Subject line and commit message both should not exceed 74 characters
line length. (Not sure how many chars PatchCheck.py actually enforces, I
always stick with 74, following the Linux kernel tradition.)

I rewrapped the commit message here for readability.


>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Justen, Jordan L <jordan.l.justen@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>

(4) I think this is also something that Jordan had pointed out a long
time ago (apologies if I mis-remember):

The strings after the tags should form correct email addresses, and if
there are various email meta-characters in them, like "." (dot) and ","
(comma), then they should be quoted, like this:

Cc: "Justen, Jordan L" <jordan.l.justen@intel.com>
Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>
Cc: "Wolman, Ayellet" <ayellet.wolman@intel.com>
Suggested-by: "Wolman, Ayellet" <ayellet.wolman@intel.com>
Signed-off-by: "Wang, Jian J" <jian.j.wang@intel.com>

If you look at the actual addresses on the emails that have been sent
out, you can see they are all malformed. For example, I have:

"Jordan L <jordan.l.justen@intel.com>" for Jordan -- the part before the
comma was taken to be a separate email address (a malformed one).

At least for my reply, I have fixed up the email addresses.


(5) The commit message mentions BIT7 of the new PCD.

First, thanks for checking Windows 7 boot (and I'm happy that I got
suspicious of the feature with regard to Windows 7). I think BIT7 is a
good feature.

However, please include the short description of that feature in the
commit message -- it is one sentence; "Disable NULL pointer detection
just after EndOfDxe."

(I think BIT7 is a really smart feature, and I like *how* it is used in
"NULL_DETECTION_ENABLED" below. The check means, "if the protection is
enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".

This doesn't mean that I like the NULL_DETECTION_ENABLED macro itself;
more on that below.)


> ---
>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>  3 files changed, 32 insertions(+), 1 deletion(-)
>
> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
> index 0dce80e59b..ee0eed7214 100644
> --- a/OvmfPkg/QemuVideoDxe/Driver.c
> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>    PCI_TYPE00                        Pci;
>    QEMU_VIDEO_CARD                   *Card;
>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;

(6) I believe I mentioned this in the earlier discussion, in some form,
but now I'll say it again:

A UEFI driver has no business poking at the CPU Arch protocol. The PI
spec (1.6) states,

  12.3 CPU Architectural Protocol
  EFI_CPU_ARCH_PROTOCOL

  Summary

  Abstracts the processor services that are required to implement some
  of the DXE services. This protocol must be produced by a boot service
  or runtime DXE driver and may only be consumed by the DXE Foundation
  and DXE drivers that produce architectural protocols.

The DXE core is obviously free to use the CPU Arch protocol, but a UEFI
driver is forbidden from it, *even if* we say that, in this UEFI driver,
we are going to use DXE services. (Which come from the PI spec, and not
the UEFI spec.)

Therefore, here we have to use gDS->SetMemorySpaceAttributes().

The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch
protocol, by the PI spec. It is not easy to see, because the PI spec has
a formatting error in this area. If you look under
GetMemorySpaceDescriptor(), there is an error code

  EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
                         architectural protocol is not available yet.

Obviously this error code belongs to SetMemorySpaceAttributes(), not
GetMemorySpaceDescriptor().

Anyway, gDS should be used, architectural protocols shouldn't be.


>
>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>
> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
>  #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>        Private->Variant == QEMU_VIDEO_BOCHS) {
> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
> +    //
> +    // Prepare CPU arch protocol for NULL pointer detection
> +    //
> +    Status = gBS->LocateProtocol (
> +                    &gEfiCpuArchProtocolGuid,
> +                    NULL,
> +                    (VOID **) &Cpu
> +                    );
> +    ASSERT_EFI_ERROR (Status);
> +
> +    DISABLE_NULL_DETECTION(Cpu);
> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
> +    ENABLE_NULL_DETECTION(Cpu);

(7) The NULL detection disabling and enabling should bracket the
affected code as tightly as possible.

So please move this into InstallVbeShim() accordingly.


>    }
>  #endif
>
> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
> index 7fbb25b3ef..bb3bc6eb0f 100644
> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
> @@ -25,6 +25,7 @@
>  #include <Protocol/PciIo.h>
>  #include <Protocol/DriverSupportedEfiVersion.h>
>  #include <Protocol/DevicePath.h>
> +#include <Protocol/Cpu.h>
>
>  #include <Library/DebugLib.h>
>  #include <Library/UefiDriverEntryPoint.h>
> @@ -82,6 +83,21 @@ typedef struct {
>
>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>
> +//
> +// VBE code will access memory between 0-4095 which will cause page fault exception
> +// if NULL pointer detection mechanism is enabled. Following macros can be used to
> +// disable/enable NULL pointer detection before/after accessing those memory.
> +//
> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
> +  if (NULL_DETECTION_ENABLED) {                                                 \
> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
> +  }
> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
> +  if (NULL_DETECTION_ENABLED) {                                                 \
> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
> +  }
> +

(8) I believe Jordan too commented on these macros elsewhere (under
patch 1/4).

In my opinion, this functionality should be extracted into a library
class, with a library instance that is suitable for at least UEFI_DRIVER
modules. (Maybe even for DXE_DRIVER modules.)

You could add a separate library instance for SMM drivers, if that were
necessary.


(9) Style comment: please put one space character between the function
designator and the opening parenthesis.


>  //
>  // QEMU Video Private Data Structure
>  //
> diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> index 7c7d429bca..5d166eb99c 100644
> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> @@ -72,7 +72,9 @@
>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
> +  gEfiCpuArchProtocolGuid
>
>  [Pcd]
>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask

(10) Instead of these, the library class that I described under (8)
should be added here.

Any further dependencies like PCDs, protocols etc should be inherited by
the driver through the library instance that the platform DSC file
resolves the library class to.

Bonus: should you realize that the feature is impossible to implement
without accessing the CPU Arch protocol directly, you could hide the
protocol GUID dependency in the library instance INF file, and I'd be
none the wiser.

... Well, I could at least pretend that. :)

Thanks,
Laszlo
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  1:17       ` Wang, Jian J
  2017-09-14  3:17         ` Wang, Jian J
@ 2017-09-14  5:50         ` Jordan Justen
  2017-09-14  6:52           ` Wang, Jian J
  2017-09-14  8:26         ` Laszlo Ersek
  2 siblings, 1 reply; 37+ messages in thread
From: Jordan Justen @ 2017-09-14  5:50 UTC (permalink / raw)
  To: Wang, Jian J, Laszlo Ersek
  Cc: edk2-devel@lists.01.org, Dong, Eric, Kinney, Michael D,
	Wolman, Ayellet, Yao, Jiewen, Zeng, Star

On 2017-09-13 18:17:26, Wang, Jian J wrote:
> Thanks for the comments and good advices. Sorry the format issues.
> This is my first patch for this project. Too many details for me to get 
> familiar with. 
> 
> (1) Sure.
> (2) I'll change that.
> (3) I'll use the tool to ensure the patch format.
> (4) I'll remove the ',' in name
> (5) I'll add more description about it.
> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>      instead. The only reason I didn't do it is that I found 
>       GetMemorySpaceDescriptor() doesn't return the same information
>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>     arch protocol is a bit safer. Anyway, I'll change it.
> (7) I did put those macros in the install function before. To reduce the
>      number of changed files, I made current changes. You're right it's
>      not worthy.
> (8) Using macro can help the readability, which is more important to me.
>     I know function can do the same. But it looks a bit heavy in this situation.

A macro can sometimes help readibility if it is doing a very common
task. I see the macros are only being used in 2 places. (Once each.)

In this case I would prefer you to just write the code all out rather
than using macros. I don't think it will make the code that much
bigger in this case, and it'll be easier to know what the code is
actually doing.

-Jordan

>     I have to admit replacing  the macros with a library is a very good idea,  
>     which brings the same readability. I didn't think of that before. Although 
>     Library is still a little bit heavy to me but it's in a different way, I think it 
>     worth a trying.
> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
> (10) You're right. Using library can reduce the disturbs to affected drivers
>        by this feature to the minimum.
> 
> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com] 
> Sent: Thursday, September 14, 2017 7:35 AM
> To: Wang, Jian J <jian.j.wang@intel.com>
> Cc: edk2-devel@lists.01.org; Justen, Jordan L <jordan.l.justen@intel.com>; Dong, Eric <eric.dong@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> Hi,
> 
> some of the points I'm going to make have already been pointed out by
> Jordan:
> 
> (1) When posting a patch series, please collect the Cc: tags from all of
> the patches, and add them *all* to the cover letter. This way everyone
> will get a personal copy of the general description.
> 
> 
> (2) The subject line is too long. One possible simplification:
> 
> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
> 
> 
> On 09/13/17 11:25, Wang, Jian J wrote:
> > QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
> > detection is enabled, page 0 must be enabled temporarily before
> > installing and disabled again afterwards. For Windows 7 boot, BIT7 of
> > PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
> 
> (3) Subject line and commit message both should not exceed 74 characters
> line length. (Not sure how many chars PatchCheck.py actually enforces, I
> always stick with 74, following the Linux kernel tradition.)
> 
> I rewrapped the commit message here for readability.
> 
> 
> >
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Eric Dong <eric.dong@intel.com>
> > Cc: Star Zeng <star.zeng@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Justen, Jordan L <jordan.l.justen@intel.com>
> > Cc: Kinney, Michael D <michael.d.kinney@intel.com>
> > Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
> > Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
> 
> (4) I think this is also something that Jordan had pointed out a long
> time ago (apologies if I mis-remember):
> 
> The strings after the tags should form correct email addresses, and if
> there are various email meta-characters in them, like "." (dot) and ","
> (comma), then they should be quoted, like this:
> 
> Cc: "Justen, Jordan L" <jordan.l.justen@intel.com>
> Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>
> Cc: "Wolman, Ayellet" <ayellet.wolman@intel.com>
> Suggested-by: "Wolman, Ayellet" <ayellet.wolman@intel.com>
> Signed-off-by: "Wang, Jian J" <jian.j.wang@intel.com>
> 
> If you look at the actual addresses on the emails that have been sent
> out, you can see they are all malformed. For example, I have:
> 
> "Jordan L <jordan.l.justen@intel.com>" for Jordan -- the part before the
> comma was taken to be a separate email address (a malformed one).
> 
> At least for my reply, I have fixed up the email addresses.
> 
> 
> (5) The commit message mentions BIT7 of the new PCD.
> 
> First, thanks for checking Windows 7 boot (and I'm happy that I got
> suspicious of the feature with regard to Windows 7). I think BIT7 is a
> good feature.
> 
> However, please include the short description of that feature in the
> commit message -- it is one sentence; "Disable NULL pointer detection
> just after EndOfDxe."
> 
> (I think BIT7 is a really smart feature, and I like *how* it is used in
> "NULL_DETECTION_ENABLED" below. The check means, "if the protection is
> enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
> 
> This doesn't mean that I like the NULL_DETECTION_ENABLED macro itself;
> more on that below.)
> 
> 
> > ---
> >  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
> >  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
> >  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
> >  3 files changed, 32 insertions(+), 1 deletion(-)
> >
> > diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
> > index 0dce80e59b..ee0eed7214 100644
> > --- a/OvmfPkg/QemuVideoDxe/Driver.c
> > +++ b/OvmfPkg/QemuVideoDxe/Driver.c
> > @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
> >    PCI_TYPE00                        Pci;
> >    QEMU_VIDEO_CARD                   *Card;
> >    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
> > +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
> 
> (6) I believe I mentioned this in the earlier discussion, in some form,
> but now I'll say it again:
> 
> A UEFI driver has no business poking at the CPU Arch protocol. The PI
> spec (1.6) states,
> 
>   12.3 CPU Architectural Protocol
>   EFI_CPU_ARCH_PROTOCOL
> 
>   Summary
> 
>   Abstracts the processor services that are required to implement some
>   of the DXE services. This protocol must be produced by a boot service
>   or runtime DXE driver and may only be consumed by the DXE Foundation
>   and DXE drivers that produce architectural protocols.
> 
> The DXE core is obviously free to use the CPU Arch protocol, but a UEFI
> driver is forbidden from it, *even if* we say that, in this UEFI driver,
> we are going to use DXE services. (Which come from the PI spec, and not
> the UEFI spec.)
> 
> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
> 
> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch
> protocol, by the PI spec. It is not easy to see, because the PI spec has
> a formatting error in this area. If you look under
> GetMemorySpaceDescriptor(), there is an error code
> 
>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>                          architectural protocol is not available yet.
> 
> Obviously this error code belongs to SetMemorySpaceAttributes(), not
> GetMemorySpaceDescriptor().
> 
> Anyway, gDS should be used, architectural protocols shouldn't be.
> 
> 
> >
> >    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> >
> > @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
> >  #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
> >    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
> >        Private->Variant == QEMU_VIDEO_BOCHS) {
> > -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
> > +    //
> > +    // Prepare CPU arch protocol for NULL pointer detection
> > +    //
> > +    Status = gBS->LocateProtocol (
> > +                    &gEfiCpuArchProtocolGuid,
> > +                    NULL,
> > +                    (VOID **) &Cpu
> > +                    );
> > +    ASSERT_EFI_ERROR (Status);
> > +
> > +    DISABLE_NULL_DETECTION(Cpu);
> > +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
> > +    ENABLE_NULL_DETECTION(Cpu);
> 
> (7) The NULL detection disabling and enabling should bracket the
> affected code as tightly as possible.
> 
> So please move this into InstallVbeShim() accordingly.
> 
> 
> >    }
> >  #endif
> >
> > diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
> > index 7fbb25b3ef..bb3bc6eb0f 100644
> > --- a/OvmfPkg/QemuVideoDxe/Qemu.h
> > +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
> > @@ -25,6 +25,7 @@
> >  #include <Protocol/PciIo.h>
> >  #include <Protocol/DriverSupportedEfiVersion.h>
> >  #include <Protocol/DevicePath.h>
> > +#include <Protocol/Cpu.h>
> >
> >  #include <Library/DebugLib.h>
> >  #include <Library/UefiDriverEntryPoint.h>
> > @@ -82,6 +83,21 @@ typedef struct {
> >
> >  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
> >
> > +//
> > +// VBE code will access memory between 0-4095 which will cause page fault exception
> > +// if NULL pointer detection mechanism is enabled. Following macros can be used to
> > +// disable/enable NULL pointer detection before/after accessing those memory.
> > +//
> > +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
> > +#define DISABLE_NULL_DETECTION(Cpu)                                             \
> > +  if (NULL_DETECTION_ENABLED) {                                                 \
> > +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
> > +  }
> > +#define ENABLE_NULL_DETECTION(Cpu)                                              \
> > +  if (NULL_DETECTION_ENABLED) {                                                 \
> > +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
> > +  }
> > +
> 
> (8) I believe Jordan too commented on these macros elsewhere (under
> patch 1/4).
> 
> In my opinion, this functionality should be extracted into a library
> class, with a library instance that is suitable for at least UEFI_DRIVER
> modules. (Maybe even for DXE_DRIVER modules.)
> 
> You could add a separate library instance for SMM drivers, if that were
> necessary.
> 
> 
> (9) Style comment: please put one space character between the function
> designator and the opening parenthesis.
> 
> 
> >  //
> >  // QEMU Video Private Data Structure
> >  //
> > diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> > index 7c7d429bca..5d166eb99c 100644
> > --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> > +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> > @@ -72,7 +72,9 @@
> >    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
> >    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
> >    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
> > +  gEfiCpuArchProtocolGuid
> >
> >  [Pcd]
> >    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
> 
> (10) Instead of these, the library class that I described under (8)
> should be added here.
> 
> Any further dependencies like PCDs, protocols etc should be inherited by
> the driver through the library instance that the platform DSC file
> resolves the library class to.
> 
> Bonus: should you realize that the feature is impossible to implement
> without accessing the CPU Arch protocol directly, you could hide the
> protocol GUID dependency in the library instance INF file, and I'd be
> none the wiser.
> 
> ... Well, I could at least pretend that. :)
> 
> Thanks,
> Laszlo


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

* Re: [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.
  2017-09-14  1:25       ` Wang, Jian J
@ 2017-09-14  6:33         ` Jordan Justen
  2017-09-14  6:51           ` Wang, Jian J
  0 siblings, 1 reply; 37+ messages in thread
From: Jordan Justen @ 2017-09-14  6:33 UTC (permalink / raw)
  To: Wang, Jian J, edk2-devel@lists.01.org
  Cc: Yao, Jiewen, Dong, Eric, Zeng, Star, Laszlo Ersek,
	Kinney, Michael D, Wolman, Ayellet

On 2017-09-13 18:25:22, Wang, Jian J wrote:
> See my comments start with [Jian] below.
> 
> -----Original Message-----
> From: Justen, Jordan L 
> Sent: Thursday, September 14, 2017 1:28 AM
> 
> > diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
> > index 30d5984f7c..273b8b7c0e 100644
> > --- a/MdeModulePkg/Core/Dxe/DxeMain.inf
> > +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
> > @@ -179,7 +179,7 @@
> >    gEfiWatchdogTimerArchProtocolGuid             ## CONSUMES
> >  
> >  [FeaturePcd]
> > -  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport         ## CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport          ## CONSUMES
> 
> Why is this line changed?
> [Jian] Just align the comment followed because the new one added

I was looking in the patch, and it didn't look like it was now aligned
with the comments above or below. (It is 1 column less than the
section below, right?)

My opinion is to not change the line since it is in a separate section
of the inf file.

-Jordan

> 
> >  
> >  [Pcd]
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber    ## SOMETIMES_CONSUMES
> > @@ -192,6 +192,7 @@
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdPropertiesTableEnable                   ## CONSUMES
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy                   ## CONSUMES
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy             ## CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask        ## CONSUMES


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

* Re: [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.
  2017-09-14  6:33         ` Jordan Justen
@ 2017-09-14  6:51           ` Wang, Jian J
  2017-09-14  8:22             ` Laszlo Ersek
  0 siblings, 1 reply; 37+ messages in thread
From: Wang, Jian J @ 2017-09-14  6:51 UTC (permalink / raw)
  To: Justen, Jordan L, edk2-devel@lists.01.org
  Cc: Yao, Jiewen, Dong, Eric, Zeng, Star, Laszlo Ersek,
	Kinney, Michael D, Wolman, Ayellet

It's a tab character in old version. It may look like the same if your tab width is to a certain number. In my editor, it looks unaligned. Sometimes I just can't resist the temptation to fix the tab:)   I'll restore it to avoid irrelevant changes in next patch update.

-----Original Message-----
From: Justen, Jordan L 
Sent: Thursday, September 14, 2017 2:34 PM
To: Wang, Jian J <jian.j.wang@intel.com>; edk2-devel@lists.01.org
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Dong, Eric <eric.dong@intel.com>; Zeng, Star <star.zeng@intel.com>; Laszlo Ersek <lersek@redhat.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
Subject: RE: [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.

On 2017-09-13 18:25:22, Wang, Jian J wrote:
> See my comments start with [Jian] below.
> 
> -----Original Message-----
> From: Justen, Jordan L 
> Sent: Thursday, September 14, 2017 1:28 AM
> 
> > diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
> > index 30d5984f7c..273b8b7c0e 100644
> > --- a/MdeModulePkg/Core/Dxe/DxeMain.inf
> > +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
> > @@ -179,7 +179,7 @@
> >    gEfiWatchdogTimerArchProtocolGuid             ## CONSUMES
> >  
> >  [FeaturePcd]
> > -  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport         ## CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport          ## CONSUMES
> 
> Why is this line changed?
> [Jian] Just align the comment followed because the new one added

I was looking in the patch, and it didn't look like it was now aligned
with the comments above or below. (It is 1 column less than the
section below, right?)

My opinion is to not change the line since it is in a separate section
of the inf file.

-Jordan

> 
> >  
> >  [Pcd]
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber    ## SOMETIMES_CONSUMES
> > @@ -192,6 +192,7 @@
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdPropertiesTableEnable                   ## CONSUMES
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy                   ## CONSUMES
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy             ## CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask        ## CONSUMES

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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  5:50         ` Jordan Justen
@ 2017-09-14  6:52           ` Wang, Jian J
  0 siblings, 0 replies; 37+ messages in thread
From: Wang, Jian J @ 2017-09-14  6:52 UTC (permalink / raw)
  To: Justen, Jordan L, Laszlo Ersek
  Cc: edk2-devel@lists.01.org, Dong, Eric, Kinney, Michael D,
	Wolman, Ayellet, Yao, Jiewen, Zeng, Star

Sure. I'll change them to functions.

-----Original Message-----
From: Justen, Jordan L 
Sent: Thursday, September 14, 2017 1:50 PM
To: Wang, Jian J <jian.j.wang@intel.com>; Laszlo Ersek <lersek@redhat.com>
Cc: edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

On 2017-09-13 18:17:26, Wang, Jian J wrote:
> Thanks for the comments and good advices. Sorry the format issues.
> This is my first patch for this project. Too many details for me to get 
> familiar with. 
> 
> (1) Sure.
> (2) I'll change that.
> (3) I'll use the tool to ensure the patch format.
> (4) I'll remove the ',' in name
> (5) I'll add more description about it.
> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>      instead. The only reason I didn't do it is that I found 
>       GetMemorySpaceDescriptor() doesn't return the same information
>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>     arch protocol is a bit safer. Anyway, I'll change it.
> (7) I did put those macros in the install function before. To reduce the
>      number of changed files, I made current changes. You're right it's
>      not worthy.
> (8) Using macro can help the readability, which is more important to me.
>     I know function can do the same. But it looks a bit heavy in this situation.

A macro can sometimes help readibility if it is doing a very common
task. I see the macros are only being used in 2 places. (Once each.)

In this case I would prefer you to just write the code all out rather
than using macros. I don't think it will make the code that much
bigger in this case, and it'll be easier to know what the code is
actually doing.

-Jordan

>     I have to admit replacing  the macros with a library is a very good idea,  
>     which brings the same readability. I didn't think of that before. Although 
>     Library is still a little bit heavy to me but it's in a different way, I think it 
>     worth a trying.
> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
> (10) You're right. Using library can reduce the disturbs to affected drivers
>        by this feature to the minimum.
> 
> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com] 
> Sent: Thursday, September 14, 2017 7:35 AM
> To: Wang, Jian J <jian.j.wang@intel.com>
> Cc: edk2-devel@lists.01.org; Justen, Jordan L <jordan.l.justen@intel.com>; Dong, Eric <eric.dong@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> Hi,
> 
> some of the points I'm going to make have already been pointed out by
> Jordan:
> 
> (1) When posting a patch series, please collect the Cc: tags from all of
> the patches, and add them *all* to the cover letter. This way everyone
> will get a personal copy of the general description.
> 
> 
> (2) The subject line is too long. One possible simplification:
> 
> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
> 
> 
> On 09/13/17 11:25, Wang, Jian J wrote:
> > QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
> > detection is enabled, page 0 must be enabled temporarily before
> > installing and disabled again afterwards. For Windows 7 boot, BIT7 of
> > PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
> 
> (3) Subject line and commit message both should not exceed 74 characters
> line length. (Not sure how many chars PatchCheck.py actually enforces, I
> always stick with 74, following the Linux kernel tradition.)
> 
> I rewrapped the commit message here for readability.
> 
> 
> >
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Eric Dong <eric.dong@intel.com>
> > Cc: Star Zeng <star.zeng@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Justen, Jordan L <jordan.l.justen@intel.com>
> > Cc: Kinney, Michael D <michael.d.kinney@intel.com>
> > Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
> > Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
> 
> (4) I think this is also something that Jordan had pointed out a long
> time ago (apologies if I mis-remember):
> 
> The strings after the tags should form correct email addresses, and if
> there are various email meta-characters in them, like "." (dot) and ","
> (comma), then they should be quoted, like this:
> 
> Cc: "Justen, Jordan L" <jordan.l.justen@intel.com>
> Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>
> Cc: "Wolman, Ayellet" <ayellet.wolman@intel.com>
> Suggested-by: "Wolman, Ayellet" <ayellet.wolman@intel.com>
> Signed-off-by: "Wang, Jian J" <jian.j.wang@intel.com>
> 
> If you look at the actual addresses on the emails that have been sent
> out, you can see they are all malformed. For example, I have:
> 
> "Jordan L <jordan.l.justen@intel.com>" for Jordan -- the part before the
> comma was taken to be a separate email address (a malformed one).
> 
> At least for my reply, I have fixed up the email addresses.
> 
> 
> (5) The commit message mentions BIT7 of the new PCD.
> 
> First, thanks for checking Windows 7 boot (and I'm happy that I got
> suspicious of the feature with regard to Windows 7). I think BIT7 is a
> good feature.
> 
> However, please include the short description of that feature in the
> commit message -- it is one sentence; "Disable NULL pointer detection
> just after EndOfDxe."
> 
> (I think BIT7 is a really smart feature, and I like *how* it is used in
> "NULL_DETECTION_ENABLED" below. The check means, "if the protection is
> enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
> 
> This doesn't mean that I like the NULL_DETECTION_ENABLED macro itself;
> more on that below.)
> 
> 
> > ---
> >  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
> >  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
> >  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
> >  3 files changed, 32 insertions(+), 1 deletion(-)
> >
> > diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
> > index 0dce80e59b..ee0eed7214 100644
> > --- a/OvmfPkg/QemuVideoDxe/Driver.c
> > +++ b/OvmfPkg/QemuVideoDxe/Driver.c
> > @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
> >    PCI_TYPE00                        Pci;
> >    QEMU_VIDEO_CARD                   *Card;
> >    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
> > +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
> 
> (6) I believe I mentioned this in the earlier discussion, in some form,
> but now I'll say it again:
> 
> A UEFI driver has no business poking at the CPU Arch protocol. The PI
> spec (1.6) states,
> 
>   12.3 CPU Architectural Protocol
>   EFI_CPU_ARCH_PROTOCOL
> 
>   Summary
> 
>   Abstracts the processor services that are required to implement some
>   of the DXE services. This protocol must be produced by a boot service
>   or runtime DXE driver and may only be consumed by the DXE Foundation
>   and DXE drivers that produce architectural protocols.
> 
> The DXE core is obviously free to use the CPU Arch protocol, but a UEFI
> driver is forbidden from it, *even if* we say that, in this UEFI driver,
> we are going to use DXE services. (Which come from the PI spec, and not
> the UEFI spec.)
> 
> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
> 
> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch
> protocol, by the PI spec. It is not easy to see, because the PI spec has
> a formatting error in this area. If you look under
> GetMemorySpaceDescriptor(), there is an error code
> 
>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>                          architectural protocol is not available yet.
> 
> Obviously this error code belongs to SetMemorySpaceAttributes(), not
> GetMemorySpaceDescriptor().
> 
> Anyway, gDS should be used, architectural protocols shouldn't be.
> 
> 
> >
> >    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> >
> > @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
> >  #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
> >    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
> >        Private->Variant == QEMU_VIDEO_BOCHS) {
> > -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
> > +    //
> > +    // Prepare CPU arch protocol for NULL pointer detection
> > +    //
> > +    Status = gBS->LocateProtocol (
> > +                    &gEfiCpuArchProtocolGuid,
> > +                    NULL,
> > +                    (VOID **) &Cpu
> > +                    );
> > +    ASSERT_EFI_ERROR (Status);
> > +
> > +    DISABLE_NULL_DETECTION(Cpu);
> > +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
> > +    ENABLE_NULL_DETECTION(Cpu);
> 
> (7) The NULL detection disabling and enabling should bracket the
> affected code as tightly as possible.
> 
> So please move this into InstallVbeShim() accordingly.
> 
> 
> >    }
> >  #endif
> >
> > diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
> > index 7fbb25b3ef..bb3bc6eb0f 100644
> > --- a/OvmfPkg/QemuVideoDxe/Qemu.h
> > +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
> > @@ -25,6 +25,7 @@
> >  #include <Protocol/PciIo.h>
> >  #include <Protocol/DriverSupportedEfiVersion.h>
> >  #include <Protocol/DevicePath.h>
> > +#include <Protocol/Cpu.h>
> >
> >  #include <Library/DebugLib.h>
> >  #include <Library/UefiDriverEntryPoint.h>
> > @@ -82,6 +83,21 @@ typedef struct {
> >
> >  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
> >
> > +//
> > +// VBE code will access memory between 0-4095 which will cause page fault exception
> > +// if NULL pointer detection mechanism is enabled. Following macros can be used to
> > +// disable/enable NULL pointer detection before/after accessing those memory.
> > +//
> > +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
> > +#define DISABLE_NULL_DETECTION(Cpu)                                             \
> > +  if (NULL_DETECTION_ENABLED) {                                                 \
> > +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
> > +  }
> > +#define ENABLE_NULL_DETECTION(Cpu)                                              \
> > +  if (NULL_DETECTION_ENABLED) {                                                 \
> > +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
> > +  }
> > +
> 
> (8) I believe Jordan too commented on these macros elsewhere (under
> patch 1/4).
> 
> In my opinion, this functionality should be extracted into a library
> class, with a library instance that is suitable for at least UEFI_DRIVER
> modules. (Maybe even for DXE_DRIVER modules.)
> 
> You could add a separate library instance for SMM drivers, if that were
> necessary.
> 
> 
> (9) Style comment: please put one space character between the function
> designator and the opening parenthesis.
> 
> 
> >  //
> >  // QEMU Video Private Data Structure
> >  //
> > diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> > index 7c7d429bca..5d166eb99c 100644
> > --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> > +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
> > @@ -72,7 +72,9 @@
> >    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
> >    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
> >    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
> > +  gEfiCpuArchProtocolGuid
> >
> >  [Pcd]
> >    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
> 
> (10) Instead of these, the library class that I described under (8)
> should be added here.
> 
> Any further dependencies like PCDs, protocols etc should be inherited by
> the driver through the library instance that the platform DSC file
> resolves the library class to.
> 
> Bonus: should you realize that the feature is impossible to implement
> without accessing the CPU Arch protocol directly, you could hide the
> protocol GUID dependency in the library instance INF file, and I'd be
> none the wiser.
> 
> ... Well, I could at least pretend that. :)
> 
> Thanks,
> Laszlo

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

* Re: [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core.
  2017-09-14  6:51           ` Wang, Jian J
@ 2017-09-14  8:22             ` Laszlo Ersek
  0 siblings, 0 replies; 37+ messages in thread
From: Laszlo Ersek @ 2017-09-14  8:22 UTC (permalink / raw)
  To: Wang, Jian J, Justen, Jordan L, edk2-devel@lists.01.org
  Cc: Yao, Jiewen, Dong, Eric, Zeng, Star, Kinney, Michael D,
	Wolman, Ayellet

On 09/14/17 08:51, Wang, Jian J wrote:
> It's a tab character in old version. It may look like the same if
> your tab width is to a certain number. In my editor, it looks
> unaligned. Sometimes I just can't resist the temptation to fix the
> tab:)   I'll restore it to avoid irrelevant changes in next patch
> update.

It is perfectly fine (and even recommended, IMO) to fix up such warts
whenever someone comes across them, but all such fixes should be
separated out to their own dedicated patches.

Thanks
Laszlo


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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  1:17       ` Wang, Jian J
  2017-09-14  3:17         ` Wang, Jian J
  2017-09-14  5:50         ` Jordan Justen
@ 2017-09-14  8:26         ` Laszlo Ersek
  2 siblings, 0 replies; 37+ messages in thread
From: Laszlo Ersek @ 2017-09-14  8:26 UTC (permalink / raw)
  To: Wang, Jian J
  Cc: edk2-devel@lists.01.org, Justen, Jordan L, Dong, Eric,
	Kinney, Michael D, Wolman, Ayellet, Yao, Jiewen, Zeng, Star

On 09/14/17 03:17, Wang, Jian J wrote:
> Thanks for the comments and good advices. Sorry the format issues.
> This is my first patch for this project. Too many details for me to get 
> familiar with. 
> 
> (1) Sure.
> (2) I'll change that.
> (3) I'll use the tool to ensure the patch format.
> (4) I'll remove the ',' in name
> (5) I'll add more description about it.
> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>      instead. The only reason I didn't do it is that I found 
>       GetMemorySpaceDescriptor() doesn't return the same information
>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>     arch protocol is a bit safer. Anyway, I'll change it.
> (7) I did put those macros in the install function before. To reduce the
>      number of changed files, I made current changes. You're right it's
>      not worthy.
> (8) Using macro can help the readability, which is more important to me.
>     I know function can do the same. But it looks a bit heavy in this situation.
>     I have to admit replacing  the macros with a library is a very good idea,  
>     which brings the same readability. I didn't think of that before. Although 
>     Library is still a little bit heavy to me but it's in a different way, I think it 
>     worth a trying.
> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.

Yes, it is in the CCS:

https://edk2-docs.gitbooks.io/edk-ii-c-coding-standards-specification/content/5_source_files/52_spacing.html#52-spacing

> 5.2.2.6 Always put space before an open parenthesis
>
> The only exception is macro definitions.
>
> if (...
> while (...
> EfiLibAllocateCopyPool (...

Thanks,
Laszlo


> (10) You're right. Using library can reduce the disturbs to affected drivers
>        by this feature to the minimum.



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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  3:17         ` Wang, Jian J
@ 2017-09-14  8:30           ` Laszlo Ersek
  2017-09-14  8:38             ` Yao, Jiewen
  0 siblings, 1 reply; 37+ messages in thread
From: Laszlo Ersek @ 2017-09-14  8:30 UTC (permalink / raw)
  To: Wang, Jian J
  Cc: Dong, Eric, Justen, Jordan L, edk2-devel@lists.01.org,
	Yao, Jiewen, Wolman, Ayellet, Kinney, Michael D, Zeng, Star

On 09/14/17 05:17, Wang, Jian J wrote:
> For the use of arch protocol, there's one thing I mentioned is not
> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it
> cannot change page attributes. That's why I have to turn to cpu arch
> protocol.
Thank you for the explanation.

In that case, we cannot avoid violating the PI spec. I agree we can
break the spec if it happens for security purposes, but in that case, I
believe that hiding the implementation behind a library class is
mandatory. Viewed from the spec side, accessing the CPU Arch protocol is
a hack, and so it should not be spread to the source code of several
driver modules.

Thank you,
Laszlo


> 
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
> Sent: Thursday, September 14, 2017 9:17 AM
> To: Laszlo Ersek <lersek@redhat.com>
> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Yao, Jiewen <jiewen.yao@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> Thanks for the comments and good advices. Sorry the format issues.
> This is my first patch for this project. Too many details for me to get 
> familiar with. 
> 
> (1) Sure.
> (2) I'll change that.
> (3) I'll use the tool to ensure the patch format.
> (4) I'll remove the ',' in name
> (5) I'll add more description about it.
> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>      instead. The only reason I didn't do it is that I found 
>       GetMemorySpaceDescriptor() doesn't return the same information
>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>     arch protocol is a bit safer. Anyway, I'll change it.
> (7) I did put those macros in the install function before. To reduce the
>      number of changed files, I made current changes. You're right it's
>      not worthy.
> (8) Using macro can help the readability, which is more important to me.
>     I know function can do the same. But it looks a bit heavy in this situation.
>     I have to admit replacing  the macros with a library is a very good idea,  
>     which brings the same readability. I didn't think of that before. Although 
>     Library is still a little bit heavy to me but it's in a different way, I think it 
>     worth a trying.
> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
> (10) You're right. Using library can reduce the disturbs to affected drivers
>        by this feature to the minimum.
> 
> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com] 
> Sent: Thursday, September 14, 2017 7:35 AM
> To: Wang, Jian J <jian.j.wang@intel.com>
> Cc: edk2-devel@lists.01.org; Justen, Jordan L <jordan.l.justen@intel.com>; Dong, Eric <eric.dong@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> Hi,
> 
> some of the points I'm going to make have already been pointed out by
> Jordan:
> 
> (1) When posting a patch series, please collect the Cc: tags from all of
> the patches, and add them *all* to the cover letter. This way everyone
> will get a personal copy of the general description.
> 
> 
> (2) The subject line is too long. One possible simplification:
> 
> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
> 
> 
> On 09/13/17 11:25, Wang, Jian J wrote:
>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
>> detection is enabled, page 0 must be enabled temporarily before
>> installing and disabled again afterwards. For Windows 7 boot, BIT7 of
>> PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
> 
> (3) Subject line and commit message both should not exceed 74 characters
> line length. (Not sure how many chars PatchCheck.py actually enforces, I
> always stick with 74, following the Linux kernel tradition.)
> 
> I rewrapped the commit message here for readability.
> 
> 
>>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Eric Dong <eric.dong@intel.com>
>> Cc: Star Zeng <star.zeng@intel.com>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Justen, Jordan L <jordan.l.justen@intel.com>
>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>
>> Cc: Wolman, Ayellet <ayellet.wolman@intel.com>
>> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com>
> 
> (4) I think this is also something that Jordan had pointed out a long
> time ago (apologies if I mis-remember):
> 
> The strings after the tags should form correct email addresses, and if
> there are various email meta-characters in them, like "." (dot) and ","
> (comma), then they should be quoted, like this:
> 
> Cc: "Justen, Jordan L" <jordan.l.justen@intel.com>
> Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>
> Cc: "Wolman, Ayellet" <ayellet.wolman@intel.com>
> Suggested-by: "Wolman, Ayellet" <ayellet.wolman@intel.com>
> Signed-off-by: "Wang, Jian J" <jian.j.wang@intel.com>
> 
> If you look at the actual addresses on the emails that have been sent
> out, you can see they are all malformed. For example, I have:
> 
> "Jordan L <jordan.l.justen@intel.com>" for Jordan -- the part before the
> comma was taken to be a separate email address (a malformed one).
> 
> At least for my reply, I have fixed up the email addresses.
> 
> 
> (5) The commit message mentions BIT7 of the new PCD.
> 
> First, thanks for checking Windows 7 boot (and I'm happy that I got
> suspicious of the feature with regard to Windows 7). I think BIT7 is a
> good feature.
> 
> However, please include the short description of that feature in the
> commit message -- it is one sentence; "Disable NULL pointer detection
> just after EndOfDxe."
> 
> (I think BIT7 is a really smart feature, and I like *how* it is used in
> "NULL_DETECTION_ENABLED" below. The check means, "if the protection is
> enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
> 
> This doesn't mean that I like the NULL_DETECTION_ENABLED macro itself;
> more on that below.)
> 
> 
>> ---
>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>
>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
>> index 0dce80e59b..ee0eed7214 100644
>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>    PCI_TYPE00                        Pci;
>>    QEMU_VIDEO_CARD                   *Card;
>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
> 
> (6) I believe I mentioned this in the earlier discussion, in some form,
> but now I'll say it again:
> 
> A UEFI driver has no business poking at the CPU Arch protocol. The PI
> spec (1.6) states,
> 
>   12.3 CPU Architectural Protocol
>   EFI_CPU_ARCH_PROTOCOL
> 
>   Summary
> 
>   Abstracts the processor services that are required to implement some
>   of the DXE services. This protocol must be produced by a boot service
>   or runtime DXE driver and may only be consumed by the DXE Foundation
>   and DXE drivers that produce architectural protocols.
> 
> The DXE core is obviously free to use the CPU Arch protocol, but a UEFI
> driver is forbidden from it, *even if* we say that, in this UEFI driver,
> we are going to use DXE services. (Which come from the PI spec, and not
> the UEFI spec.)
> 
> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
> 
> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch
> protocol, by the PI spec. It is not easy to see, because the PI spec has
> a formatting error in this area. If you look under
> GetMemorySpaceDescriptor(), there is an error code
> 
>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>                          architectural protocol is not available yet.
> 
> Obviously this error code belongs to SetMemorySpaceAttributes(), not
> GetMemorySpaceDescriptor().
> 
> Anyway, gDS should be used, architectural protocols shouldn't be.
> 
> 
>>
>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>
>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
>>  #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>> +    //
>> +    // Prepare CPU arch protocol for NULL pointer detection
>> +    //
>> +    Status = gBS->LocateProtocol (
>> +                    &gEfiCpuArchProtocolGuid,
>> +                    NULL,
>> +                    (VOID **) &Cpu
>> +                    );
>> +    ASSERT_EFI_ERROR (Status);
>> +
>> +    DISABLE_NULL_DETECTION(Cpu);
>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>> +    ENABLE_NULL_DETECTION(Cpu);
> 
> (7) The NULL detection disabling and enabling should bracket the
> affected code as tightly as possible.
> 
> So please move this into InstallVbeShim() accordingly.
> 
> 
>>    }
>>  #endif
>>
>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
>> index 7fbb25b3ef..bb3bc6eb0f 100644
>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>> @@ -25,6 +25,7 @@
>>  #include <Protocol/PciIo.h>
>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>  #include <Protocol/DevicePath.h>
>> +#include <Protocol/Cpu.h>
>>
>>  #include <Library/DebugLib.h>
>>  #include <Library/UefiDriverEntryPoint.h>
>> @@ -82,6 +83,21 @@ typedef struct {
>>
>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>
>> +//
>> +// VBE code will access memory between 0-4095 which will cause page fault exception
>> +// if NULL pointer detection mechanism is enabled. Following macros can be used to
>> +// disable/enable NULL pointer detection before/after accessing those memory.
>> +//
>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>> +  }
>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>> +  }
>> +
> 
> (8) I believe Jordan too commented on these macros elsewhere (under
> patch 1/4).
> 
> In my opinion, this functionality should be extracted into a library
> class, with a library instance that is suitable for at least UEFI_DRIVER
> modules. (Maybe even for DXE_DRIVER modules.)
> 
> You could add a separate library instance for SMM drivers, if that were
> necessary.
> 
> 
> (9) Style comment: please put one space character between the function
> designator and the opening parenthesis.
> 
> 
>>  //
>>  // QEMU Video Private Data Structure
>>  //
>> diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> index 7c7d429bca..5d166eb99c 100644
>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> @@ -72,7 +72,9 @@
>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>> +  gEfiCpuArchProtocolGuid
>>
>>  [Pcd]
>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>> +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
> 
> (10) Instead of these, the library class that I described under (8)
> should be added here.
> 
> Any further dependencies like PCDs, protocols etc should be inherited by
> the driver through the library instance that the platform DSC file
> resolves the library class to.
> 
> Bonus: should you realize that the feature is impossible to implement
> without accessing the CPU Arch protocol directly, you could hide the
> protocol GUID dependency in the library instance INF file, and I'd be
> none the wiser.
> 
> ... Well, I could at least pretend that. :)
> 
> Thanks,
> Laszlo
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
> 



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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  8:30           ` Laszlo Ersek
@ 2017-09-14  8:38             ` Yao, Jiewen
  2017-09-14  8:46               ` Wang, Jian J
  2017-09-14  8:52               ` Laszlo Ersek
  0 siblings, 2 replies; 37+ messages in thread
From: Yao, Jiewen @ 2017-09-14  8:38 UTC (permalink / raw)
  To: Laszlo Ersek, Wang, Jian J
  Cc: Dong, Eric, Justen, Jordan L, edk2-devel@lists.01.org,
	Wolman, Ayellet, Kinney, Michael D, Zeng, Star

HI
I wonder if it is spec limitation or implementation limitation.

If it is implementation limitation, we can enhance the DxeCore to allow it.

Thank you
Yao Jiewen

From: Laszlo Ersek [mailto:lersek@redhat.com]
Sent: Thursday, September 14, 2017 4:30 PM
To: Wang, Jian J <jian.j.wang@intel.com>
Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Yao, Jiewen <jiewen.yao@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

On 09/14/17 05:17, Wang, Jian J wrote:
> For the use of arch protocol, there's one thing I mentioned is not
> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it
> cannot change page attributes. That's why I have to turn to cpu arch
> protocol.
Thank you for the explanation.

In that case, we cannot avoid violating the PI spec. I agree we can
break the spec if it happens for security purposes, but in that case, I
believe that hiding the implementation behind a library class is
mandatory. Viewed from the spec side, accessing the CPU Arch protocol is
a hack, and so it should not be spread to the source code of several
driver modules.

Thank you,
Laszlo


>
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
> Sent: Thursday, September 14, 2017 9:17 AM
> To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>
> Thanks for the comments and good advices. Sorry the format issues.
> This is my first patch for this project. Too many details for me to get
> familiar with.
>
> (1) Sure.
> (2) I'll change that.
> (3) I'll use the tool to ensure the patch format.
> (4) I'll remove the ',' in name
> (5) I'll add more description about it.
> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>      instead. The only reason I didn't do it is that I found
>       GetMemorySpaceDescriptor() doesn't return the same information
>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>     arch protocol is a bit safer. Anyway, I'll change it.
> (7) I did put those macros in the install function before. To reduce the
>      number of changed files, I made current changes. You're right it's
>      not worthy.
> (8) Using macro can help the readability, which is more important to me.
>     I know function can do the same. But it looks a bit heavy in this situation.
>     I have to admit replacing  the macros with a library is a very good idea,
>     which brings the same readability. I didn't think of that before. Although
>     Library is still a little bit heavy to me but it's in a different way, I think it
>     worth a trying.
> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
> (10) You're right. Using library can reduce the disturbs to affected drivers
>        by this feature to the minimum.
>
> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Thursday, September 14, 2017 7:35 AM
> To: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> Cc: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>
> Hi,
>
> some of the points I'm going to make have already been pointed out by
> Jordan:
>
> (1) When posting a patch series, please collect the Cc: tags from all of
> the patches, and add them *all* to the cover letter. This way everyone
> will get a personal copy of the general description.
>
>
> (2) The subject line is too long. One possible simplification:
>
> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
>
>
> On 09/13/17 11:25, Wang, Jian J wrote:
>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
>> detection is enabled, page 0 must be enabled temporarily before
>> installing and disabled again afterwards. For Windows 7 boot, BIT7 of
>> PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
>
> (3) Subject line and commit message both should not exceed 74 characters
> line length. (Not sure how many chars PatchCheck.py actually enforces, I
> always stick with 74, following the Linux kernel tradition.)
>
> I rewrapped the commit message here for readability.
>
>
>>
>> Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>> Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>> Cc: Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>> Cc: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>> Cc: Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>
> (4) I think this is also something that Jordan had pointed out a long
> time ago (apologies if I mis-remember):
>
> The strings after the tags should form correct email addresses, and if
> there are various email meta-characters in them, like "." (dot) and ","
> (comma), then they should be quoted, like this:
>
> Cc: "Justen, Jordan L" <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
> Cc: "Kinney, Michael D" <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> Cc: "Wolman, Ayellet" <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
> Suggested-by: "Wolman, Ayellet" <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
> Signed-off-by: "Wang, Jian J" <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>
> If you look at the actual addresses on the emails that have been sent
> out, you can see they are all malformed. For example, I have:
>
> "Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>" for Jordan -- the part before the
> comma was taken to be a separate email address (a malformed one).
>
> At least for my reply, I have fixed up the email addresses.
>
>
> (5) The commit message mentions BIT7 of the new PCD.
>
> First, thanks for checking Windows 7 boot (and I'm happy that I got
> suspicious of the feature with regard to Windows 7). I think BIT7 is a
> good feature.
>
> However, please include the short description of that feature in the
> commit message -- it is one sentence; "Disable NULL pointer detection
> just after EndOfDxe."
>
> (I think BIT7 is a really smart feature, and I like *how* it is used in
> "NULL_DETECTION_ENABLED" below. The check means, "if the protection is
> enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
>
> This doesn't mean that I like the NULL_DETECTION_ENABLED macro itself;
> more on that below.)
>
>
>> ---
>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>
>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
>> index 0dce80e59b..ee0eed7214 100644
>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>    PCI_TYPE00                        Pci;
>>    QEMU_VIDEO_CARD                   *Card;
>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
>
> (6) I believe I mentioned this in the earlier discussion, in some form,
> but now I'll say it again:
>
> A UEFI driver has no business poking at the CPU Arch protocol. The PI
> spec (1.6) states,
>
>   12.3 CPU Architectural Protocol
>   EFI_CPU_ARCH_PROTOCOL
>
>   Summary
>
>   Abstracts the processor services that are required to implement some
>   of the DXE services. This protocol must be produced by a boot service
>   or runtime DXE driver and may only be consumed by the DXE Foundation
>   and DXE drivers that produce architectural protocols.
>
> The DXE core is obviously free to use the CPU Arch protocol, but a UEFI
> driver is forbidden from it, *even if* we say that, in this UEFI driver,
> we are going to use DXE services. (Which come from the PI spec, and not
> the UEFI spec.)
>
> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
>
> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch
> protocol, by the PI spec. It is not easy to see, because the PI spec has
> a formatting error in this area. If you look under
> GetMemorySpaceDescriptor(), there is an error code
>
>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>                          architectural protocol is not available yet.
>
> Obviously this error code belongs to SetMemorySpaceAttributes(), not
> GetMemorySpaceDescriptor().
>
> Anyway, gDS should be used, architectural protocols shouldn't be.
>
>
>>
>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>
>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
>>  #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>> +    //
>> +    // Prepare CPU arch protocol for NULL pointer detection
>> +    //
>> +    Status = gBS->LocateProtocol (
>> +                    &gEfiCpuArchProtocolGuid,
>> +                    NULL,
>> +                    (VOID **) &Cpu
>> +                    );
>> +    ASSERT_EFI_ERROR (Status);
>> +
>> +    DISABLE_NULL_DETECTION(Cpu);
>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>> +    ENABLE_NULL_DETECTION(Cpu);
>
> (7) The NULL detection disabling and enabling should bracket the
> affected code as tightly as possible.
>
> So please move this into InstallVbeShim() accordingly.
>
>
>>    }
>>  #endif
>>
>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
>> index 7fbb25b3ef..bb3bc6eb0f 100644
>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>> @@ -25,6 +25,7 @@
>>  #include <Protocol/PciIo.h>
>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>  #include <Protocol/DevicePath.h>
>> +#include <Protocol/Cpu.h>
>>
>>  #include <Library/DebugLib.h>
>>  #include <Library/UefiDriverEntryPoint.h>
>> @@ -82,6 +83,21 @@ typedef struct {
>>
>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>
>> +//
>> +// VBE code will access memory between 0-4095 which will cause page fault exception
>> +// if NULL pointer detection mechanism is enabled. Following macros can be used to
>> +// disable/enable NULL pointer detection before/after accessing those memory.
>> +//
>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>> +  }
>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>> +  }
>> +
>
> (8) I believe Jordan too commented on these macros elsewhere (under
> patch 1/4).
>
> In my opinion, this functionality should be extracted into a library
> class, with a library instance that is suitable for at least UEFI_DRIVER
> modules. (Maybe even for DXE_DRIVER modules.)
>
> You could add a separate library instance for SMM drivers, if that were
> necessary.
>
>
> (9) Style comment: please put one space character between the function
> designator and the opening parenthesis.
>
>
>>  //
>>  // QEMU Video Private Data Structure
>>  //
>> diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> index 7c7d429bca..5d166eb99c 100644
>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> @@ -72,7 +72,9 @@
>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>> +  gEfiCpuArchProtocolGuid
>>
>>  [Pcd]
>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>> +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
>
> (10) Instead of these, the library class that I described under (8)
> should be added here.
>
> Any further dependencies like PCDs, protocols etc should be inherited by
> the driver through the library instance that the platform DSC file
> resolves the library class to.
>
> Bonus: should you realize that the feature is impossible to implement
> without accessing the CPU Arch protocol directly, you could hide the
> protocol GUID dependency in the library instance INF file, and I'd be
> none the wiser.
>
> ... Well, I could at least pretend that. :)
>
> Thanks,
> Laszlo
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> https://lists.01.org/mailman/listinfo/edk2-devel
>

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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  8:38             ` Yao, Jiewen
@ 2017-09-14  8:46               ` Wang, Jian J
  2017-09-14  8:48                 ` Yao, Jiewen
  2017-09-14  8:54                 ` Laszlo Ersek
  2017-09-14  8:52               ` Laszlo Ersek
  1 sibling, 2 replies; 37+ messages in thread
From: Wang, Jian J @ 2017-09-14  8:46 UTC (permalink / raw)
  To: Yao, Jiewen, Laszlo Ersek
  Cc: Dong, Eric, Justen, Jordan L, edk2-devel@lists.01.org,
	Wolman, Ayellet, Kinney, Michael D, Zeng, Star

It’s an implementation limitation. All page attributes will be filtered out before calling CPU arch protocol to update the attributes (Gcd.c).

From: Yao, Jiewen
Sent: Thursday, September 14, 2017 4:38 PM
To: Laszlo Ersek <lersek@redhat.com>; Wang, Jian J <jian.j.wang@intel.com>
Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet <ayellet.wolman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

HI
I wonder if it is spec limitation or implementation limitation.

If it is implementation limitation, we can enhance the DxeCore to allow it.

Thank you
Yao Jiewen

From: Laszlo Ersek [mailto:lersek@redhat.com]
Sent: Thursday, September 14, 2017 4:30 PM
To: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

On 09/14/17 05:17, Wang, Jian J wrote:
> For the use of arch protocol, there's one thing I mentioned is not
> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it
> cannot change page attributes. That's why I have to turn to cpu arch
> protocol.
Thank you for the explanation.

In that case, we cannot avoid violating the PI spec. I agree we can
break the spec if it happens for security purposes, but in that case, I
believe that hiding the implementation behind a library class is
mandatory. Viewed from the spec side, accessing the CPU Arch protocol is
a hack, and so it should not be spread to the source code of several
driver modules.

Thank you,
Laszlo


>
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
> Sent: Thursday, September 14, 2017 9:17 AM
> To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>
> Thanks for the comments and good advices. Sorry the format issues.
> This is my first patch for this project. Too many details for me to get
> familiar with.
>
> (1) Sure.
> (2) I'll change that.
> (3) I'll use the tool to ensure the patch format.
> (4) I'll remove the ',' in name
> (5) I'll add more description about it.
> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>      instead. The only reason I didn't do it is that I found
>       GetMemorySpaceDescriptor() doesn't return the same information
>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>     arch protocol is a bit safer. Anyway, I'll change it.
> (7) I did put those macros in the install function before. To reduce the
>      number of changed files, I made current changes. You're right it's
>      not worthy.
> (8) Using macro can help the readability, which is more important to me.
>     I know function can do the same. But it looks a bit heavy in this situation.
>     I have to admit replacing  the macros with a library is a very good idea,
>     which brings the same readability. I didn't think of that before. Although
>     Library is still a little bit heavy to me but it's in a different way, I think it
>     worth a trying.
> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
> (10) You're right. Using library can reduce the disturbs to affected drivers
>        by this feature to the minimum.
>
> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Thursday, September 14, 2017 7:35 AM
> To: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> Cc: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>
> Hi,
>
> some of the points I'm going to make have already been pointed out by
> Jordan:
>
> (1) When posting a patch series, please collect the Cc: tags from all of
> the patches, and add them *all* to the cover letter. This way everyone
> will get a personal copy of the general description.
>
>
> (2) The subject line is too long. One possible simplification:
>
> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
>
>
> On 09/13/17 11:25, Wang, Jian J wrote:
>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
>> detection is enabled, page 0 must be enabled temporarily before
>> installing and disabled again afterwards. For Windows 7 boot, BIT7 of
>> PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
>
> (3) Subject line and commit message both should not exceed 74 characters
> line length. (Not sure how many chars PatchCheck.py actually enforces, I
> always stick with 74, following the Linux kernel tradition.)
>
> I rewrapped the commit message here for readability.
>
>
>>
>> Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>> Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>> Cc: Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>> Cc: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>> Cc: Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>
> (4) I think this is also something that Jordan had pointed out a long
> time ago (apologies if I mis-remember):
>
> The strings after the tags should form correct email addresses, and if
> there are various email meta-characters in them, like "." (dot) and ","
> (comma), then they should be quoted, like this:
>
> Cc: "Justen, Jordan L" <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
> Cc: "Kinney, Michael D" <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> Cc: "Wolman, Ayellet" <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
> Suggested-by: "Wolman, Ayellet" <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
> Signed-off-by: "Wang, Jian J" <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>
> If you look at the actual addresses on the emails that have been sent
> out, you can see they are all malformed. For example, I have:
>
> "Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>" for Jordan -- the part before the
> comma was taken to be a separate email address (a malformed one).
>
> At least for my reply, I have fixed up the email addresses.
>
>
> (5) The commit message mentions BIT7 of the new PCD.
>
> First, thanks for checking Windows 7 boot (and I'm happy that I got
> suspicious of the feature with regard to Windows 7). I think BIT7 is a
> good feature.
>
> However, please include the short description of that feature in the
> commit message -- it is one sentence; "Disable NULL pointer detection
> just after EndOfDxe."
>
> (I think BIT7 is a really smart feature, and I like *how* it is used in
> "NULL_DETECTION_ENABLED" below. The check means, "if the protection is
> enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
>
> This doesn't mean that I like the NULL_DETECTION_ENABLED macro itself;
> more on that below.)
>
>
>> ---
>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>
>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
>> index 0dce80e59b..ee0eed7214 100644
>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>    PCI_TYPE00                        Pci;
>>    QEMU_VIDEO_CARD                   *Card;
>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
>
> (6) I believe I mentioned this in the earlier discussion, in some form,
> but now I'll say it again:
>
> A UEFI driver has no business poking at the CPU Arch protocol. The PI
> spec (1.6) states,
>
>   12.3 CPU Architectural Protocol
>   EFI_CPU_ARCH_PROTOCOL
>
>   Summary
>
>   Abstracts the processor services that are required to implement some
>   of the DXE services. This protocol must be produced by a boot service
>   or runtime DXE driver and may only be consumed by the DXE Foundation
>   and DXE drivers that produce architectural protocols.
>
> The DXE core is obviously free to use the CPU Arch protocol, but a UEFI
> driver is forbidden from it, *even if* we say that, in this UEFI driver,
> we are going to use DXE services. (Which come from the PI spec, and not
> the UEFI spec.)
>
> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
>
> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch
> protocol, by the PI spec. It is not easy to see, because the PI spec has
> a formatting error in this area. If you look under
> GetMemorySpaceDescriptor(), there is an error code
>
>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>                          architectural protocol is not available yet.
>
> Obviously this error code belongs to SetMemorySpaceAttributes(), not
> GetMemorySpaceDescriptor().
>
> Anyway, gDS should be used, architectural protocols shouldn't be.
>
>
>>
>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>
>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
>>  #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>> +    //
>> +    // Prepare CPU arch protocol for NULL pointer detection
>> +    //
>> +    Status = gBS->LocateProtocol (
>> +                    &gEfiCpuArchProtocolGuid,
>> +                    NULL,
>> +                    (VOID **) &Cpu
>> +                    );
>> +    ASSERT_EFI_ERROR (Status);
>> +
>> +    DISABLE_NULL_DETECTION(Cpu);
>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>> +    ENABLE_NULL_DETECTION(Cpu);
>
> (7) The NULL detection disabling and enabling should bracket the
> affected code as tightly as possible.
>
> So please move this into InstallVbeShim() accordingly.
>
>
>>    }
>>  #endif
>>
>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
>> index 7fbb25b3ef..bb3bc6eb0f 100644
>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>> @@ -25,6 +25,7 @@
>>  #include <Protocol/PciIo.h>
>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>  #include <Protocol/DevicePath.h>
>> +#include <Protocol/Cpu.h>
>>
>>  #include <Library/DebugLib.h>
>>  #include <Library/UefiDriverEntryPoint.h>
>> @@ -82,6 +83,21 @@ typedef struct {
>>
>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>
>> +//
>> +// VBE code will access memory between 0-4095 which will cause page fault exception
>> +// if NULL pointer detection mechanism is enabled. Following macros can be used to
>> +// disable/enable NULL pointer detection before/after accessing those memory.
>> +//
>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>> +  }
>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>> +  }
>> +
>
> (8) I believe Jordan too commented on these macros elsewhere (under
> patch 1/4).
>
> In my opinion, this functionality should be extracted into a library
> class, with a library instance that is suitable for at least UEFI_DRIVER
> modules. (Maybe even for DXE_DRIVER modules.)
>
> You could add a separate library instance for SMM drivers, if that were
> necessary.
>
>
> (9) Style comment: please put one space character between the function
> designator and the opening parenthesis.
>
>
>>  //
>>  // QEMU Video Private Data Structure
>>  //
>> diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> index 7c7d429bca..5d166eb99c 100644
>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> @@ -72,7 +72,9 @@
>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>> +  gEfiCpuArchProtocolGuid
>>
>>  [Pcd]
>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>> +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
>
> (10) Instead of these, the library class that I described under (8)
> should be added here.
>
> Any further dependencies like PCDs, protocols etc should be inherited by
> the driver through the library instance that the platform DSC file
> resolves the library class to.
>
> Bonus: should you realize that the feature is impossible to implement
> without accessing the CPU Arch protocol directly, you could hide the
> protocol GUID dependency in the library instance INF file, and I'd be
> none the wiser.
>
> ... Well, I could at least pretend that. :)
>
> Thanks,
> Laszlo
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> https://lists.01.org/mailman/listinfo/edk2-devel
>

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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  8:46               ` Wang, Jian J
@ 2017-09-14  8:48                 ` Yao, Jiewen
  2017-09-14  8:54                 ` Laszlo Ersek
  1 sibling, 0 replies; 37+ messages in thread
From: Yao, Jiewen @ 2017-09-14  8:48 UTC (permalink / raw)
  To: Wang, Jian J, Laszlo Ersek
  Cc: Dong, Eric, Justen, Jordan L, edk2-devel@lists.01.org,
	Wolman, Ayellet, Kinney, Michael D, Zeng, Star, Yao, Jiewen

If so, can we enhance the GCD implementation?

I think this is compatible, because we allow more usage.

And most important we still follow spec.

Thank you
Yao Jiewen

From: Wang, Jian J
Sent: Thursday, September 14, 2017 4:46 PM
To: Yao, Jiewen <jiewen.yao@intel.com>; Laszlo Ersek <lersek@redhat.com>
Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet <ayellet.wolman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

It’s an implementation limitation. All page attributes will be filtered out before calling CPU arch protocol to update the attributes (Gcd.c).

From: Yao, Jiewen
Sent: Thursday, September 14, 2017 4:38 PM
To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

HI
I wonder if it is spec limitation or implementation limitation.

If it is implementation limitation, we can enhance the DxeCore to allow it.

Thank you
Yao Jiewen

From: Laszlo Ersek [mailto:lersek@redhat.com]
Sent: Thursday, September 14, 2017 4:30 PM
To: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

On 09/14/17 05:17, Wang, Jian J wrote:
> For the use of arch protocol, there's one thing I mentioned is not
> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it
> cannot change page attributes. That's why I have to turn to cpu arch
> protocol.
Thank you for the explanation.

In that case, we cannot avoid violating the PI spec. I agree we can
break the spec if it happens for security purposes, but in that case, I
believe that hiding the implementation behind a library class is
mandatory. Viewed from the spec side, accessing the CPU Arch protocol is
a hack, and so it should not be spread to the source code of several
driver modules.

Thank you,
Laszlo


>
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
> Sent: Thursday, September 14, 2017 9:17 AM
> To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>
> Thanks for the comments and good advices. Sorry the format issues.
> This is my first patch for this project. Too many details for me to get
> familiar with.
>
> (1) Sure.
> (2) I'll change that.
> (3) I'll use the tool to ensure the patch format.
> (4) I'll remove the ',' in name
> (5) I'll add more description about it.
> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>      instead. The only reason I didn't do it is that I found
>       GetMemorySpaceDescriptor() doesn't return the same information
>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>     arch protocol is a bit safer. Anyway, I'll change it.
> (7) I did put those macros in the install function before. To reduce the
>      number of changed files, I made current changes. You're right it's
>      not worthy.
> (8) Using macro can help the readability, which is more important to me.
>     I know function can do the same. But it looks a bit heavy in this situation.
>     I have to admit replacing  the macros with a library is a very good idea,
>     which brings the same readability. I didn't think of that before. Although
>     Library is still a little bit heavy to me but it's in a different way, I think it
>     worth a trying.
> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
> (10) You're right. Using library can reduce the disturbs to affected drivers
>        by this feature to the minimum.
>
> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Thursday, September 14, 2017 7:35 AM
> To: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> Cc: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>
> Hi,
>
> some of the points I'm going to make have already been pointed out by
> Jordan:
>
> (1) When posting a patch series, please collect the Cc: tags from all of
> the patches, and add them *all* to the cover letter. This way everyone
> will get a personal copy of the general description.
>
>
> (2) The subject line is too long. One possible simplification:
>
> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
>
>
> On 09/13/17 11:25, Wang, Jian J wrote:
>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
>> detection is enabled, page 0 must be enabled temporarily before
>> installing and disabled again afterwards. For Windows 7 boot, BIT7 of
>> PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
>
> (3) Subject line and commit message both should not exceed 74 characters
> line length. (Not sure how many chars PatchCheck.py actually enforces, I
> always stick with 74, following the Linux kernel tradition.)
>
> I rewrapped the commit message here for readability.
>
>
>>
>> Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>> Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>> Cc: Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>> Cc: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>> Cc: Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>
> (4) I think this is also something that Jordan had pointed out a long
> time ago (apologies if I mis-remember):
>
> The strings after the tags should form correct email addresses, and if
> there are various email meta-characters in them, like "." (dot) and ","
> (comma), then they should be quoted, like this:
>
> Cc: "Justen, Jordan L" <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
> Cc: "Kinney, Michael D" <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> Cc: "Wolman, Ayellet" <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
> Suggested-by: "Wolman, Ayellet" <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
> Signed-off-by: "Wang, Jian J" <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>
> If you look at the actual addresses on the emails that have been sent
> out, you can see they are all malformed. For example, I have:
>
> "Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>" for Jordan -- the part before the
> comma was taken to be a separate email address (a malformed one).
>
> At least for my reply, I have fixed up the email addresses.
>
>
> (5) The commit message mentions BIT7 of the new PCD.
>
> First, thanks for checking Windows 7 boot (and I'm happy that I got
> suspicious of the feature with regard to Windows 7). I think BIT7 is a
> good feature.
>
> However, please include the short description of that feature in the
> commit message -- it is one sentence; "Disable NULL pointer detection
> just after EndOfDxe."
>
> (I think BIT7 is a really smart feature, and I like *how* it is used in
> "NULL_DETECTION_ENABLED" below. The check means, "if the protection is
> enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
>
> This doesn't mean that I like the NULL_DETECTION_ENABLED macro itself;
> more on that below.)
>
>
>> ---
>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>
>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
>> index 0dce80e59b..ee0eed7214 100644
>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>    PCI_TYPE00                        Pci;
>>    QEMU_VIDEO_CARD                   *Card;
>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
>
> (6) I believe I mentioned this in the earlier discussion, in some form,
> but now I'll say it again:
>
> A UEFI driver has no business poking at the CPU Arch protocol. The PI
> spec (1.6) states,
>
>   12.3 CPU Architectural Protocol
>   EFI_CPU_ARCH_PROTOCOL
>
>   Summary
>
>   Abstracts the processor services that are required to implement some
>   of the DXE services. This protocol must be produced by a boot service
>   or runtime DXE driver and may only be consumed by the DXE Foundation
>   and DXE drivers that produce architectural protocols.
>
> The DXE core is obviously free to use the CPU Arch protocol, but a UEFI
> driver is forbidden from it, *even if* we say that, in this UEFI driver,
> we are going to use DXE services. (Which come from the PI spec, and not
> the UEFI spec.)
>
> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
>
> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch
> protocol, by the PI spec. It is not easy to see, because the PI spec has
> a formatting error in this area. If you look under
> GetMemorySpaceDescriptor(), there is an error code
>
>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>                          architectural protocol is not available yet.
>
> Obviously this error code belongs to SetMemorySpaceAttributes(), not
> GetMemorySpaceDescriptor().
>
> Anyway, gDS should be used, architectural protocols shouldn't be.
>
>
>>
>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>
>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
>>  #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>> +    //
>> +    // Prepare CPU arch protocol for NULL pointer detection
>> +    //
>> +    Status = gBS->LocateProtocol (
>> +                    &gEfiCpuArchProtocolGuid,
>> +                    NULL,
>> +                    (VOID **) &Cpu
>> +                    );
>> +    ASSERT_EFI_ERROR (Status);
>> +
>> +    DISABLE_NULL_DETECTION(Cpu);
>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>> +    ENABLE_NULL_DETECTION(Cpu);
>
> (7) The NULL detection disabling and enabling should bracket the
> affected code as tightly as possible.
>
> So please move this into InstallVbeShim() accordingly.
>
>
>>    }
>>  #endif
>>
>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
>> index 7fbb25b3ef..bb3bc6eb0f 100644
>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>> @@ -25,6 +25,7 @@
>>  #include <Protocol/PciIo.h>
>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>  #include <Protocol/DevicePath.h>
>> +#include <Protocol/Cpu.h>
>>
>>  #include <Library/DebugLib.h>
>>  #include <Library/UefiDriverEntryPoint.h>
>> @@ -82,6 +83,21 @@ typedef struct {
>>
>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>
>> +//
>> +// VBE code will access memory between 0-4095 which will cause page fault exception
>> +// if NULL pointer detection mechanism is enabled. Following macros can be used to
>> +// disable/enable NULL pointer detection before/after accessing those memory.
>> +//
>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>> +  }
>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>> +  }
>> +
>
> (8) I believe Jordan too commented on these macros elsewhere (under
> patch 1/4).
>
> In my opinion, this functionality should be extracted into a library
> class, with a library instance that is suitable for at least UEFI_DRIVER
> modules. (Maybe even for DXE_DRIVER modules.)
>
> You could add a separate library instance for SMM drivers, if that were
> necessary.
>
>
> (9) Style comment: please put one space character between the function
> designator and the opening parenthesis.
>
>
>>  //
>>  // QEMU Video Private Data Structure
>>  //
>> diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> index 7c7d429bca..5d166eb99c 100644
>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>> @@ -72,7 +72,9 @@
>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>> +  gEfiCpuArchProtocolGuid
>>
>>  [Pcd]
>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>> +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
>
> (10) Instead of these, the library class that I described under (8)
> should be added here.
>
> Any further dependencies like PCDs, protocols etc should be inherited by
> the driver through the library instance that the platform DSC file
> resolves the library class to.
>
> Bonus: should you realize that the feature is impossible to implement
> without accessing the CPU Arch protocol directly, you could hide the
> protocol GUID dependency in the library instance INF file, and I'd be
> none the wiser.
>
> ... Well, I could at least pretend that. :)
>
> Thanks,
> Laszlo
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> https://lists.01.org/mailman/listinfo/edk2-devel
>

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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  8:38             ` Yao, Jiewen
  2017-09-14  8:46               ` Wang, Jian J
@ 2017-09-14  8:52               ` Laszlo Ersek
  1 sibling, 0 replies; 37+ messages in thread
From: Laszlo Ersek @ 2017-09-14  8:52 UTC (permalink / raw)
  To: Yao, Jiewen, Wang, Jian J
  Cc: Dong, Eric, Justen, Jordan L, edk2-devel@lists.01.org,
	Wolman, Ayellet, Kinney, Michael D, Zeng, Star

On 09/14/17 10:38, Yao, Jiewen wrote:
> HI
> I wonder if it is spec limitation or implementation limitation.
> 
> If it is implementation limitation, we can enhance the DxeCore to allow it.

My opinion is that the spec limits the use of the CPU Arch protocol to
said core modules because those modules need to "own" the CPU Arch
protocol. If random code messes with the CPU Arch protocol, then the
system's actual state can diverge from what the DXE core (for example)
thinks about the system, and that could be bad.

If SetMemorySpaceAttributes() doesn't work due to an implementation
limitation, as you say, I agree the implementation should be fixed.

However, if the SetMemorySpaceAttributes() spec itself makes the service
unsuitable for this, even preventing future PI releases from extending
the service backwards-compatibly -- and I can't tell if that's the case
--, then the "proper way" to enhance the spec would be to introduce a
new DXE service. I believe.

Thanks
Laszlo

> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Thursday, September 14, 2017 4:30 PM
> To: Wang, Jian J <jian.j.wang@intel.com>
> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Yao, Jiewen <jiewen.yao@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> On 09/14/17 05:17, Wang, Jian J wrote:
>> For the use of arch protocol, there's one thing I mentioned is not
>> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it
>> cannot change page attributes. That's why I have to turn to cpu arch
>> protocol.
> Thank you for the explanation.
> 
> In that case, we cannot avoid violating the PI spec. I agree we can
> break the spec if it happens for security purposes, but in that case, I
> believe that hiding the implementation behind a library class is
> mandatory. Viewed from the spec side, accessing the CPU Arch protocol is
> a hack, and so it should not be spread to the source code of several
> driver modules.
> 
> Thank you,
> Laszlo
> 
> 
>>
>> -----Original Message-----
>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
>> Sent: Thursday, September 14, 2017 9:17 AM
>> To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> Thanks for the comments and good advices. Sorry the format issues.
>> This is my first patch for this project. Too many details for me to get
>> familiar with.
>>
>> (1) Sure.
>> (2) I'll change that.
>> (3) I'll use the tool to ensure the patch format.
>> (4) I'll remove the ',' in name
>> (5) I'll add more description about it.
>> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>>      instead. The only reason I didn't do it is that I found
>>       GetMemorySpaceDescriptor() doesn't return the same information
>>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>>     arch protocol is a bit safer. Anyway, I'll change it.
>> (7) I did put those macros in the install function before. To reduce the
>>      number of changed files, I made current changes. You're right it's
>>      not worthy.
>> (8) Using macro can help the readability, which is more important to me.
>>     I know function can do the same. But it looks a bit heavy in this situation.
>>     I have to admit replacing  the macros with a library is a very good idea,
>>     which brings the same readability. I didn't think of that before. Although
>>     Library is still a little bit heavy to me but it's in a different way, I think it
>>     worth a trying.
>> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
>> (10) You're right. Using library can reduce the disturbs to affected drivers
>>        by this feature to the minimum.
>>
>> -----Original Message-----
>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>> Sent: Thursday, September 14, 2017 7:35 AM
>> To: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>> Cc: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> Hi,
>>
>> some of the points I'm going to make have already been pointed out by
>> Jordan:
>>
>> (1) When posting a patch series, please collect the Cc: tags from all of
>> the patches, and add them *all* to the cover letter. This way everyone
>> will get a personal copy of the general description.
>>
>>
>> (2) The subject line is too long. One possible simplification:
>>
>> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
>>
>>
>> On 09/13/17 11:25, Wang, Jian J wrote:
>>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
>>> detection is enabled, page 0 must be enabled temporarily before
>>> installing and disabled again afterwards. For Windows 7 boot, BIT7 of
>>> PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
>>
>> (3) Subject line and commit message both should not exceed 74 characters
>> line length. (Not sure how many chars PatchCheck.py actually enforces, I
>> always stick with 74, following the Linux kernel tradition.)
>>
>> I rewrapped the commit message here for readability.
>>
>>
>>>
>>> Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>>> Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>>> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>> Cc: Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>> Cc: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>> Cc: Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Contributed-under: TianoCore Contribution Agreement 1.1
>>> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>
>> (4) I think this is also something that Jordan had pointed out a long
>> time ago (apologies if I mis-remember):
>>
>> The strings after the tags should form correct email addresses, and if
>> there are various email meta-characters in them, like "." (dot) and ","
>> (comma), then they should be quoted, like this:
>>
>> Cc: "Justen, Jordan L" <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>> Cc: "Kinney, Michael D" <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>> Cc: "Wolman, Ayellet" <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Suggested-by: "Wolman, Ayellet" <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Signed-off-by: "Wang, Jian J" <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>
>> If you look at the actual addresses on the emails that have been sent
>> out, you can see they are all malformed. For example, I have:
>>
>> "Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>" for Jordan -- the part before the
>> comma was taken to be a separate email address (a malformed one).
>>
>> At least for my reply, I have fixed up the email addresses.
>>
>>
>> (5) The commit message mentions BIT7 of the new PCD.
>>
>> First, thanks for checking Windows 7 boot (and I'm happy that I got
>> suspicious of the feature with regard to Windows 7). I think BIT7 is a
>> good feature.
>>
>> However, please include the short description of that feature in the
>> commit message -- it is one sentence; "Disable NULL pointer detection
>> just after EndOfDxe."
>>
>> (I think BIT7 is a really smart feature, and I like *how* it is used in
>> "NULL_DETECTION_ENABLED" below. The check means, "if the protection is
>> enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
>>
>> This doesn't mean that I like the NULL_DETECTION_ENABLED macro itself;
>> more on that below.)
>>
>>
>>> ---
>>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
>>> index 0dce80e59b..ee0eed7214 100644
>>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>>    PCI_TYPE00                        Pci;
>>>    QEMU_VIDEO_CARD                   *Card;
>>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
>>
>> (6) I believe I mentioned this in the earlier discussion, in some form,
>> but now I'll say it again:
>>
>> A UEFI driver has no business poking at the CPU Arch protocol. The PI
>> spec (1.6) states,
>>
>>   12.3 CPU Architectural Protocol
>>   EFI_CPU_ARCH_PROTOCOL
>>
>>   Summary
>>
>>   Abstracts the processor services that are required to implement some
>>   of the DXE services. This protocol must be produced by a boot service
>>   or runtime DXE driver and may only be consumed by the DXE Foundation
>>   and DXE drivers that produce architectural protocols.
>>
>> The DXE core is obviously free to use the CPU Arch protocol, but a UEFI
>> driver is forbidden from it, *even if* we say that, in this UEFI driver,
>> we are going to use DXE services. (Which come from the PI spec, and not
>> the UEFI spec.)
>>
>> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
>>
>> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch
>> protocol, by the PI spec. It is not easy to see, because the PI spec has
>> a formatting error in this area. If you look under
>> GetMemorySpaceDescriptor(), there is an error code
>>
>>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>>                          architectural protocol is not available yet.
>>
>> Obviously this error code belongs to SetMemorySpaceAttributes(), not
>> GetMemorySpaceDescriptor().
>>
>> Anyway, gDS should be used, architectural protocols shouldn't be.
>>
>>
>>>
>>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>>
>>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
>>>  #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
>>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>> +    //
>>> +    // Prepare CPU arch protocol for NULL pointer detection
>>> +    //
>>> +    Status = gBS->LocateProtocol (
>>> +                    &gEfiCpuArchProtocolGuid,
>>> +                    NULL,
>>> +                    (VOID **) &Cpu
>>> +                    );
>>> +    ASSERT_EFI_ERROR (Status);
>>> +
>>> +    DISABLE_NULL_DETECTION(Cpu);
>>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>> +    ENABLE_NULL_DETECTION(Cpu);
>>
>> (7) The NULL detection disabling and enabling should bracket the
>> affected code as tightly as possible.
>>
>> So please move this into InstallVbeShim() accordingly.
>>
>>
>>>    }
>>>  #endif
>>>
>>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
>>> index 7fbb25b3ef..bb3bc6eb0f 100644
>>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>>> @@ -25,6 +25,7 @@
>>>  #include <Protocol/PciIo.h>
>>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>>  #include <Protocol/DevicePath.h>
>>> +#include <Protocol/Cpu.h>
>>>
>>>  #include <Library/DebugLib.h>
>>>  #include <Library/UefiDriverEntryPoint.h>
>>> @@ -82,6 +83,21 @@ typedef struct {
>>>
>>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>>
>>> +//
>>> +// VBE code will access memory between 0-4095 which will cause page fault exception
>>> +// if NULL pointer detection mechanism is enabled. Following macros can be used to
>>> +// disable/enable NULL pointer detection before/after accessing those memory.
>>> +//
>>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>>> +  }
>>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>>> +  }
>>> +
>>
>> (8) I believe Jordan too commented on these macros elsewhere (under
>> patch 1/4).
>>
>> In my opinion, this functionality should be extracted into a library
>> class, with a library instance that is suitable for at least UEFI_DRIVER
>> modules. (Maybe even for DXE_DRIVER modules.)
>>
>> You could add a separate library instance for SMM drivers, if that were
>> necessary.
>>
>>
>> (9) Style comment: please put one space character between the function
>> designator and the opening parenthesis.
>>
>>
>>>  //
>>>  // QEMU Video Private Data Structure
>>>  //
>>> diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>> index 7c7d429bca..5d166eb99c 100644
>>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>> @@ -72,7 +72,9 @@
>>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>>> +  gEfiCpuArchProtocolGuid
>>>
>>>  [Pcd]
>>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>>> +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
>>
>> (10) Instead of these, the library class that I described under (8)
>> should be added here.
>>
>> Any further dependencies like PCDs, protocols etc should be inherited by
>> the driver through the library instance that the platform DSC file
>> resolves the library class to.
>>
>> Bonus: should you realize that the feature is impossible to implement
>> without accessing the CPU Arch protocol directly, you could hide the
>> protocol GUID dependency in the library instance INF file, and I'd be
>> none the wiser.
>>
>> ... Well, I could at least pretend that. :)
>>
>> Thanks,
>> Laszlo
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>> https://lists.01.org/mailman/listinfo/edk2-devel
>>



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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  8:46               ` Wang, Jian J
  2017-09-14  8:48                 ` Yao, Jiewen
@ 2017-09-14  8:54                 ` Laszlo Ersek
  2017-09-14  9:39                   ` Zeng, Star
  1 sibling, 1 reply; 37+ messages in thread
From: Laszlo Ersek @ 2017-09-14  8:54 UTC (permalink / raw)
  To: Wang, Jian J, Yao, Jiewen
  Cc: Dong, Eric, Justen, Jordan L, edk2-devel@lists.01.org,
	Wolman, Ayellet, Kinney, Michael D, Zeng, Star

On 09/14/17 10:46, Wang, Jian J wrote:
> It’s an implementation limitation. All page attributes will be filtered out before calling CPU arch protocol to update the attributes (Gcd.c).

That cannot be a random occurrence; I'm sure there was some specific
intent behind filtering out the page attributes.

Does "git blame" provide a reason, from the message of the commit that
added the filtering?

Thanks,
Laszlo

> From: Yao, Jiewen
> Sent: Thursday, September 14, 2017 4:38 PM
> To: Laszlo Ersek <lersek@redhat.com>; Wang, Jian J <jian.j.wang@intel.com>
> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet <ayellet.wolman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> HI
> I wonder if it is spec limitation or implementation limitation.
> 
> If it is implementation limitation, we can enhance the DxeCore to allow it.
> 
> Thank you
> Yao Jiewen
> 
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Thursday, September 14, 2017 4:30 PM
> To: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> On 09/14/17 05:17, Wang, Jian J wrote:
>> For the use of arch protocol, there's one thing I mentioned is not
>> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it
>> cannot change page attributes. That's why I have to turn to cpu arch
>> protocol.
> Thank you for the explanation.
> 
> In that case, we cannot avoid violating the PI spec. I agree we can
> break the spec if it happens for security purposes, but in that case, I
> believe that hiding the implementation behind a library class is
> mandatory. Viewed from the spec side, accessing the CPU Arch protocol is
> a hack, and so it should not be spread to the source code of several
> driver modules.
> 
> Thank you,
> Laszlo
> 
> 
>>
>> -----Original Message-----
>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
>> Sent: Thursday, September 14, 2017 9:17 AM
>> To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> Thanks for the comments and good advices. Sorry the format issues.
>> This is my first patch for this project. Too many details for me to get
>> familiar with.
>>
>> (1) Sure.
>> (2) I'll change that.
>> (3) I'll use the tool to ensure the patch format.
>> (4) I'll remove the ',' in name
>> (5) I'll add more description about it.
>> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>>      instead. The only reason I didn't do it is that I found
>>       GetMemorySpaceDescriptor() doesn't return the same information
>>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>>     arch protocol is a bit safer. Anyway, I'll change it.
>> (7) I did put those macros in the install function before. To reduce the
>>      number of changed files, I made current changes. You're right it's
>>      not worthy.
>> (8) Using macro can help the readability, which is more important to me.
>>     I know function can do the same. But it looks a bit heavy in this situation.
>>     I have to admit replacing  the macros with a library is a very good idea,
>>     which brings the same readability. I didn't think of that before. Although
>>     Library is still a little bit heavy to me but it's in a different way, I think it
>>     worth a trying.
>> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
>> (10) You're right. Using library can reduce the disturbs to affected drivers
>>        by this feature to the minimum.
>>
>> -----Original Message-----
>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>> Sent: Thursday, September 14, 2017 7:35 AM
>> To: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>> Cc: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> Hi,
>>
>> some of the points I'm going to make have already been pointed out by
>> Jordan:
>>
>> (1) When posting a patch series, please collect the Cc: tags from all of
>> the patches, and add them *all* to the cover letter. This way everyone
>> will get a personal copy of the general description.
>>
>>
>> (2) The subject line is too long. One possible simplification:
>>
>> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
>>
>>
>> On 09/13/17 11:25, Wang, Jian J wrote:
>>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL pointer
>>> detection is enabled, page 0 must be enabled temporarily before
>>> installing and disabled again afterwards. For Windows 7 boot, BIT7 of
>>> PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
>>
>> (3) Subject line and commit message both should not exceed 74 characters
>> line length. (Not sure how many chars PatchCheck.py actually enforces, I
>> always stick with 74, following the Linux kernel tradition.)
>>
>> I rewrapped the commit message here for readability.
>>
>>
>>>
>>> Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>>> Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>>> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>> Cc: Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>> Cc: Kinney, Michael D <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>> Cc: Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Suggested-by: Wolman, Ayellet <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Contributed-under: TianoCore Contribution Agreement 1.1
>>> Signed-off-by: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>
>> (4) I think this is also something that Jordan had pointed out a long
>> time ago (apologies if I mis-remember):
>>
>> The strings after the tags should form correct email addresses, and if
>> there are various email meta-characters in them, like "." (dot) and ","
>> (comma), then they should be quoted, like this:
>>
>> Cc: "Justen, Jordan L" <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>> Cc: "Kinney, Michael D" <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>> Cc: "Wolman, Ayellet" <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Suggested-by: "Wolman, Ayellet" <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Signed-off-by: "Wang, Jian J" <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>
>> If you look at the actual addresses on the emails that have been sent
>> out, you can see they are all malformed. For example, I have:
>>
>> "Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>" for Jordan -- the part before the
>> comma was taken to be a separate email address (a malformed one).
>>
>> At least for my reply, I have fixed up the email addresses.
>>
>>
>> (5) The commit message mentions BIT7 of the new PCD.
>>
>> First, thanks for checking Windows 7 boot (and I'm happy that I got
>> suspicious of the feature with regard to Windows 7). I think BIT7 is a
>> good feature.
>>
>> However, please include the short description of that feature in the
>> commit message -- it is one sentence; "Disable NULL pointer detection
>> just after EndOfDxe."
>>
>> (I think BIT7 is a really smart feature, and I like *how* it is used in
>> "NULL_DETECTION_ENABLED" below. The check means, "if the protection is
>> enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
>>
>> This doesn't mean that I like the NULL_DETECTION_ENABLED macro itself;
>> more on that below.)
>>
>>
>>> ---
>>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
>>> index 0dce80e59b..ee0eed7214 100644
>>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>>    PCI_TYPE00                        Pci;
>>>    QEMU_VIDEO_CARD                   *Card;
>>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
>>
>> (6) I believe I mentioned this in the earlier discussion, in some form,
>> but now I'll say it again:
>>
>> A UEFI driver has no business poking at the CPU Arch protocol. The PI
>> spec (1.6) states,
>>
>>   12.3 CPU Architectural Protocol
>>   EFI_CPU_ARCH_PROTOCOL
>>
>>   Summary
>>
>>   Abstracts the processor services that are required to implement some
>>   of the DXE services. This protocol must be produced by a boot service
>>   or runtime DXE driver and may only be consumed by the DXE Foundation
>>   and DXE drivers that produce architectural protocols.
>>
>> The DXE core is obviously free to use the CPU Arch protocol, but a UEFI
>> driver is forbidden from it, *even if* we say that, in this UEFI driver,
>> we are going to use DXE services. (Which come from the PI spec, and not
>> the UEFI spec.)
>>
>> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
>>
>> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch
>> protocol, by the PI spec. It is not easy to see, because the PI spec has
>> a formatting error in this area. If you look under
>> GetMemorySpaceDescriptor(), there is an error code
>>
>>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>>                          architectural protocol is not available yet.
>>
>> Obviously this error code belongs to SetMemorySpaceAttributes(), not
>> GetMemorySpaceDescriptor().
>>
>> Anyway, gDS should be used, architectural protocols shouldn't be.
>>
>>
>>>
>>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>>
>>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (
>>>  #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
>>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>> +    //
>>> +    // Prepare CPU arch protocol for NULL pointer detection
>>> +    //
>>> +    Status = gBS->LocateProtocol (
>>> +                    &gEfiCpuArchProtocolGuid,
>>> +                    NULL,
>>> +                    (VOID **) &Cpu
>>> +                    );
>>> +    ASSERT_EFI_ERROR (Status);
>>> +
>>> +    DISABLE_NULL_DETECTION(Cpu);
>>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>> +    ENABLE_NULL_DETECTION(Cpu);
>>
>> (7) The NULL detection disabling and enabling should bracket the
>> affected code as tightly as possible.
>>
>> So please move this into InstallVbeShim() accordingly.
>>
>>
>>>    }
>>>  #endif
>>>
>>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
>>> index 7fbb25b3ef..bb3bc6eb0f 100644
>>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>>> @@ -25,6 +25,7 @@
>>>  #include <Protocol/PciIo.h>
>>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>>  #include <Protocol/DevicePath.h>
>>> +#include <Protocol/Cpu.h>
>>>
>>>  #include <Library/DebugLib.h>
>>>  #include <Library/UefiDriverEntryPoint.h>
>>> @@ -82,6 +83,21 @@ typedef struct {
>>>
>>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>>
>>> +//
>>> +// VBE code will access memory between 0-4095 which will cause page fault exception
>>> +// if NULL pointer detection mechanism is enabled. Following macros can be used to
>>> +// disable/enable NULL pointer detection before/after accessing those memory.
>>> +//
>>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>>> +  }
>>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>>> +  }
>>> +
>>
>> (8) I believe Jordan too commented on these macros elsewhere (under
>> patch 1/4).
>>
>> In my opinion, this functionality should be extracted into a library
>> class, with a library instance that is suitable for at least UEFI_DRIVER
>> modules. (Maybe even for DXE_DRIVER modules.)
>>
>> You could add a separate library instance for SMM drivers, if that were
>> necessary.
>>
>>
>> (9) Style comment: please put one space character between the function
>> designator and the opening parenthesis.
>>
>>
>>>  //
>>>  // QEMU Video Private Data Structure
>>>  //
>>> diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>> index 7c7d429bca..5d166eb99c 100644
>>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>> @@ -72,7 +72,9 @@
>>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>>> +  gEfiCpuArchProtocolGuid
>>>
>>>  [Pcd]
>>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>>> +  gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
>>
>> (10) Instead of these, the library class that I described under (8)
>> should be added here.
>>
>> Any further dependencies like PCDs, protocols etc should be inherited by
>> the driver through the library instance that the platform DSC file
>> resolves the library class to.
>>
>> Bonus: should you realize that the feature is impossible to implement
>> without accessing the CPU Arch protocol directly, you could hide the
>> protocol GUID dependency in the library instance INF file, and I'd be
>> none the wiser.
>>
>> ... Well, I could at least pretend that. :)
>>
>> Thanks,
>> Laszlo
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>> https://lists.01.org/mailman/listinfo/edk2-devel
>>



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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  8:54                 ` Laszlo Ersek
@ 2017-09-14  9:39                   ` Zeng, Star
  2017-09-14  9:55                     ` Laszlo Ersek
  0 siblings, 1 reply; 37+ messages in thread
From: Zeng, Star @ 2017-09-14  9:39 UTC (permalink / raw)
  To: Laszlo Ersek, Wang, Jian J, Yao, Jiewen
  Cc: Dong, Eric, Justen, Jordan L, edk2-devel@lists.01.org,
	Wolman, Ayellet, Kinney, Michael D, Zeng, Star

There is a realistic problem I just found and want to share.

GCD database is built based on resource hob reported from PEI, and GCD checks the input Attributes against Capabilities when setting Attributes, but we (I just searched the whole codebase) can see there is no code reporting resource hob with EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE, EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE or EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE set.



Thanks,
Star
-----Original Message-----
From: Laszlo Ersek [mailto:lersek@redhat.com] 
Sent: Thursday, September 14, 2017 4:54 PM
To: Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet <ayellet.wolman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

On 09/14/17 10:46, Wang, Jian J wrote:
> It’s an implementation limitation. All page attributes will be filtered out before calling CPU arch protocol to update the attributes (Gcd.c).

That cannot be a random occurrence; I'm sure there was some specific intent behind filtering out the page attributes.

Does "git blame" provide a reason, from the message of the commit that added the filtering?

Thanks,
Laszlo

> From: Yao, Jiewen
> Sent: Thursday, September 14, 2017 4:38 PM
> To: Laszlo Ersek <lersek@redhat.com>; Wang, Jian J 
> <jian.j.wang@intel.com>
> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L 
> <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet 
> <ayellet.wolman@intel.com>; Kinney, Michael D 
> <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> HI
> I wonder if it is spec limitation or implementation limitation.
> 
> If it is implementation limitation, we can enhance the DxeCore to allow it.
> 
> Thank you
> Yao Jiewen
> 
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Thursday, September 14, 2017 4:30 PM
> To: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; 
> Justen, Jordan L 
> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; 
> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
> Michael D 
> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Zeng, 
> Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> On 09/14/17 05:17, Wang, Jian J wrote:
>> For the use of arch protocol, there's one thing I mentioned is not 
>> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it 
>> cannot change page attributes. That's why I have to turn to cpu arch 
>> protocol.
> Thank you for the explanation.
> 
> In that case, we cannot avoid violating the PI spec. I agree we can 
> break the spec if it happens for security purposes, but in that case, 
> I believe that hiding the implementation behind a library class is 
> mandatory. Viewed from the spec side, accessing the CPU Arch protocol 
> is a hack, and so it should not be spread to the source code of 
> several driver modules.
> 
> Thank you,
> Laszlo
> 
> 
>>
>> -----Original Message-----
>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf 
>> Of Wang, Jian J
>> Sent: Thursday, September 14, 2017 9:17 AM
>> To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; 
>> Justen, Jordan L 
>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; 
>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
>> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
>> Michael D 
>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; 
>> Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> Thanks for the comments and good advices. Sorry the format issues.
>> This is my first patch for this project. Too many details for me to 
>> get familiar with.
>>
>> (1) Sure.
>> (2) I'll change that.
>> (3) I'll use the tool to ensure the patch format.
>> (4) I'll remove the ',' in name
>> (5) I'll add more description about it.
>> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>>      instead. The only reason I didn't do it is that I found
>>       GetMemorySpaceDescriptor() doesn't return the same information
>>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>>     arch protocol is a bit safer. Anyway, I'll change it.
>> (7) I did put those macros in the install function before. To reduce the
>>      number of changed files, I made current changes. You're right it's
>>      not worthy.
>> (8) Using macro can help the readability, which is more important to me.
>>     I know function can do the same. But it looks a bit heavy in this situation.
>>     I have to admit replacing  the macros with a library is a very good idea,
>>     which brings the same readability. I didn't think of that before. Although
>>     Library is still a little bit heavy to me but it's in a different way, I think it
>>     worth a trying.
>> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
>> (10) You're right. Using library can reduce the disturbs to affected drivers
>>        by this feature to the minimum.
>>
>> -----Original Message-----
>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>> Sent: Thursday, September 14, 2017 7:35 AM
>> To: Wang, Jian J 
>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>> Cc: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Justen, 
>> Jordan L 
>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Dong, 
>> Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Kinney, 
>> Michael D 
>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; 
>> Wolman, Ayellet 
>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Yao, 
>> Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zeng, 
>> Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> Hi,
>>
>> some of the points I'm going to make have already been pointed out by
>> Jordan:
>>
>> (1) When posting a patch series, please collect the Cc: tags from all 
>> of the patches, and add them *all* to the cover letter. This way 
>> everyone will get a personal copy of the general description.
>>
>>
>> (2) The subject line is too long. One possible simplification:
>>
>> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
>>
>>
>> On 09/13/17 11:25, Wang, Jian J wrote:
>>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL 
>>> pointer detection is enabled, page 0 must be enabled temporarily 
>>> before installing and disabled again afterwards. For Windows 7 boot, 
>>> BIT7 of PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
>>
>> (3) Subject line and commit message both should not exceed 74 
>> characters line length. (Not sure how many chars PatchCheck.py 
>> actually enforces, I always stick with 74, following the Linux kernel 
>> tradition.)
>>
>> I rewrapped the commit message here for readability.
>>
>>
>>>
>>> Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>>> Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>>> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>> Cc: Justen, Jordan L 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>> Cc: Kinney, Michael D 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>> Cc: Wolman, Ayellet 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Suggested-by: Wolman, Ayellet 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Contributed-under: TianoCore Contribution Agreement 1.1
>>> Signed-off-by: Wang, Jian J 
>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>
>> (4) I think this is also something that Jordan had pointed out a long 
>> time ago (apologies if I mis-remember):
>>
>> The strings after the tags should form correct email addresses, and 
>> if there are various email meta-characters in them, like "." (dot) and ","
>> (comma), then they should be quoted, like this:
>>
>> Cc: "Justen, Jordan L" 
>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>> Cc: "Kinney, Michael D" 
>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>> Cc: "Wolman, Ayellet" 
>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Suggested-by: "Wolman, Ayellet" 
>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>> Signed-off-by: "Wang, Jian J" 
>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>
>> If you look at the actual addresses on the emails that have been sent 
>> out, you can see they are all malformed. For example, I have:
>>
>> "Jordan L 
>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>" for Jordan -- the part before the comma was taken to be a separate email address (a malformed one).
>>
>> At least for my reply, I have fixed up the email addresses.
>>
>>
>> (5) The commit message mentions BIT7 of the new PCD.
>>
>> First, thanks for checking Windows 7 boot (and I'm happy that I got 
>> suspicious of the feature with regard to Windows 7). I think BIT7 is 
>> a good feature.
>>
>> However, please include the short description of that feature in the 
>> commit message -- it is one sentence; "Disable NULL pointer detection 
>> just after EndOfDxe."
>>
>> (I think BIT7 is a really smart feature, and I like *how* it is used 
>> in "NULL_DETECTION_ENABLED" below. The check means, "if the 
>> protection is enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
>>
>> This doesn't mean that I like the NULL_DETECTION_ENABLED macro 
>> itself; more on that below.)
>>
>>
>>> ---
>>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c 
>>> b/OvmfPkg/QemuVideoDxe/Driver.c index 0dce80e59b..ee0eed7214 100644
>>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>>    PCI_TYPE00                        Pci;
>>>    QEMU_VIDEO_CARD                   *Card;
>>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
>>
>> (6) I believe I mentioned this in the earlier discussion, in some 
>> form, but now I'll say it again:
>>
>> A UEFI driver has no business poking at the CPU Arch protocol. The PI 
>> spec (1.6) states,
>>
>>   12.3 CPU Architectural Protocol
>>   EFI_CPU_ARCH_PROTOCOL
>>
>>   Summary
>>
>>   Abstracts the processor services that are required to implement some
>>   of the DXE services. This protocol must be produced by a boot service
>>   or runtime DXE driver and may only be consumed by the DXE Foundation
>>   and DXE drivers that produce architectural protocols.
>>
>> The DXE core is obviously free to use the CPU Arch protocol, but a 
>> UEFI driver is forbidden from it, *even if* we say that, in this UEFI 
>> driver, we are going to use DXE services. (Which come from the PI 
>> spec, and not the UEFI spec.)
>>
>> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
>>
>> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch 
>> protocol, by the PI spec. It is not easy to see, because the PI spec 
>> has a formatting error in this area. If you look under 
>> GetMemorySpaceDescriptor(), there is an error code
>>
>>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>>                          architectural protocol is not available yet.
>>
>> Obviously this error code belongs to SetMemorySpaceAttributes(), not 
>> GetMemorySpaceDescriptor().
>>
>> Anyway, gDS should be used, architectural protocols shouldn't be.
>>
>>
>>>
>>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>>
>>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (  #if defined 
>>> MDE_CPU_IA32 || defined MDE_CPU_X64
>>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>> +    //
>>> +    // Prepare CPU arch protocol for NULL pointer detection
>>> +    //
>>> +    Status = gBS->LocateProtocol (
>>> +                    &gEfiCpuArchProtocolGuid,
>>> +                    NULL,
>>> +                    (VOID **) &Cpu
>>> +                    );
>>> +    ASSERT_EFI_ERROR (Status);
>>> +
>>> +    DISABLE_NULL_DETECTION(Cpu);
>>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>> +    ENABLE_NULL_DETECTION(Cpu);
>>
>> (7) The NULL detection disabling and enabling should bracket the 
>> affected code as tightly as possible.
>>
>> So please move this into InstallVbeShim() accordingly.
>>
>>
>>>    }
>>>  #endif
>>>
>>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h 
>>> b/OvmfPkg/QemuVideoDxe/Qemu.h index 7fbb25b3ef..bb3bc6eb0f 100644
>>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>>> @@ -25,6 +25,7 @@
>>>  #include <Protocol/PciIo.h>
>>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>>  #include <Protocol/DevicePath.h>
>>> +#include <Protocol/Cpu.h>
>>>
>>>  #include <Library/DebugLib.h>
>>>  #include <Library/UefiDriverEntryPoint.h> @@ -82,6 +83,21 @@ 
>>> typedef struct {
>>>
>>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>>
>>> +//
>>> +// VBE code will access memory between 0-4095 which will cause page 
>>> +fault exception // if NULL pointer detection mechanism is enabled. 
>>> +Following macros can be used to // disable/enable NULL pointer detection before/after accessing those memory.
>>> +//
>>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>>> +  }
>>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>>> +  }
>>> +
>>
>> (8) I believe Jordan too commented on these macros elsewhere (under 
>> patch 1/4).
>>
>> In my opinion, this functionality should be extracted into a library 
>> class, with a library instance that is suitable for at least 
>> UEFI_DRIVER modules. (Maybe even for DXE_DRIVER modules.)
>>
>> You could add a separate library instance for SMM drivers, if that 
>> were necessary.
>>
>>
>> (9) Style comment: please put one space character between the 
>> function designator and the opening parenthesis.
>>
>>
>>>  //
>>>  // QEMU Video Private Data Structure  // diff --git 
>>> a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf 
>>> b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>> index 7c7d429bca..5d166eb99c 100644
>>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>> @@ -72,7 +72,9 @@
>>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>>> +  gEfiCpuArchProtocolGuid
>>>
>>>  [Pcd]
>>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>>> +  
>>> + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
>>
>> (10) Instead of these, the library class that I described under (8) 
>> should be added here.
>>
>> Any further dependencies like PCDs, protocols etc should be inherited 
>> by the driver through the library instance that the platform DSC file 
>> resolves the library class to.
>>
>> Bonus: should you realize that the feature is impossible to implement 
>> without accessing the CPU Arch protocol directly, you could hide the 
>> protocol GUID dependency in the library instance INF file, and I'd be 
>> none the wiser.
>>
>> ... Well, I could at least pretend that. :)
>>
>> Thanks,
>> Laszlo
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>> https://lists.01.org/mailman/listinfo/edk2-devel
>>


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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  9:39                   ` Zeng, Star
@ 2017-09-14  9:55                     ` Laszlo Ersek
  2017-09-14 10:16                       ` Zeng, Star
  0 siblings, 1 reply; 37+ messages in thread
From: Laszlo Ersek @ 2017-09-14  9:55 UTC (permalink / raw)
  To: Zeng, Star, Wang, Jian J, Yao, Jiewen
  Cc: Dong, Eric, Justen, Jordan L, edk2-devel@lists.01.org,
	Wolman, Ayellet, Kinney, Michael D

On 09/14/17 11:39, Zeng, Star wrote:
> There is a realistic problem I just found and want to share.
> 
> GCD database is built based on resource hob reported from PEI, and
> GCD checks the input Attributes against Capabilities when setting
> Attributes, but we (I just searched the whole codebase) can see there
> is no code reporting resource hob with
> EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE,
> EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE or
> EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE set.
... Are you saying that, if we modify AddMemoryBaseSizeHob() in
OvmfPkg/PlatformPei, to report
EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE (*), then
gDS->SetMemorySpaceAttributes() will start to work?

((*) "MdePkg/Include/Pi/PiHob.h": "NOTE: Since PI spec 1.4, please use
EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE as Memory capability
attribute: The memory supports being protected from processor writes")

If that's the case, then I hope Jian can include such an OvmfPkg patch
in his series. :)

Thanks!
Laszlo

> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com] 
> Sent: Thursday, September 14, 2017 4:54 PM
> To: Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet <ayellet.wolman@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> On 09/14/17 10:46, Wang, Jian J wrote:
>> It’s an implementation limitation. All page attributes will be filtered out before calling CPU arch protocol to update the attributes (Gcd.c).
> 
> That cannot be a random occurrence; I'm sure there was some specific intent behind filtering out the page attributes.
> 
> Does "git blame" provide a reason, from the message of the commit that added the filtering?
> 
> Thanks,
> Laszlo
> 
>> From: Yao, Jiewen
>> Sent: Thursday, September 14, 2017 4:38 PM
>> To: Laszlo Ersek <lersek@redhat.com>; Wang, Jian J 
>> <jian.j.wang@intel.com>
>> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L 
>> <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet 
>> <ayellet.wolman@intel.com>; Kinney, Michael D 
>> <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
>> Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> HI
>> I wonder if it is spec limitation or implementation limitation.
>>
>> If it is implementation limitation, we can enhance the DxeCore to allow it.
>>
>> Thank you
>> Yao Jiewen
>>
>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>> Sent: Thursday, September 14, 2017 4:30 PM
>> To: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; 
>> Justen, Jordan L 
>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; 
>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
>> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
>> Michael D 
>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Zeng, 
>> Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> On 09/14/17 05:17, Wang, Jian J wrote:
>>> For the use of arch protocol, there's one thing I mentioned is not 
>>> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it 
>>> cannot change page attributes. That's why I have to turn to cpu arch 
>>> protocol.
>> Thank you for the explanation.
>>
>> In that case, we cannot avoid violating the PI spec. I agree we can 
>> break the spec if it happens for security purposes, but in that case, 
>> I believe that hiding the implementation behind a library class is 
>> mandatory. Viewed from the spec side, accessing the CPU Arch protocol 
>> is a hack, and so it should not be spread to the source code of 
>> several driver modules.
>>
>> Thank you,
>> Laszlo
>>
>>
>>>
>>> -----Original Message-----
>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf 
>>> Of Wang, Jian J
>>> Sent: Thursday, September 14, 2017 9:17 AM
>>> To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; 
>>> Justen, Jordan L 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; 
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
>>> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
>>> Michael D 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; 
>>> Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>>
>>> Thanks for the comments and good advices. Sorry the format issues.
>>> This is my first patch for this project. Too many details for me to 
>>> get familiar with.
>>>
>>> (1) Sure.
>>> (2) I'll change that.
>>> (3) I'll use the tool to ensure the patch format.
>>> (4) I'll remove the ',' in name
>>> (5) I'll add more description about it.
>>> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>>>      instead. The only reason I didn't do it is that I found
>>>       GetMemorySpaceDescriptor() doesn't return the same information
>>>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>>>     arch protocol is a bit safer. Anyway, I'll change it.
>>> (7) I did put those macros in the install function before. To reduce the
>>>      number of changed files, I made current changes. You're right it's
>>>      not worthy.
>>> (8) Using macro can help the readability, which is more important to me.
>>>     I know function can do the same. But it looks a bit heavy in this situation.
>>>     I have to admit replacing  the macros with a library is a very good idea,
>>>     which brings the same readability. I didn't think of that before. Although
>>>     Library is still a little bit heavy to me but it's in a different way, I think it
>>>     worth a trying.
>>> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
>>> (10) You're right. Using library can reduce the disturbs to affected drivers
>>>        by this feature to the minimum.
>>>
>>> -----Original Message-----
>>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>>> Sent: Thursday, September 14, 2017 7:35 AM
>>> To: Wang, Jian J 
>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>> Cc: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Justen, 
>>> Jordan L 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Dong, 
>>> Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Kinney, 
>>> Michael D 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; 
>>> Wolman, Ayellet 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Yao, 
>>> Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zeng, 
>>> Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>>
>>> Hi,
>>>
>>> some of the points I'm going to make have already been pointed out by
>>> Jordan:
>>>
>>> (1) When posting a patch series, please collect the Cc: tags from all 
>>> of the patches, and add them *all* to the cover letter. This way 
>>> everyone will get a personal copy of the general description.
>>>
>>>
>>> (2) The subject line is too long. One possible simplification:
>>>
>>> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
>>>
>>>
>>> On 09/13/17 11:25, Wang, Jian J wrote:
>>>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL 
>>>> pointer detection is enabled, page 0 must be enabled temporarily 
>>>> before installing and disabled again afterwards. For Windows 7 boot, 
>>>> BIT7 of PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
>>>
>>> (3) Subject line and commit message both should not exceed 74 
>>> characters line length. (Not sure how many chars PatchCheck.py 
>>> actually enforces, I always stick with 74, following the Linux kernel 
>>> tradition.)
>>>
>>> I rewrapped the commit message here for readability.
>>>
>>>
>>>>
>>>> Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>>>> Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>>>> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>>> Cc: Justen, Jordan L 
>>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>>> Cc: Kinney, Michael D 
>>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>>> Cc: Wolman, Ayellet 
>>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>>> Suggested-by: Wolman, Ayellet 
>>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>>> Contributed-under: TianoCore Contribution Agreement 1.1
>>>> Signed-off-by: Wang, Jian J 
>>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>>
>>> (4) I think this is also something that Jordan had pointed out a long 
>>> time ago (apologies if I mis-remember):
>>>
>>> The strings after the tags should form correct email addresses, and 
>>> if there are various email meta-characters in them, like "." (dot) and ","
>>> (comma), then they should be quoted, like this:
>>>
>>> Cc: "Justen, Jordan L" 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>> Cc: "Kinney, Michael D" 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>> Cc: "Wolman, Ayellet" 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Suggested-by: "Wolman, Ayellet" 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Signed-off-by: "Wang, Jian J" 
>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>>
>>> If you look at the actual addresses on the emails that have been sent 
>>> out, you can see they are all malformed. For example, I have:
>>>
>>> "Jordan L 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>" for Jordan -- the part before the comma was taken to be a separate email address (a malformed one).
>>>
>>> At least for my reply, I have fixed up the email addresses.
>>>
>>>
>>> (5) The commit message mentions BIT7 of the new PCD.
>>>
>>> First, thanks for checking Windows 7 boot (and I'm happy that I got 
>>> suspicious of the feature with regard to Windows 7). I think BIT7 is 
>>> a good feature.
>>>
>>> However, please include the short description of that feature in the 
>>> commit message -- it is one sentence; "Disable NULL pointer detection 
>>> just after EndOfDxe."
>>>
>>> (I think BIT7 is a really smart feature, and I like *how* it is used 
>>> in "NULL_DETECTION_ENABLED" below. The check means, "if the 
>>> protection is enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
>>>
>>> This doesn't mean that I like the NULL_DETECTION_ENABLED macro 
>>> itself; more on that below.)
>>>
>>>
>>>> ---
>>>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c 
>>>> b/OvmfPkg/QemuVideoDxe/Driver.c index 0dce80e59b..ee0eed7214 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>>>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>>>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>>>    PCI_TYPE00                        Pci;
>>>>    QEMU_VIDEO_CARD                   *Card;
>>>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>>>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
>>>
>>> (6) I believe I mentioned this in the earlier discussion, in some 
>>> form, but now I'll say it again:
>>>
>>> A UEFI driver has no business poking at the CPU Arch protocol. The PI 
>>> spec (1.6) states,
>>>
>>>   12.3 CPU Architectural Protocol
>>>   EFI_CPU_ARCH_PROTOCOL
>>>
>>>   Summary
>>>
>>>   Abstracts the processor services that are required to implement some
>>>   of the DXE services. This protocol must be produced by a boot service
>>>   or runtime DXE driver and may only be consumed by the DXE Foundation
>>>   and DXE drivers that produce architectural protocols.
>>>
>>> The DXE core is obviously free to use the CPU Arch protocol, but a 
>>> UEFI driver is forbidden from it, *even if* we say that, in this UEFI 
>>> driver, we are going to use DXE services. (Which come from the PI 
>>> spec, and not the UEFI spec.)
>>>
>>> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
>>>
>>> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch 
>>> protocol, by the PI spec. It is not easy to see, because the PI spec 
>>> has a formatting error in this area. If you look under 
>>> GetMemorySpaceDescriptor(), there is an error code
>>>
>>>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>>>                          architectural protocol is not available yet.
>>>
>>> Obviously this error code belongs to SetMemorySpaceAttributes(), not 
>>> GetMemorySpaceDescriptor().
>>>
>>> Anyway, gDS should be used, architectural protocols shouldn't be.
>>>
>>>
>>>>
>>>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>>>
>>>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (  #if defined 
>>>> MDE_CPU_IA32 || defined MDE_CPU_X64
>>>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>>>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>>> +    //
>>>> +    // Prepare CPU arch protocol for NULL pointer detection
>>>> +    //
>>>> +    Status = gBS->LocateProtocol (
>>>> +                    &gEfiCpuArchProtocolGuid,
>>>> +                    NULL,
>>>> +                    (VOID **) &Cpu
>>>> +                    );
>>>> +    ASSERT_EFI_ERROR (Status);
>>>> +
>>>> +    DISABLE_NULL_DETECTION(Cpu);
>>>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>>> +    ENABLE_NULL_DETECTION(Cpu);
>>>
>>> (7) The NULL detection disabling and enabling should bracket the 
>>> affected code as tightly as possible.
>>>
>>> So please move this into InstallVbeShim() accordingly.
>>>
>>>
>>>>    }
>>>>  #endif
>>>>
>>>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h 
>>>> b/OvmfPkg/QemuVideoDxe/Qemu.h index 7fbb25b3ef..bb3bc6eb0f 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>>>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>>>> @@ -25,6 +25,7 @@
>>>>  #include <Protocol/PciIo.h>
>>>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>>>  #include <Protocol/DevicePath.h>
>>>> +#include <Protocol/Cpu.h>
>>>>
>>>>  #include <Library/DebugLib.h>
>>>>  #include <Library/UefiDriverEntryPoint.h> @@ -82,6 +83,21 @@ 
>>>> typedef struct {
>>>>
>>>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>>>
>>>> +//
>>>> +// VBE code will access memory between 0-4095 which will cause page 
>>>> +fault exception // if NULL pointer detection mechanism is enabled. 
>>>> +Following macros can be used to // disable/enable NULL pointer detection before/after accessing those memory.
>>>> +//
>>>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>>>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>>>> +  }
>>>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>>>> +  }
>>>> +
>>>
>>> (8) I believe Jordan too commented on these macros elsewhere (under 
>>> patch 1/4).
>>>
>>> In my opinion, this functionality should be extracted into a library 
>>> class, with a library instance that is suitable for at least 
>>> UEFI_DRIVER modules. (Maybe even for DXE_DRIVER modules.)
>>>
>>> You could add a separate library instance for SMM drivers, if that 
>>> were necessary.
>>>
>>>
>>> (9) Style comment: please put one space character between the 
>>> function designator and the opening parenthesis.
>>>
>>>
>>>>  //
>>>>  // QEMU Video Private Data Structure  // diff --git 
>>>> a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf 
>>>> b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> index 7c7d429bca..5d166eb99c 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> @@ -72,7 +72,9 @@
>>>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>>>> +  gEfiCpuArchProtocolGuid
>>>>
>>>>  [Pcd]
>>>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>>>> +  
>>>> + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
>>>
>>> (10) Instead of these, the library class that I described under (8) 
>>> should be added here.
>>>
>>> Any further dependencies like PCDs, protocols etc should be inherited 
>>> by the driver through the library instance that the platform DSC file 
>>> resolves the library class to.
>>>
>>> Bonus: should you realize that the feature is impossible to implement 
>>> without accessing the CPU Arch protocol directly, you could hide the 
>>> protocol GUID dependency in the library instance INF file, and I'd be 
>>> none the wiser.
>>>
>>> ... Well, I could at least pretend that. :)
>>>
>>> Thanks,
>>> Laszlo
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>>> https://lists.01.org/mailman/listinfo/edk2-devel
>>>
> 



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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14  9:55                     ` Laszlo Ersek
@ 2017-09-14 10:16                       ` Zeng, Star
  2017-09-15  0:15                         ` Wang, Jian J
  0 siblings, 1 reply; 37+ messages in thread
From: Zeng, Star @ 2017-09-14 10:16 UTC (permalink / raw)
  To: Laszlo Ersek, Wang, Jian J, Yao, Jiewen
  Cc: Kinney, Michael D, Justen, Jordan L, edk2-devel@lists.01.org,
	Dong, Eric, Wolman, Ayellet, Zeng, Star

No, I want to say even the GCD is updated to not filter page attributes, it will still not work as all the memory controller code for now are not reporting the Capability.


Thanks,
Star
-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Laszlo Ersek
Sent: Thursday, September 14, 2017 5:55 PM
To: Zeng, Star <star.zeng@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

On 09/14/17 11:39, Zeng, Star wrote:
> There is a realistic problem I just found and want to share.
> 
> GCD database is built based on resource hob reported from PEI, and GCD 
> checks the input Attributes against Capabilities when setting 
> Attributes, but we (I just searched the whole codebase) can see there 
> is no code reporting resource hob with 
> EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE,
> EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE or 
> EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE set.
... Are you saying that, if we modify AddMemoryBaseSizeHob() in OvmfPkg/PlatformPei, to report EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE (*), then
gDS->SetMemorySpaceAttributes() will start to work?

((*) "MdePkg/Include/Pi/PiHob.h": "NOTE: Since PI spec 1.4, please use EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE as Memory capability
attribute: The memory supports being protected from processor writes")

If that's the case, then I hope Jian can include such an OvmfPkg patch in his series. :)

Thanks!
Laszlo

> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Thursday, September 14, 2017 4:54 PM
> To: Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen 
> <jiewen.yao@intel.com>
> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L 
> <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet 
> <ayellet.wolman@intel.com>; Kinney, Michael D 
> <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> On 09/14/17 10:46, Wang, Jian J wrote:
>> It’s an implementation limitation. All page attributes will be filtered out before calling CPU arch protocol to update the attributes (Gcd.c).
> 
> That cannot be a random occurrence; I'm sure there was some specific intent behind filtering out the page attributes.
> 
> Does "git blame" provide a reason, from the message of the commit that added the filtering?
> 
> Thanks,
> Laszlo
> 
>> From: Yao, Jiewen
>> Sent: Thursday, September 14, 2017 4:38 PM
>> To: Laszlo Ersek <lersek@redhat.com>; Wang, Jian J 
>> <jian.j.wang@intel.com>
>> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L 
>> <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet 
>> <ayellet.wolman@intel.com>; Kinney, Michael D 
>> <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
>> Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> HI
>> I wonder if it is spec limitation or implementation limitation.
>>
>> If it is implementation limitation, we can enhance the DxeCore to allow it.
>>
>> Thank you
>> Yao Jiewen
>>
>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>> Sent: Thursday, September 14, 2017 4:30 PM
>> To: Wang, Jian J 
>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>;
>> Justen, Jordan L
>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>;
>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
>> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
>> Michael D 
>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; 
>> Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> On 09/14/17 05:17, Wang, Jian J wrote:
>>> For the use of arch protocol, there's one thing I mentioned is not 
>>> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it 
>>> cannot change page attributes. That's why I have to turn to cpu arch 
>>> protocol.
>> Thank you for the explanation.
>>
>> In that case, we cannot avoid violating the PI spec. I agree we can 
>> break the spec if it happens for security purposes, but in that case, 
>> I believe that hiding the implementation behind a library class is 
>> mandatory. Viewed from the spec side, accessing the CPU Arch protocol 
>> is a hack, and so it should not be spread to the source code of 
>> several driver modules.
>>
>> Thank you,
>> Laszlo
>>
>>
>>>
>>> -----Original Message-----
>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf 
>>> Of Wang, Jian J
>>> Sent: Thursday, September 14, 2017 9:17 AM
>>> To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>;
>>> Justen, Jordan L
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>;
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
>>> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
>>> Michael D 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
>>> Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>>
>>> Thanks for the comments and good advices. Sorry the format issues.
>>> This is my first patch for this project. Too many details for me to 
>>> get familiar with.
>>>
>>> (1) Sure.
>>> (2) I'll change that.
>>> (3) I'll use the tool to ensure the patch format.
>>> (4) I'll remove the ',' in name
>>> (5) I'll add more description about it.
>>> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>>>      instead. The only reason I didn't do it is that I found
>>>       GetMemorySpaceDescriptor() doesn't return the same information
>>>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>>>     arch protocol is a bit safer. Anyway, I'll change it.
>>> (7) I did put those macros in the install function before. To reduce the
>>>      number of changed files, I made current changes. You're right it's
>>>      not worthy.
>>> (8) Using macro can help the readability, which is more important to me.
>>>     I know function can do the same. But it looks a bit heavy in this situation.
>>>     I have to admit replacing  the macros with a library is a very good idea,
>>>     which brings the same readability. I didn't think of that before. Although
>>>     Library is still a little bit heavy to me but it's in a different way, I think it
>>>     worth a trying.
>>> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
>>> (10) You're right. Using library can reduce the disturbs to affected drivers
>>>        by this feature to the minimum.
>>>
>>> -----Original Message-----
>>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>>> Sent: Thursday, September 14, 2017 7:35 AM
>>> To: Wang, Jian J
>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>> Cc: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Justen, 
>>> Jordan L 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Dong, 
>>> Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Kinney, 
>>> Michael D 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
>>> Wolman, Ayellet
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Yao, 
>>> Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zeng, 
>>> Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>>
>>> Hi,
>>>
>>> some of the points I'm going to make have already been pointed out 
>>> by
>>> Jordan:
>>>
>>> (1) When posting a patch series, please collect the Cc: tags from 
>>> all of the patches, and add them *all* to the cover letter. This way 
>>> everyone will get a personal copy of the general description.
>>>
>>>
>>> (2) The subject line is too long. One possible simplification:
>>>
>>> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
>>>
>>>
>>> On 09/13/17 11:25, Wang, Jian J wrote:
>>>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL 
>>>> pointer detection is enabled, page 0 must be enabled temporarily 
>>>> before installing and disabled again afterwards. For Windows 7 
>>>> boot,
>>>> BIT7 of PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
>>>
>>> (3) Subject line and commit message both should not exceed 74 
>>> characters line length. (Not sure how many chars PatchCheck.py 
>>> actually enforces, I always stick with 74, following the Linux 
>>> kernel
>>> tradition.)
>>>
>>> I rewrapped the commit message here for readability.
>>>
>>>
>>>>
>>>> Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>>>> Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>>>> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>>> Cc: Justen, Jordan L
>>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>>> Cc: Kinney, Michael D
>>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>>> Cc: Wolman, Ayellet
>>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>>> Suggested-by: Wolman, Ayellet
>>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>>> Contributed-under: TianoCore Contribution Agreement 1.1
>>>> Signed-off-by: Wang, Jian J
>>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>>
>>> (4) I think this is also something that Jordan had pointed out a 
>>> long time ago (apologies if I mis-remember):
>>>
>>> The strings after the tags should form correct email addresses, and 
>>> if there are various email meta-characters in them, like "." (dot) and ","
>>> (comma), then they should be quoted, like this:
>>>
>>> Cc: "Justen, Jordan L" 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>> Cc: "Kinney, Michael D" 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>> Cc: "Wolman, Ayellet" 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Suggested-by: "Wolman, Ayellet" 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Signed-off-by: "Wang, Jian J" 
>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>>
>>> If you look at the actual addresses on the emails that have been 
>>> sent out, you can see they are all malformed. For example, I have:
>>>
>>> "Jordan L
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>" for Jordan -- the part before the comma was taken to be a separate email address (a malformed one).
>>>
>>> At least for my reply, I have fixed up the email addresses.
>>>
>>>
>>> (5) The commit message mentions BIT7 of the new PCD.
>>>
>>> First, thanks for checking Windows 7 boot (and I'm happy that I got 
>>> suspicious of the feature with regard to Windows 7). I think BIT7 is 
>>> a good feature.
>>>
>>> However, please include the short description of that feature in the 
>>> commit message -- it is one sentence; "Disable NULL pointer 
>>> detection just after EndOfDxe."
>>>
>>> (I think BIT7 is a really smart feature, and I like *how* it is used 
>>> in "NULL_DETECTION_ENABLED" below. The check means, "if the 
>>> protection is enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
>>>
>>> This doesn't mean that I like the NULL_DETECTION_ENABLED macro 
>>> itself; more on that below.)
>>>
>>>
>>>> ---
>>>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c 
>>>> b/OvmfPkg/QemuVideoDxe/Driver.c index 0dce80e59b..ee0eed7214 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>>>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>>>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>>>    PCI_TYPE00                        Pci;
>>>>    QEMU_VIDEO_CARD                   *Card;
>>>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>>>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
>>>
>>> (6) I believe I mentioned this in the earlier discussion, in some 
>>> form, but now I'll say it again:
>>>
>>> A UEFI driver has no business poking at the CPU Arch protocol. The 
>>> PI spec (1.6) states,
>>>
>>>   12.3 CPU Architectural Protocol
>>>   EFI_CPU_ARCH_PROTOCOL
>>>
>>>   Summary
>>>
>>>   Abstracts the processor services that are required to implement some
>>>   of the DXE services. This protocol must be produced by a boot service
>>>   or runtime DXE driver and may only be consumed by the DXE Foundation
>>>   and DXE drivers that produce architectural protocols.
>>>
>>> The DXE core is obviously free to use the CPU Arch protocol, but a 
>>> UEFI driver is forbidden from it, *even if* we say that, in this 
>>> UEFI driver, we are going to use DXE services. (Which come from the 
>>> PI spec, and not the UEFI spec.)
>>>
>>> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
>>>
>>> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch 
>>> protocol, by the PI spec. It is not easy to see, because the PI spec 
>>> has a formatting error in this area. If you look under 
>>> GetMemorySpaceDescriptor(), there is an error code
>>>
>>>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>>>                          architectural protocol is not available yet.
>>>
>>> Obviously this error code belongs to SetMemorySpaceAttributes(), not 
>>> GetMemorySpaceDescriptor().
>>>
>>> Anyway, gDS should be used, architectural protocols shouldn't be.
>>>
>>>
>>>>
>>>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>>>
>>>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (  #if defined
>>>> MDE_CPU_IA32 || defined MDE_CPU_X64
>>>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>>>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>>> +    //
>>>> +    // Prepare CPU arch protocol for NULL pointer detection
>>>> +    //
>>>> +    Status = gBS->LocateProtocol (
>>>> +                    &gEfiCpuArchProtocolGuid,
>>>> +                    NULL,
>>>> +                    (VOID **) &Cpu
>>>> +                    );
>>>> +    ASSERT_EFI_ERROR (Status);
>>>> +
>>>> +    DISABLE_NULL_DETECTION(Cpu);
>>>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>>> +    ENABLE_NULL_DETECTION(Cpu);
>>>
>>> (7) The NULL detection disabling and enabling should bracket the 
>>> affected code as tightly as possible.
>>>
>>> So please move this into InstallVbeShim() accordingly.
>>>
>>>
>>>>    }
>>>>  #endif
>>>>
>>>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h 
>>>> b/OvmfPkg/QemuVideoDxe/Qemu.h index 7fbb25b3ef..bb3bc6eb0f 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>>>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>>>> @@ -25,6 +25,7 @@
>>>>  #include <Protocol/PciIo.h>
>>>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>>>  #include <Protocol/DevicePath.h>
>>>> +#include <Protocol/Cpu.h>
>>>>
>>>>  #include <Library/DebugLib.h>
>>>>  #include <Library/UefiDriverEntryPoint.h> @@ -82,6 +83,21 @@ 
>>>> typedef struct {
>>>>
>>>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>>>
>>>> +//
>>>> +// VBE code will access memory between 0-4095 which will cause 
>>>> +page fault exception // if NULL pointer detection mechanism is enabled.
>>>> +Following macros can be used to // disable/enable NULL pointer detection before/after accessing those memory.
>>>> +//
>>>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>>>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>>>> +  }
>>>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>>>> +  }
>>>> +
>>>
>>> (8) I believe Jordan too commented on these macros elsewhere (under 
>>> patch 1/4).
>>>
>>> In my opinion, this functionality should be extracted into a library 
>>> class, with a library instance that is suitable for at least 
>>> UEFI_DRIVER modules. (Maybe even for DXE_DRIVER modules.)
>>>
>>> You could add a separate library instance for SMM drivers, if that 
>>> were necessary.
>>>
>>>
>>> (9) Style comment: please put one space character between the 
>>> function designator and the opening parenthesis.
>>>
>>>
>>>>  //
>>>>  // QEMU Video Private Data Structure  // diff --git 
>>>> a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> index 7c7d429bca..5d166eb99c 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> @@ -72,7 +72,9 @@
>>>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>>>> +  gEfiCpuArchProtocolGuid
>>>>
>>>>  [Pcd]
>>>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>>>> +  
>>>> + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMas
>>>> + k
>>>
>>> (10) Instead of these, the library class that I described under (8) 
>>> should be added here.
>>>
>>> Any further dependencies like PCDs, protocols etc should be 
>>> inherited by the driver through the library instance that the 
>>> platform DSC file resolves the library class to.
>>>
>>> Bonus: should you realize that the feature is impossible to 
>>> implement without accessing the CPU Arch protocol directly, you 
>>> could hide the protocol GUID dependency in the library instance INF 
>>> file, and I'd be none the wiser.
>>>
>>> ... Well, I could at least pretend that. :)
>>>
>>> Thanks,
>>> Laszlo
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>>> https://lists.01.org/mailman/listinfo/edk2-devel
>>>
> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-14 10:16                       ` Zeng, Star
@ 2017-09-15  0:15                         ` Wang, Jian J
  2017-09-15  6:05                           ` Wang, Jian J
  0 siblings, 1 reply; 37+ messages in thread
From: Wang, Jian J @ 2017-09-15  0:15 UTC (permalink / raw)
  To: Zeng, Star, Laszlo Ersek, Yao, Jiewen
  Cc: Kinney, Michael D, Justen, Jordan L, edk2-devel@lists.01.org,
	Dong, Eric, Wolman, Ayellet

gDS-> SetMemorySpaceCapabilities() can change the Capability at any time. But I'm not sure about any side-effect of it.

-----Original Message-----
From: Zeng, Star 
Sent: Thursday, September 14, 2017 6:17 PM
To: Laszlo Ersek <lersek@redhat.com>; Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

No, I want to say even the GCD is updated to not filter page attributes, it will still not work as all the memory controller code for now are not reporting the Capability.


Thanks,
Star
-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Laszlo Ersek
Sent: Thursday, September 14, 2017 5:55 PM
To: Zeng, Star <star.zeng@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

On 09/14/17 11:39, Zeng, Star wrote:
> There is a realistic problem I just found and want to share.
> 
> GCD database is built based on resource hob reported from PEI, and GCD 
> checks the input Attributes against Capabilities when setting 
> Attributes, but we (I just searched the whole codebase) can see there 
> is no code reporting resource hob with 
> EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE,
> EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE or 
> EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE set.
... Are you saying that, if we modify AddMemoryBaseSizeHob() in OvmfPkg/PlatformPei, to report EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE (*), then
gDS->SetMemorySpaceAttributes() will start to work?

((*) "MdePkg/Include/Pi/PiHob.h": "NOTE: Since PI spec 1.4, please use EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE as Memory capability
attribute: The memory supports being protected from processor writes")

If that's the case, then I hope Jian can include such an OvmfPkg patch in his series. :)

Thanks!
Laszlo

> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Thursday, September 14, 2017 4:54 PM
> To: Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen 
> <jiewen.yao@intel.com>
> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L 
> <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet 
> <ayellet.wolman@intel.com>; Kinney, Michael D 
> <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> On 09/14/17 10:46, Wang, Jian J wrote:
>> It’s an implementation limitation. All page attributes will be filtered out before calling CPU arch protocol to update the attributes (Gcd.c).
> 
> That cannot be a random occurrence; I'm sure there was some specific intent behind filtering out the page attributes.
> 
> Does "git blame" provide a reason, from the message of the commit that added the filtering?
> 
> Thanks,
> Laszlo
> 
>> From: Yao, Jiewen
>> Sent: Thursday, September 14, 2017 4:38 PM
>> To: Laszlo Ersek <lersek@redhat.com>; Wang, Jian J 
>> <jian.j.wang@intel.com>
>> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L 
>> <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet 
>> <ayellet.wolman@intel.com>; Kinney, Michael D 
>> <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
>> Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> HI
>> I wonder if it is spec limitation or implementation limitation.
>>
>> If it is implementation limitation, we can enhance the DxeCore to allow it.
>>
>> Thank you
>> Yao Jiewen
>>
>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>> Sent: Thursday, September 14, 2017 4:30 PM
>> To: Wang, Jian J 
>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>;
>> Justen, Jordan L
>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>;
>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
>> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
>> Michael D 
>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; 
>> Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> On 09/14/17 05:17, Wang, Jian J wrote:
>>> For the use of arch protocol, there's one thing I mentioned is not 
>>> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it 
>>> cannot change page attributes. That's why I have to turn to cpu arch 
>>> protocol.
>> Thank you for the explanation.
>>
>> In that case, we cannot avoid violating the PI spec. I agree we can 
>> break the spec if it happens for security purposes, but in that case, 
>> I believe that hiding the implementation behind a library class is 
>> mandatory. Viewed from the spec side, accessing the CPU Arch protocol 
>> is a hack, and so it should not be spread to the source code of 
>> several driver modules.
>>
>> Thank you,
>> Laszlo
>>
>>
>>>
>>> -----Original Message-----
>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf 
>>> Of Wang, Jian J
>>> Sent: Thursday, September 14, 2017 9:17 AM
>>> To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>;
>>> Justen, Jordan L
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>;
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
>>> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
>>> Michael D 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
>>> Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>>
>>> Thanks for the comments and good advices. Sorry the format issues.
>>> This is my first patch for this project. Too many details for me to 
>>> get familiar with.
>>>
>>> (1) Sure.
>>> (2) I'll change that.
>>> (3) I'll use the tool to ensure the patch format.
>>> (4) I'll remove the ',' in name
>>> (5) I'll add more description about it.
>>> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>>>      instead. The only reason I didn't do it is that I found
>>>       GetMemorySpaceDescriptor() doesn't return the same information
>>>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>>>     arch protocol is a bit safer. Anyway, I'll change it.
>>> (7) I did put those macros in the install function before. To reduce the
>>>      number of changed files, I made current changes. You're right it's
>>>      not worthy.
>>> (8) Using macro can help the readability, which is more important to me.
>>>     I know function can do the same. But it looks a bit heavy in this situation.
>>>     I have to admit replacing  the macros with a library is a very good idea,
>>>     which brings the same readability. I didn't think of that before. Although
>>>     Library is still a little bit heavy to me but it's in a different way, I think it
>>>     worth a trying.
>>> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
>>> (10) You're right. Using library can reduce the disturbs to affected drivers
>>>        by this feature to the minimum.
>>>
>>> -----Original Message-----
>>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>>> Sent: Thursday, September 14, 2017 7:35 AM
>>> To: Wang, Jian J
>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>> Cc: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Justen, 
>>> Jordan L 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Dong, 
>>> Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Kinney, 
>>> Michael D 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
>>> Wolman, Ayellet
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Yao, 
>>> Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zeng, 
>>> Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>>
>>> Hi,
>>>
>>> some of the points I'm going to make have already been pointed out 
>>> by
>>> Jordan:
>>>
>>> (1) When posting a patch series, please collect the Cc: tags from 
>>> all of the patches, and add them *all* to the cover letter. This way 
>>> everyone will get a personal copy of the general description.
>>>
>>>
>>> (2) The subject line is too long. One possible simplification:
>>>
>>> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
>>>
>>>
>>> On 09/13/17 11:25, Wang, Jian J wrote:
>>>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL 
>>>> pointer detection is enabled, page 0 must be enabled temporarily 
>>>> before installing and disabled again afterwards. For Windows 7 
>>>> boot,
>>>> BIT7 of PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
>>>
>>> (3) Subject line and commit message both should not exceed 74 
>>> characters line length. (Not sure how many chars PatchCheck.py 
>>> actually enforces, I always stick with 74, following the Linux 
>>> kernel
>>> tradition.)
>>>
>>> I rewrapped the commit message here for readability.
>>>
>>>
>>>>
>>>> Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>>>> Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>>>> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>>> Cc: Justen, Jordan L
>>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>>> Cc: Kinney, Michael D
>>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>>> Cc: Wolman, Ayellet
>>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>>> Suggested-by: Wolman, Ayellet
>>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>>> Contributed-under: TianoCore Contribution Agreement 1.1
>>>> Signed-off-by: Wang, Jian J
>>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>>
>>> (4) I think this is also something that Jordan had pointed out a 
>>> long time ago (apologies if I mis-remember):
>>>
>>> The strings after the tags should form correct email addresses, and 
>>> if there are various email meta-characters in them, like "." (dot) and ","
>>> (comma), then they should be quoted, like this:
>>>
>>> Cc: "Justen, Jordan L" 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>> Cc: "Kinney, Michael D" 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>> Cc: "Wolman, Ayellet" 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Suggested-by: "Wolman, Ayellet" 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Signed-off-by: "Wang, Jian J" 
>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>>
>>> If you look at the actual addresses on the emails that have been 
>>> sent out, you can see they are all malformed. For example, I have:
>>>
>>> "Jordan L
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>" for Jordan -- the part before the comma was taken to be a separate email address (a malformed one).
>>>
>>> At least for my reply, I have fixed up the email addresses.
>>>
>>>
>>> (5) The commit message mentions BIT7 of the new PCD.
>>>
>>> First, thanks for checking Windows 7 boot (and I'm happy that I got 
>>> suspicious of the feature with regard to Windows 7). I think BIT7 is 
>>> a good feature.
>>>
>>> However, please include the short description of that feature in the 
>>> commit message -- it is one sentence; "Disable NULL pointer 
>>> detection just after EndOfDxe."
>>>
>>> (I think BIT7 is a really smart feature, and I like *how* it is used 
>>> in "NULL_DETECTION_ENABLED" below. The check means, "if the 
>>> protection is enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
>>>
>>> This doesn't mean that I like the NULL_DETECTION_ENABLED macro 
>>> itself; more on that below.)
>>>
>>>
>>>> ---
>>>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c 
>>>> b/OvmfPkg/QemuVideoDxe/Driver.c index 0dce80e59b..ee0eed7214 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>>>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>>>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>>>    PCI_TYPE00                        Pci;
>>>>    QEMU_VIDEO_CARD                   *Card;
>>>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>>>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
>>>
>>> (6) I believe I mentioned this in the earlier discussion, in some 
>>> form, but now I'll say it again:
>>>
>>> A UEFI driver has no business poking at the CPU Arch protocol. The 
>>> PI spec (1.6) states,
>>>
>>>   12.3 CPU Architectural Protocol
>>>   EFI_CPU_ARCH_PROTOCOL
>>>
>>>   Summary
>>>
>>>   Abstracts the processor services that are required to implement some
>>>   of the DXE services. This protocol must be produced by a boot service
>>>   or runtime DXE driver and may only be consumed by the DXE Foundation
>>>   and DXE drivers that produce architectural protocols.
>>>
>>> The DXE core is obviously free to use the CPU Arch protocol, but a 
>>> UEFI driver is forbidden from it, *even if* we say that, in this 
>>> UEFI driver, we are going to use DXE services. (Which come from the 
>>> PI spec, and not the UEFI spec.)
>>>
>>> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
>>>
>>> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch 
>>> protocol, by the PI spec. It is not easy to see, because the PI spec 
>>> has a formatting error in this area. If you look under 
>>> GetMemorySpaceDescriptor(), there is an error code
>>>
>>>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>>>                          architectural protocol is not available yet.
>>>
>>> Obviously this error code belongs to SetMemorySpaceAttributes(), not 
>>> GetMemorySpaceDescriptor().
>>>
>>> Anyway, gDS should be used, architectural protocols shouldn't be.
>>>
>>>
>>>>
>>>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>>>
>>>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (  #if defined
>>>> MDE_CPU_IA32 || defined MDE_CPU_X64
>>>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>>>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>>> +    //
>>>> +    // Prepare CPU arch protocol for NULL pointer detection
>>>> +    //
>>>> +    Status = gBS->LocateProtocol (
>>>> +                    &gEfiCpuArchProtocolGuid,
>>>> +                    NULL,
>>>> +                    (VOID **) &Cpu
>>>> +                    );
>>>> +    ASSERT_EFI_ERROR (Status);
>>>> +
>>>> +    DISABLE_NULL_DETECTION(Cpu);
>>>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>>> +    ENABLE_NULL_DETECTION(Cpu);
>>>
>>> (7) The NULL detection disabling and enabling should bracket the 
>>> affected code as tightly as possible.
>>>
>>> So please move this into InstallVbeShim() accordingly.
>>>
>>>
>>>>    }
>>>>  #endif
>>>>
>>>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h 
>>>> b/OvmfPkg/QemuVideoDxe/Qemu.h index 7fbb25b3ef..bb3bc6eb0f 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>>>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>>>> @@ -25,6 +25,7 @@
>>>>  #include <Protocol/PciIo.h>
>>>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>>>  #include <Protocol/DevicePath.h>
>>>> +#include <Protocol/Cpu.h>
>>>>
>>>>  #include <Library/DebugLib.h>
>>>>  #include <Library/UefiDriverEntryPoint.h> @@ -82,6 +83,21 @@ 
>>>> typedef struct {
>>>>
>>>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>>>
>>>> +//
>>>> +// VBE code will access memory between 0-4095 which will cause 
>>>> +page fault exception // if NULL pointer detection mechanism is enabled.
>>>> +Following macros can be used to // disable/enable NULL pointer detection before/after accessing those memory.
>>>> +//
>>>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>>>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>>>> +  }
>>>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>>>> +  }
>>>> +
>>>
>>> (8) I believe Jordan too commented on these macros elsewhere (under 
>>> patch 1/4).
>>>
>>> In my opinion, this functionality should be extracted into a library 
>>> class, with a library instance that is suitable for at least 
>>> UEFI_DRIVER modules. (Maybe even for DXE_DRIVER modules.)
>>>
>>> You could add a separate library instance for SMM drivers, if that 
>>> were necessary.
>>>
>>>
>>> (9) Style comment: please put one space character between the 
>>> function designator and the opening parenthesis.
>>>
>>>
>>>>  //
>>>>  // QEMU Video Private Data Structure  // diff --git 
>>>> a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> index 7c7d429bca..5d166eb99c 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> @@ -72,7 +72,9 @@
>>>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>>>> +  gEfiCpuArchProtocolGuid
>>>>
>>>>  [Pcd]
>>>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>>>> +  
>>>> + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMas
>>>> + k
>>>
>>> (10) Instead of these, the library class that I described under (8) 
>>> should be added here.
>>>
>>> Any further dependencies like PCDs, protocols etc should be 
>>> inherited by the driver through the library instance that the 
>>> platform DSC file resolves the library class to.
>>>
>>> Bonus: should you realize that the feature is impossible to 
>>> implement without accessing the CPU Arch protocol directly, you 
>>> could hide the protocol GUID dependency in the library instance INF 
>>> file, and I'd be none the wiser.
>>>
>>> ... Well, I could at least pretend that. :)
>>>
>>> Thanks,
>>> Laszlo
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>>> https://lists.01.org/mailman/listinfo/edk2-devel
>>>
> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-15  0:15                         ` Wang, Jian J
@ 2017-09-15  6:05                           ` Wang, Jian J
  2017-09-15  6:28                             ` Zeng, Star
  0 siblings, 1 reply; 37+ messages in thread
From: Wang, Jian J @ 2017-09-15  6:05 UTC (permalink / raw)
  To: Wang, Jian J, Zeng, Star, Laszlo Ersek, Yao, Jiewen
  Cc: Kinney, Michael D, Justen, Jordan L, edk2-devel@lists.01.org,
	Dong, Eric, Wolman, Ayellet

For record, we'll make following changes to address the page attributes issue:

(1) Update gDS->SetMemorySpaceAddress() to remove the filter set on page attributes
(2) Update CPU driver to sync all memory attributes including page related. No platform code changes needed.

Above changes will be submitted in a separate patch. As a result (after it's done), the related changes for this patch will be 
(3) Replace macros with functions, in which gDS->SetMemorySpaceAttributes() will be used instead of CPU arch method.


-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
Sent: Friday, September 15, 2017 8:15 AM
To: Zeng, Star <star.zeng@intel.com>; Laszlo Ersek <lersek@redhat.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

gDS-> SetMemorySpaceCapabilities() can change the Capability at any time. But I'm not sure about any side-effect of it.

-----Original Message-----
From: Zeng, Star 
Sent: Thursday, September 14, 2017 6:17 PM
To: Laszlo Ersek <lersek@redhat.com>; Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

No, I want to say even the GCD is updated to not filter page attributes, it will still not work as all the memory controller code for now are not reporting the Capability.


Thanks,
Star
-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Laszlo Ersek
Sent: Thursday, September 14, 2017 5:55 PM
To: Zeng, Star <star.zeng@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

On 09/14/17 11:39, Zeng, Star wrote:
> There is a realistic problem I just found and want to share.
> 
> GCD database is built based on resource hob reported from PEI, and GCD 
> checks the input Attributes against Capabilities when setting 
> Attributes, but we (I just searched the whole codebase) can see there 
> is no code reporting resource hob with 
> EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE,
> EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE or 
> EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE set.
... Are you saying that, if we modify AddMemoryBaseSizeHob() in OvmfPkg/PlatformPei, to report EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE (*), then
gDS->SetMemorySpaceAttributes() will start to work?

((*) "MdePkg/Include/Pi/PiHob.h": "NOTE: Since PI spec 1.4, please use EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE as Memory capability
attribute: The memory supports being protected from processor writes")

If that's the case, then I hope Jian can include such an OvmfPkg patch in his series. :)

Thanks!
Laszlo

> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Thursday, September 14, 2017 4:54 PM
> To: Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen 
> <jiewen.yao@intel.com>
> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L 
> <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet 
> <ayellet.wolman@intel.com>; Kinney, Michael D 
> <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> On 09/14/17 10:46, Wang, Jian J wrote:
>> It’s an implementation limitation. All page attributes will be filtered out before calling CPU arch protocol to update the attributes (Gcd.c).
> 
> That cannot be a random occurrence; I'm sure there was some specific intent behind filtering out the page attributes.
> 
> Does "git blame" provide a reason, from the message of the commit that added the filtering?
> 
> Thanks,
> Laszlo
> 
>> From: Yao, Jiewen
>> Sent: Thursday, September 14, 2017 4:38 PM
>> To: Laszlo Ersek <lersek@redhat.com>; Wang, Jian J 
>> <jian.j.wang@intel.com>
>> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L 
>> <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet 
>> <ayellet.wolman@intel.com>; Kinney, Michael D 
>> <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
>> Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> HI
>> I wonder if it is spec limitation or implementation limitation.
>>
>> If it is implementation limitation, we can enhance the DxeCore to allow it.
>>
>> Thank you
>> Yao Jiewen
>>
>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>> Sent: Thursday, September 14, 2017 4:30 PM
>> To: Wang, Jian J 
>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>;
>> Justen, Jordan L
>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>;
>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
>> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
>> Michael D 
>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; 
>> Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> On 09/14/17 05:17, Wang, Jian J wrote:
>>> For the use of arch protocol, there's one thing I mentioned is not 
>>> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it 
>>> cannot change page attributes. That's why I have to turn to cpu arch 
>>> protocol.
>> Thank you for the explanation.
>>
>> In that case, we cannot avoid violating the PI spec. I agree we can 
>> break the spec if it happens for security purposes, but in that case, 
>> I believe that hiding the implementation behind a library class is 
>> mandatory. Viewed from the spec side, accessing the CPU Arch protocol 
>> is a hack, and so it should not be spread to the source code of 
>> several driver modules.
>>
>> Thank you,
>> Laszlo
>>
>>
>>>
>>> -----Original Message-----
>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf 
>>> Of Wang, Jian J
>>> Sent: Thursday, September 14, 2017 9:17 AM
>>> To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>;
>>> Justen, Jordan L
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>;
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
>>> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
>>> Michael D 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
>>> Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>>
>>> Thanks for the comments and good advices. Sorry the format issues.
>>> This is my first patch for this project. Too many details for me to 
>>> get familiar with.
>>>
>>> (1) Sure.
>>> (2) I'll change that.
>>> (3) I'll use the tool to ensure the patch format.
>>> (4) I'll remove the ',' in name
>>> (5) I'll add more description about it.
>>> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>>>      instead. The only reason I didn't do it is that I found
>>>       GetMemorySpaceDescriptor() doesn't return the same information
>>>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>>>     arch protocol is a bit safer. Anyway, I'll change it.
>>> (7) I did put those macros in the install function before. To reduce the
>>>      number of changed files, I made current changes. You're right it's
>>>      not worthy.
>>> (8) Using macro can help the readability, which is more important to me.
>>>     I know function can do the same. But it looks a bit heavy in this situation.
>>>     I have to admit replacing  the macros with a library is a very good idea,
>>>     which brings the same readability. I didn't think of that before. Although
>>>     Library is still a little bit heavy to me but it's in a different way, I think it
>>>     worth a trying.
>>> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
>>> (10) You're right. Using library can reduce the disturbs to affected drivers
>>>        by this feature to the minimum.
>>>
>>> -----Original Message-----
>>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>>> Sent: Thursday, September 14, 2017 7:35 AM
>>> To: Wang, Jian J
>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>> Cc: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Justen, 
>>> Jordan L 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Dong, 
>>> Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Kinney, 
>>> Michael D 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
>>> Wolman, Ayellet
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Yao, 
>>> Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zeng, 
>>> Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>>
>>> Hi,
>>>
>>> some of the points I'm going to make have already been pointed out 
>>> by
>>> Jordan:
>>>
>>> (1) When posting a patch series, please collect the Cc: tags from 
>>> all of the patches, and add them *all* to the cover letter. This way 
>>> everyone will get a personal copy of the general description.
>>>
>>>
>>> (2) The subject line is too long. One possible simplification:
>>>
>>> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
>>>
>>>
>>> On 09/13/17 11:25, Wang, Jian J wrote:
>>>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL 
>>>> pointer detection is enabled, page 0 must be enabled temporarily 
>>>> before installing and disabled again afterwards. For Windows 7 
>>>> boot,
>>>> BIT7 of PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
>>>
>>> (3) Subject line and commit message both should not exceed 74 
>>> characters line length. (Not sure how many chars PatchCheck.py 
>>> actually enforces, I always stick with 74, following the Linux 
>>> kernel
>>> tradition.)
>>>
>>> I rewrapped the commit message here for readability.
>>>
>>>
>>>>
>>>> Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>>>> Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>>>> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>>> Cc: Justen, Jordan L
>>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>>> Cc: Kinney, Michael D
>>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>>> Cc: Wolman, Ayellet
>>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>>> Suggested-by: Wolman, Ayellet
>>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>>> Contributed-under: TianoCore Contribution Agreement 1.1
>>>> Signed-off-by: Wang, Jian J
>>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>>
>>> (4) I think this is also something that Jordan had pointed out a 
>>> long time ago (apologies if I mis-remember):
>>>
>>> The strings after the tags should form correct email addresses, and 
>>> if there are various email meta-characters in them, like "." (dot) and ","
>>> (comma), then they should be quoted, like this:
>>>
>>> Cc: "Justen, Jordan L" 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>> Cc: "Kinney, Michael D" 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>> Cc: "Wolman, Ayellet" 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Suggested-by: "Wolman, Ayellet" 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Signed-off-by: "Wang, Jian J" 
>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>>
>>> If you look at the actual addresses on the emails that have been 
>>> sent out, you can see they are all malformed. For example, I have:
>>>
>>> "Jordan L
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>" for Jordan -- the part before the comma was taken to be a separate email address (a malformed one).
>>>
>>> At least for my reply, I have fixed up the email addresses.
>>>
>>>
>>> (5) The commit message mentions BIT7 of the new PCD.
>>>
>>> First, thanks for checking Windows 7 boot (and I'm happy that I got 
>>> suspicious of the feature with regard to Windows 7). I think BIT7 is 
>>> a good feature.
>>>
>>> However, please include the short description of that feature in the 
>>> commit message -- it is one sentence; "Disable NULL pointer 
>>> detection just after EndOfDxe."
>>>
>>> (I think BIT7 is a really smart feature, and I like *how* it is used 
>>> in "NULL_DETECTION_ENABLED" below. The check means, "if the 
>>> protection is enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
>>>
>>> This doesn't mean that I like the NULL_DETECTION_ENABLED macro 
>>> itself; more on that below.)
>>>
>>>
>>>> ---
>>>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c 
>>>> b/OvmfPkg/QemuVideoDxe/Driver.c index 0dce80e59b..ee0eed7214 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>>>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>>>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>>>    PCI_TYPE00                        Pci;
>>>>    QEMU_VIDEO_CARD                   *Card;
>>>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>>>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
>>>
>>> (6) I believe I mentioned this in the earlier discussion, in some 
>>> form, but now I'll say it again:
>>>
>>> A UEFI driver has no business poking at the CPU Arch protocol. The 
>>> PI spec (1.6) states,
>>>
>>>   12.3 CPU Architectural Protocol
>>>   EFI_CPU_ARCH_PROTOCOL
>>>
>>>   Summary
>>>
>>>   Abstracts the processor services that are required to implement some
>>>   of the DXE services. This protocol must be produced by a boot service
>>>   or runtime DXE driver and may only be consumed by the DXE Foundation
>>>   and DXE drivers that produce architectural protocols.
>>>
>>> The DXE core is obviously free to use the CPU Arch protocol, but a 
>>> UEFI driver is forbidden from it, *even if* we say that, in this 
>>> UEFI driver, we are going to use DXE services. (Which come from the 
>>> PI spec, and not the UEFI spec.)
>>>
>>> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
>>>
>>> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch 
>>> protocol, by the PI spec. It is not easy to see, because the PI spec 
>>> has a formatting error in this area. If you look under 
>>> GetMemorySpaceDescriptor(), there is an error code
>>>
>>>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>>>                          architectural protocol is not available yet.
>>>
>>> Obviously this error code belongs to SetMemorySpaceAttributes(), not 
>>> GetMemorySpaceDescriptor().
>>>
>>> Anyway, gDS should be used, architectural protocols shouldn't be.
>>>
>>>
>>>>
>>>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>>>
>>>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (  #if defined
>>>> MDE_CPU_IA32 || defined MDE_CPU_X64
>>>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>>>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>>> +    //
>>>> +    // Prepare CPU arch protocol for NULL pointer detection
>>>> +    //
>>>> +    Status = gBS->LocateProtocol (
>>>> +                    &gEfiCpuArchProtocolGuid,
>>>> +                    NULL,
>>>> +                    (VOID **) &Cpu
>>>> +                    );
>>>> +    ASSERT_EFI_ERROR (Status);
>>>> +
>>>> +    DISABLE_NULL_DETECTION(Cpu);
>>>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>>> +    ENABLE_NULL_DETECTION(Cpu);
>>>
>>> (7) The NULL detection disabling and enabling should bracket the 
>>> affected code as tightly as possible.
>>>
>>> So please move this into InstallVbeShim() accordingly.
>>>
>>>
>>>>    }
>>>>  #endif
>>>>
>>>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h 
>>>> b/OvmfPkg/QemuVideoDxe/Qemu.h index 7fbb25b3ef..bb3bc6eb0f 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>>>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>>>> @@ -25,6 +25,7 @@
>>>>  #include <Protocol/PciIo.h>
>>>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>>>  #include <Protocol/DevicePath.h>
>>>> +#include <Protocol/Cpu.h>
>>>>
>>>>  #include <Library/DebugLib.h>
>>>>  #include <Library/UefiDriverEntryPoint.h> @@ -82,6 +83,21 @@ 
>>>> typedef struct {
>>>>
>>>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>>>
>>>> +//
>>>> +// VBE code will access memory between 0-4095 which will cause 
>>>> +page fault exception // if NULL pointer detection mechanism is enabled.
>>>> +Following macros can be used to // disable/enable NULL pointer detection before/after accessing those memory.
>>>> +//
>>>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>>>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>>>> +  }
>>>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>>>> +  }
>>>> +
>>>
>>> (8) I believe Jordan too commented on these macros elsewhere (under 
>>> patch 1/4).
>>>
>>> In my opinion, this functionality should be extracted into a library 
>>> class, with a library instance that is suitable for at least 
>>> UEFI_DRIVER modules. (Maybe even for DXE_DRIVER modules.)
>>>
>>> You could add a separate library instance for SMM drivers, if that 
>>> were necessary.
>>>
>>>
>>> (9) Style comment: please put one space character between the 
>>> function designator and the opening parenthesis.
>>>
>>>
>>>>  //
>>>>  // QEMU Video Private Data Structure  // diff --git 
>>>> a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> index 7c7d429bca..5d166eb99c 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> @@ -72,7 +72,9 @@
>>>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>>>> +  gEfiCpuArchProtocolGuid
>>>>
>>>>  [Pcd]
>>>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>>>> +  
>>>> + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMas
>>>> + k
>>>
>>> (10) Instead of these, the library class that I described under (8) 
>>> should be added here.
>>>
>>> Any further dependencies like PCDs, protocols etc should be 
>>> inherited by the driver through the library instance that the 
>>> platform DSC file resolves the library class to.
>>>
>>> Bonus: should you realize that the feature is impossible to 
>>> implement without accessing the CPU Arch protocol directly, you 
>>> could hide the protocol GUID dependency in the library instance INF 
>>> file, and I'd be none the wiser.
>>>
>>> ... Well, I could at least pretend that. :)
>>>
>>> Thanks,
>>> Laszlo
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>>> https://lists.01.org/mailman/listinfo/edk2-devel
>>>
> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

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

* Re: [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
  2017-09-15  6:05                           ` Wang, Jian J
@ 2017-09-15  6:28                             ` Zeng, Star
  0 siblings, 0 replies; 37+ messages in thread
From: Zeng, Star @ 2017-09-15  6:28 UTC (permalink / raw)
  To: Wang, Jian J, Laszlo Ersek, Yao, Jiewen
  Cc: Kinney, Michael D, Justen, Jordan L, edk2-devel@lists.01.org,
	Dong, Eric, Wolman, Ayellet, Zeng, Star

With this approach, please make sure to do more test, for example, check memory map change and OS boot, etc.


Thanks,
Star
-----Original Message-----
From: Wang, Jian J 
Sent: Friday, September 15, 2017 2:06 PM
To: Wang, Jian J <jian.j.wang@intel.com>; Zeng, Star <star.zeng@intel.com>; Laszlo Ersek <lersek@redhat.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

For record, we'll make following changes to address the page attributes issue:

(1) Update gDS->SetMemorySpaceAddress() to remove the filter set on page attributes
(2) Update CPU driver to sync all memory attributes including page related. No platform code changes needed.

Above changes will be submitted in a separate patch. As a result (after it's done), the related changes for this patch will be 
(3) Replace macros with functions, in which gDS->SetMemorySpaceAttributes() will be used instead of CPU arch method.


-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Wang, Jian J
Sent: Friday, September 15, 2017 8:15 AM
To: Zeng, Star <star.zeng@intel.com>; Laszlo Ersek <lersek@redhat.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

gDS-> SetMemorySpaceCapabilities() can change the Capability at any time. But I'm not sure about any side-effect of it.

-----Original Message-----
From: Zeng, Star 
Sent: Thursday, September 14, 2017 6:17 PM
To: Laszlo Ersek <lersek@redhat.com>; Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>; Zeng, Star <star.zeng@intel.com>
Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

No, I want to say even the GCD is updated to not filter page attributes, it will still not work as all the memory controller code for now are not reporting the Capability.


Thanks,
Star
-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Laszlo Ersek
Sent: Thursday, September 14, 2017 5:55 PM
To: Zeng, Star <star.zeng@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Wolman, Ayellet <ayellet.wolman@intel.com>
Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.

On 09/14/17 11:39, Zeng, Star wrote:
> There is a realistic problem I just found and want to share.
> 
> GCD database is built based on resource hob reported from PEI, and GCD 
> checks the input Attributes against Capabilities when setting 
> Attributes, but we (I just searched the whole codebase) can see there 
> is no code reporting resource hob with 
> EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE,
> EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE or 
> EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE set.
... Are you saying that, if we modify AddMemoryBaseSizeHob() in OvmfPkg/PlatformPei, to report EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE (*), then
gDS->SetMemorySpaceAttributes() will start to work?

((*) "MdePkg/Include/Pi/PiHob.h": "NOTE: Since PI spec 1.4, please use EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE as Memory capability
attribute: The memory supports being protected from processor writes")

If that's the case, then I hope Jian can include such an OvmfPkg patch in his series. :)

Thanks!
Laszlo

> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Thursday, September 14, 2017 4:54 PM
> To: Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen 
> <jiewen.yao@intel.com>
> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L 
> <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet 
> <ayellet.wolman@intel.com>; Kinney, Michael D 
> <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
> 
> On 09/14/17 10:46, Wang, Jian J wrote:
>> It’s an implementation limitation. All page attributes will be filtered out before calling CPU arch protocol to update the attributes (Gcd.c).
> 
> That cannot be a random occurrence; I'm sure there was some specific intent behind filtering out the page attributes.
> 
> Does "git blame" provide a reason, from the message of the commit that added the filtering?
> 
> Thanks,
> Laszlo
> 
>> From: Yao, Jiewen
>> Sent: Thursday, September 14, 2017 4:38 PM
>> To: Laszlo Ersek <lersek@redhat.com>; Wang, Jian J 
>> <jian.j.wang@intel.com>
>> Cc: Dong, Eric <eric.dong@intel.com>; Justen, Jordan L 
>> <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Wolman, Ayellet 
>> <ayellet.wolman@intel.com>; Kinney, Michael D 
>> <michael.d.kinney@intel.com>; Zeng, Star <star.zeng@intel.com>
>> Subject: RE: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> HI
>> I wonder if it is spec limitation or implementation limitation.
>>
>> If it is implementation limitation, we can enhance the DxeCore to allow it.
>>
>> Thank you
>> Yao Jiewen
>>
>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>> Sent: Thursday, September 14, 2017 4:30 PM
>> To: Wang, Jian J 
>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>;
>> Justen, Jordan L
>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>;
>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
>> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
>> Michael D 
>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; 
>> Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>
>> On 09/14/17 05:17, Wang, Jian J wrote:
>>> For the use of arch protocol, there's one thing I mentioned is not 
>>> accurate. I actually tried gDS->SetMemorySpaceAttributes() but it 
>>> cannot change page attributes. That's why I have to turn to cpu arch 
>>> protocol.
>> Thank you for the explanation.
>>
>> In that case, we cannot avoid violating the PI spec. I agree we can 
>> break the spec if it happens for security purposes, but in that case, 
>> I believe that hiding the implementation behind a library class is 
>> mandatory. Viewed from the spec side, accessing the CPU Arch protocol 
>> is a hack, and so it should not be spread to the source code of 
>> several driver modules.
>>
>> Thank you,
>> Laszlo
>>
>>
>>>
>>> -----Original Message-----
>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf 
>>> Of Wang, Jian J
>>> Sent: Thursday, September 14, 2017 9:17 AM
>>> To: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>> Cc: Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>;
>>> Justen, Jordan L
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>;
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Yao, Jiewen 
>>> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wolman, Ayellet 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Kinney, 
>>> Michael D 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
>>> Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>>
>>> Thanks for the comments and good advices. Sorry the format issues.
>>> This is my first patch for this project. Too many details for me to 
>>> get familiar with.
>>>
>>> (1) Sure.
>>> (2) I'll change that.
>>> (3) I'll use the tool to ensure the patch format.
>>> (4) I'll remove the ',' in name
>>> (5) I'll add more description about it.
>>> (6) You're right. I should use SetMemorySpaceAttributes() of DXE service
>>>      instead. The only reason I didn't do it is that I found
>>>       GetMemorySpaceDescriptor() doesn't return the same information
>>>      which SetMemorySpaceAttributes() just changed. So I feel using CPU
>>>     arch protocol is a bit safer. Anyway, I'll change it.
>>> (7) I did put those macros in the install function before. To reduce the
>>>      number of changed files, I made current changes. You're right it's
>>>      not worthy.
>>> (8) Using macro can help the readability, which is more important to me.
>>>     I know function can do the same. But it looks a bit heavy in this situation.
>>>     I have to admit replacing  the macros with a library is a very good idea,
>>>     which brings the same readability. I didn't think of that before. Although
>>>     Library is still a little bit heavy to me but it's in a different way, I think it
>>>     worth a trying.
>>> (9) Putting a space before open parenthesis is forced style? If so, I'll add it.
>>> (10) You're right. Using library can reduce the disturbs to affected drivers
>>>        by this feature to the minimum.
>>>
>>> -----Original Message-----
>>> From: Laszlo Ersek [mailto:lersek@redhat.com]
>>> Sent: Thursday, September 14, 2017 7:35 AM
>>> To: Wang, Jian J
>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>> Cc: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Justen, 
>>> Jordan L 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Dong, 
>>> Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Kinney, 
>>> Michael D 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>;
>>> Wolman, Ayellet
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>; Yao, 
>>> Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zeng, 
>>> Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>> Subject: Re: [edk2] [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to bypass NULL pointer detection if enabled.
>>>
>>> Hi,
>>>
>>> some of the points I'm going to make have already been pointed out 
>>> by
>>> Jordan:
>>>
>>> (1) When posting a patch series, please collect the Cc: tags from 
>>> all of the patches, and add them *all* to the cover letter. This way 
>>> everyone will get a personal copy of the general description.
>>>
>>>
>>> (2) The subject line is too long. One possible simplification:
>>>
>>> OvmfPkg/QemuVideoDxe: bypass NULL pointer detection
>>>
>>>
>>> On 09/13/17 11:25, Wang, Jian J wrote:
>>>> QemuVideoDxe driver will install VBE SHIM into page 0. If NULL 
>>>> pointer detection is enabled, page 0 must be enabled temporarily 
>>>> before installing and disabled again afterwards. For Windows 7 
>>>> boot,
>>>> BIT7 of PcdNullPointerDetectionPropertyMask must still be set to avoid hang.
>>>
>>> (3) Subject line and commit message both should not exceed 74 
>>> characters line length. (Not sure how many chars PatchCheck.py 
>>> actually enforces, I always stick with 74, following the Linux 
>>> kernel
>>> tradition.)
>>>
>>> I rewrapped the commit message here for readability.
>>>
>>>
>>>>
>>>> Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>>>> Cc: Eric Dong <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>>>> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
>>>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>>>> Cc: Justen, Jordan L
>>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>>> Cc: Kinney, Michael D
>>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>>> Cc: Wolman, Ayellet
>>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>>> Suggested-by: Wolman, Ayellet
>>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>>> Contributed-under: TianoCore Contribution Agreement 1.1
>>>> Signed-off-by: Wang, Jian J
>>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>>
>>> (4) I think this is also something that Jordan had pointed out a 
>>> long time ago (apologies if I mis-remember):
>>>
>>> The strings after the tags should form correct email addresses, and 
>>> if there are various email meta-characters in them, like "." (dot) and ","
>>> (comma), then they should be quoted, like this:
>>>
>>> Cc: "Justen, Jordan L" 
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
>>> Cc: "Kinney, Michael D" 
>>> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
>>> Cc: "Wolman, Ayellet" 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Suggested-by: "Wolman, Ayellet" 
>>> <ayellet.wolman@intel.com<mailto:ayellet.wolman@intel.com>>
>>> Signed-off-by: "Wang, Jian J" 
>>> <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
>>>
>>> If you look at the actual addresses on the emails that have been 
>>> sent out, you can see they are all malformed. For example, I have:
>>>
>>> "Jordan L
>>> <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>" for Jordan -- the part before the comma was taken to be a separate email address (a malformed one).
>>>
>>> At least for my reply, I have fixed up the email addresses.
>>>
>>>
>>> (5) The commit message mentions BIT7 of the new PCD.
>>>
>>> First, thanks for checking Windows 7 boot (and I'm happy that I got 
>>> suspicious of the feature with regard to Windows 7). I think BIT7 is 
>>> a good feature.
>>>
>>> However, please include the short description of that feature in the 
>>> commit message -- it is one sentence; "Disable NULL pointer 
>>> detection just after EndOfDxe."
>>>
>>> (I think BIT7 is a really smart feature, and I like *how* it is used 
>>> in "NULL_DETECTION_ENABLED" below. The check means, "if the 
>>> protection is enabled for DXE, and *not disabled* (== also enabled) after End-of-Dxe".
>>>
>>> This doesn't mean that I like the NULL_DETECTION_ENABLED macro 
>>> itself; more on that below.)
>>>
>>>
>>>> ---
>>>>  OvmfPkg/QemuVideoDxe/Driver.c         | 15 ++++++++++++++-
>>>>  OvmfPkg/QemuVideoDxe/Qemu.h           | 16 ++++++++++++++++
>>>>  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf |  2 ++
>>>>  3 files changed, 32 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/OvmfPkg/QemuVideoDxe/Driver.c 
>>>> b/OvmfPkg/QemuVideoDxe/Driver.c index 0dce80e59b..ee0eed7214 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/Driver.c
>>>> +++ b/OvmfPkg/QemuVideoDxe/Driver.c
>>>> @@ -194,6 +194,7 @@ QemuVideoControllerDriverStart (
>>>>    PCI_TYPE00                        Pci;
>>>>    QEMU_VIDEO_CARD                   *Card;
>>>>    EFI_PCI_IO_PROTOCOL               *ChildPciIo;
>>>> +  EFI_CPU_ARCH_PROTOCOL             *Cpu;
>>>
>>> (6) I believe I mentioned this in the earlier discussion, in some 
>>> form, but now I'll say it again:
>>>
>>> A UEFI driver has no business poking at the CPU Arch protocol. The 
>>> PI spec (1.6) states,
>>>
>>>   12.3 CPU Architectural Protocol
>>>   EFI_CPU_ARCH_PROTOCOL
>>>
>>>   Summary
>>>
>>>   Abstracts the processor services that are required to implement some
>>>   of the DXE services. This protocol must be produced by a boot service
>>>   or runtime DXE driver and may only be consumed by the DXE Foundation
>>>   and DXE drivers that produce architectural protocols.
>>>
>>> The DXE core is obviously free to use the CPU Arch protocol, but a 
>>> UEFI driver is forbidden from it, *even if* we say that, in this 
>>> UEFI driver, we are going to use DXE services. (Which come from the 
>>> PI spec, and not the UEFI spec.)
>>>
>>> Therefore, here we have to use gDS->SetMemorySpaceAttributes().
>>>
>>> The gDS->SetMemorySpaceAttributes() service depends on the CPU Arch 
>>> protocol, by the PI spec. It is not easy to see, because the PI spec 
>>> has a formatting error in this area. If you look under 
>>> GetMemorySpaceDescriptor(), there is an error code
>>>
>>>   EFI_NOT_AVAILABLE_YET  The attributes cannot be set because CPU
>>>                          architectural protocol is not available yet.
>>>
>>> Obviously this error code belongs to SetMemorySpaceAttributes(), not 
>>> GetMemorySpaceDescriptor().
>>>
>>> Anyway, gDS should be used, architectural protocols shouldn't be.
>>>
>>>
>>>>
>>>>    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
>>>>
>>>> @@ -479,7 +480,19 @@ QemuVideoControllerDriverStart (  #if defined
>>>> MDE_CPU_IA32 || defined MDE_CPU_X64
>>>>    if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||
>>>>        Private->Variant == QEMU_VIDEO_BOCHS) {
>>>> -    InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>>> +    //
>>>> +    // Prepare CPU arch protocol for NULL pointer detection
>>>> +    //
>>>> +    Status = gBS->LocateProtocol (
>>>> +                    &gEfiCpuArchProtocolGuid,
>>>> +                    NULL,
>>>> +                    (VOID **) &Cpu
>>>> +                    );
>>>> +    ASSERT_EFI_ERROR (Status);
>>>> +
>>>> +    DISABLE_NULL_DETECTION(Cpu);
>>>> +      InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
>>>> +    ENABLE_NULL_DETECTION(Cpu);
>>>
>>> (7) The NULL detection disabling and enabling should bracket the 
>>> affected code as tightly as possible.
>>>
>>> So please move this into InstallVbeShim() accordingly.
>>>
>>>
>>>>    }
>>>>  #endif
>>>>
>>>> diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h 
>>>> b/OvmfPkg/QemuVideoDxe/Qemu.h index 7fbb25b3ef..bb3bc6eb0f 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/Qemu.h
>>>> +++ b/OvmfPkg/QemuVideoDxe/Qemu.h
>>>> @@ -25,6 +25,7 @@
>>>>  #include <Protocol/PciIo.h>
>>>>  #include <Protocol/DriverSupportedEfiVersion.h>
>>>>  #include <Protocol/DevicePath.h>
>>>> +#include <Protocol/Cpu.h>
>>>>
>>>>  #include <Library/DebugLib.h>
>>>>  #include <Library/UefiDriverEntryPoint.h> @@ -82,6 +83,21 @@ 
>>>> typedef struct {
>>>>
>>>>  #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff
>>>>
>>>> +//
>>>> +// VBE code will access memory between 0-4095 which will cause 
>>>> +page fault exception // if NULL pointer detection mechanism is enabled.
>>>> +Following macros can be used to // disable/enable NULL pointer detection before/after accessing those memory.
>>>> +//
>>>> +#define NULL_DETECTION_ENABLED  ((PcdGet8(PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0)
>>>> +#define DISABLE_NULL_DETECTION(Cpu)                                             \
>>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, 0);                     \
>>>> +  }
>>>> +#define ENABLE_NULL_DETECTION(Cpu)                                              \
>>>> +  if (NULL_DETECTION_ENABLED) {                                                 \
>>>> +    (Cpu)->SetMemoryAttributes((Cpu), 0, EFI_PAGE_SIZE, EFI_MEMORY_RP);         \
>>>> +  }
>>>> +
>>>
>>> (8) I believe Jordan too commented on these macros elsewhere (under 
>>> patch 1/4).
>>>
>>> In my opinion, this functionality should be extracted into a library 
>>> class, with a library instance that is suitable for at least 
>>> UEFI_DRIVER modules. (Maybe even for DXE_DRIVER modules.)
>>>
>>> You could add a separate library instance for SMM drivers, if that 
>>> were necessary.
>>>
>>>
>>> (9) Style comment: please put one space character between the 
>>> function designator and the opening parenthesis.
>>>
>>>
>>>>  //
>>>>  // QEMU Video Private Data Structure  // diff --git 
>>>> a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> index 7c7d429bca..5d166eb99c 100644
>>>> --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
>>>> @@ -72,7 +72,9 @@
>>>>    gEfiGraphicsOutputProtocolGuid                # PROTOCOL BY_START
>>>>    gEfiDevicePathProtocolGuid                    # PROTOCOL BY_START
>>>>    gEfiPciIoProtocolGuid                         # PROTOCOL TO_START
>>>> +  gEfiCpuArchProtocolGuid
>>>>
>>>>  [Pcd]
>>>>    gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
>>>> +  
>>>> + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMas
>>>> + k
>>>
>>> (10) Instead of these, the library class that I described under (8) 
>>> should be added here.
>>>
>>> Any further dependencies like PCDs, protocols etc should be 
>>> inherited by the driver through the library instance that the 
>>> platform DSC file resolves the library class to.
>>>
>>> Bonus: should you realize that the feature is impossible to 
>>> implement without accessing the CPU Arch protocol directly, you 
>>> could hide the protocol GUID dependency in the library instance INF 
>>> file, and I'd be none the wiser.
>>>
>>> ... Well, I could at least pretend that. :)
>>>
>>> Thanks,
>>> Laszlo
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>>> https://lists.01.org/mailman/listinfo/edk2-devel
>>>
> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

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

end of thread, other threads:[~2017-09-15  6:26 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <Implement NULL pointer detection feature>
2017-09-13  9:25 ` [PATCH 0/4] Implement NULL pointer detection feature for special pool Wang, Jian J
2017-09-13  9:25   ` [PATCH 1/4] MdeModulePkg/Core: Implement NULL pointer detection in EDK-II Core Wang, Jian J
2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
2017-09-14  1:37       ` Wang, Jian J
2017-09-13 17:28     ` Jordan Justen
2017-09-14  1:25       ` Wang, Jian J
2017-09-14  6:33         ` Jordan Justen
2017-09-14  6:51           ` Wang, Jian J
2017-09-14  8:22             ` Laszlo Ersek
2017-09-13  9:25   ` [PATCH 2/4] UefiCpuPkg/PiSmmCpuDxeSmm: Implement NULL pointer detection for SMM mode code Wang, Jian J
2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
2017-09-14  1:31       ` Wang, Jian J
2017-09-13 17:31     ` Jordan Justen
2017-09-14  1:20       ` Wang, Jian J
2017-09-13  9:25   ` [PATCH 3/4] IntelFrameworkModulePkg/Csm: Update CSM code to temporarily bypass NULL pointer detection if enabled Wang, Jian J
2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
2017-09-13  9:25   ` [PATCH 4/4] OvmfPkg/QemuVideoDxe: Update QemuVideoDxe driver to " Wang, Jian J
2017-09-13 16:33     ` Johnson, Brian (EXL - Eagan)
2017-09-13 23:34     ` Laszlo Ersek
2017-09-14  1:17       ` Wang, Jian J
2017-09-14  3:17         ` Wang, Jian J
2017-09-14  8:30           ` Laszlo Ersek
2017-09-14  8:38             ` Yao, Jiewen
2017-09-14  8:46               ` Wang, Jian J
2017-09-14  8:48                 ` Yao, Jiewen
2017-09-14  8:54                 ` Laszlo Ersek
2017-09-14  9:39                   ` Zeng, Star
2017-09-14  9:55                     ` Laszlo Ersek
2017-09-14 10:16                       ` Zeng, Star
2017-09-15  0:15                         ` Wang, Jian J
2017-09-15  6:05                           ` Wang, Jian J
2017-09-15  6:28                             ` Zeng, Star
2017-09-14  8:52               ` Laszlo Ersek
2017-09-14  5:50         ` Jordan Justen
2017-09-14  6:52           ` Wang, Jian J
2017-09-14  8:26         ` Laszlo Ersek
2017-09-13  8:07 Wang, Jian J

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