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 <[email protected]>
> Cc: Eric Dong <[email protected]>
> Cc: Star Zeng <[email protected]>
> Cc: Laszlo Ersek <[email protected]>
> Cc: Justen, Jordan L <[email protected]>
> Cc: Kinney, Michael D <[email protected]>
> Cc: Wolman, Ayellet <[email protected]>
> Suggested-by: Wolman, Ayellet <[email protected]>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Wang, Jian J <[email protected]>
> ---
>  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
> 
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to