public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Zhang, Hongbin1" <hongbin1.zhang@intel.com>
To: "Ni, Ray" <ray.ni@intel.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Zeng, Star" <star.zeng@intel.com>,
	"Wu, Jiaxin" <jiaxin.wu@intel.com>,
	Sami Mujawar <sami.mujawar@arm.com>,
	Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Supreeth Venkatesh <supreeth.venkatesh@arm.com>,
	"Bu, Daocheng" <daocheng.bu@intel.com>,
	"Chen, Bo" <bo.chen@intel.com>,
	"Yao, Jiewen" <jiewen.yao@intel.com>
Subject: Re: [PATCH v1] StandaloneMmPkg: Add StandaloneMmIplPei driver.
Date: Mon, 26 Jun 2023 01:45:03 +0000	[thread overview]
Message-ID: <SA1PR11MB5826DA452306A8F0827B85B6C126A@SA1PR11MB5826.namprd11.prod.outlook.com> (raw)
In-Reply-To: <PH7PR11MB5820FD9AFBE862E362E86696C153A@PH7PR11MB5820.namprd11.prod.outlook.com>

Hi Ray,
  I have split to 5 patches with 5 commits in https://github.com/tianocore/edk2/pull/4375/ according to your suggestion.
  Please help to review it again.

Thanks,
Hongbin

-----Original Message-----
From: Zhang, Hongbin1 
Sent: Wednesday, June 7, 2023 10:37 AM
To: Yao, Jiewen <jiewen.yao@intel.com>; Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
Cc: Zeng, Star <star.zeng@intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>; Sami Mujawar <sami.mujawar@arm.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>; Supreeth Venkatesh <supreeth.venkatesh@arm.com>; Bu, Daocheng <daocheng.bu@intel.com>; Chen, Bo <bo.chen@intel.com>
Subject: RE: [PATCH v1] StandaloneMmPkg: Add StandaloneMmIplPei driver.

Thanks Jiewen.
I will change this.

-----Original Message-----
From: Yao, Jiewen <jiewen.yao@intel.com> 
Sent: Wednesday, June 7, 2023 10:31 AM
To: Zhang, Hongbin1 <hongbin1.zhang@intel.com>; Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
Cc: Zeng, Star <star.zeng@intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>; Sami Mujawar <sami.mujawar@arm.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>; Supreeth Venkatesh <supreeth.venkatesh@arm.com>; Bu, Daocheng <daocheng.bu@intel.com>; Chen, Bo <bo.chen@intel.com>
Subject: RE: [PATCH v1] StandaloneMmPkg: Add StandaloneMmIplPei driver.

> 5th patch register ReadyToBoot callback. But is it too late from security perspective? Why not lock after SMM core exit? @Yao, Jiewen

Agree with Ray. ReadyToBoot is too late.



> -----Original Message-----
> From: Zhang, Hongbin1 <hongbin1.zhang@intel.com>
> Sent: Wednesday, June 7, 2023 10:29 AM
> To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io; Yao, Jiewen
> <jiewen.yao@intel.com>
> Cc: Zeng, Star <star.zeng@intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>; Sami
> Mujawar <sami.mujawar@arm.com>; Ard Biesheuvel
> <ardb+tianocore@kernel.org>; Supreeth Venkatesh
> <supreeth.venkatesh@arm.com>; Bu, Daocheng <daocheng.bu@intel.com>;
> Chen, Bo <bo.chen@intel.com>
> Subject: RE: [PATCH v1] StandaloneMmPkg: Add StandaloneMmIplPei driver.
> 
> Thanks Ray.
> Replied your code comments with [Hongbin].
> And I will split to several patches, it will be better for reviewing.
> 
> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Wednesday, June 7, 2023 10:04 AM
> To: Zhang, Hongbin1 <hongbin1.zhang@intel.com>; devel@edk2.groups.io; Yao,
> Jiewen <jiewen.yao@intel.com>
> Cc: Zeng, Star <star.zeng@intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>; Sami
> Mujawar <sami.mujawar@arm.com>; Ard Biesheuvel
> <ardb+tianocore@kernel.org>; Supreeth Venkatesh
> <supreeth.venkatesh@arm.com>
> Subject: RE: [PATCH v1] StandaloneMmPkg: Add StandaloneMmIplPei driver.
> 
> Hongbin,
> The patch is so big. Can you please split the patch to small patches? For example:
> 1st patch only implements the Ipl entrypoint to find the correct SMRAM range
> and dump it
> 2nd patch loads SMM CORE without mode switch if sizeof (UINTN) matches
> SMM core module type.
> 3rd patch loads SMM CORE with mode switch if sizeof (UINTN) == 4 but SMM
> core module type is 64bit.
> 4th patch Deadloop() when sizeof (UINTN) == 8 but SMM core module type is
> 32bit.
> 5th patch register ReadyToBoot callback. But is it too late from security
> perspective? Why not lock after SMM core exit? @Yao, Jiewen
> 
> Back to the code content, 3 comments:
> 1. Have you tested the flow when LoadImageAtFixedAddress is enabled? If no, I
> prefer you do not add the logic at all in the first version. We can enable that
> later.
>      -- Yes, currently PcdLoadModuleAtFixAddressEnable was not used and
> verified, I will add later [Hongbin].
> 2. "EFIAPI" for GetSectionFromAnyFvByFileType should be removed. And the
> function prototype could be refined as below:
>     EFI_STATUS
>     LocateMmFvAndCore
>       OUT EFI_PHYSICAL_ADDRESS  *MmFvBaseAddress,
>       OUT VOID                  **MmCoreImageAddress
>     Please avoid directly modifying global variables inside this function.
>      -- Ok, will change that [Hongbin].
> 3. Can the StandaloneMmCore in open source be directly used with this IPL?
>      -- I will think about this later [Hongbin].
> 
> Thanks,
> Ray
> 
> 
> > -----Original Message-----
> > From: Zhang, Hongbin1 <hongbin1.zhang@intel.com>
> > Sent: Monday, May 22, 2023 1:21 PM
> > To: devel@edk2.groups.io
> > Cc: Zhang, Hongbin1 <hongbin1.zhang@intel.com>; Yao, Jiewen
> > <jiewen.yao@intel.com>; Ni, Ray <ray.ni@intel.com>; Zeng, Star
> > <star.zeng@intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>; Sami Mujawar
> > <sami.mujawar@arm.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
> > Supreeth Venkatesh <supreeth.venkatesh@arm.com>
> > Subject: [PATCH v1] StandaloneMmPkg: Add StandaloneMmIplPei driver.
> >
> > Add StandaloneMmIplPei IA32/X64 driver at PEI stage.
> > FSP will use this driver to load Standalone MM code
> > to dispatch other Standalone MM drivers.
> >
> > Signed-off-by: Hongbin1 Zhang <hongbin1.zhang@intel.com>
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Ray Ni <ray.ni@intel.com>
> > Cc: Star Zeng <star.zeng@intel.com>
> > Cc: Jiaxin Wu <jiaxin.wu@intel.com>
> > Cc: Sami Mujawar <sami.mujawar@arm.com>
> > Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> > Cc: Supreeth Venkatesh <supreeth.venkatesh@arm.com>
> > ---
> >  StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c     |
> 456
> > ++++++++++++
> >  StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c   |
> 787
> > ++++++++++++++++++++
> >  StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c      |
> 32 +
> >  StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm  |
> 148
> > ++++
> >  StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h   |  66
> > ++
> >  StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf |
> 75
> > ++
> >  StandaloneMmPkg/StandaloneMmPkg.ci.yaml                           |   4 +-
> >  StandaloneMmPkg/StandaloneMmPkg.dsc                               |  15 +-
> >  UefiPayloadPkg/UniversalPayloadBuild.sh                           |  34 +-
> >  edksetup.sh                                                       | 294 ++++----
> >  10 files changed, 1744 insertions(+), 167 deletions(-)
> >
> > diff --git
> > a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c
> > b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c
> > new file mode 100644
> > index 0000000000..d6174d73a3
> > --- /dev/null
> > +++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/LoadSmmCore.c
> > @@ -0,0 +1,456 @@
> > +/** @file
> > +  SMM IPL that load the SMM Core into SMRAM
> > +
> > +  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <PiPei.h>
> > +#include <PiSmm.h>
> > +#include <StandaloneMm.h>
> > +#include <Library/HobLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/MemoryAllocationLib.h>
> > +#include <StandaloneMmIplPei.h>
> > +
> > +#pragma pack(1)
> > +
> > +//
> > +// Page-Map Level-4 Offset (PML4) and
> > +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
> > +//
> > +
> > +typedef union {
> > +  struct {
> > +    UINT64    Present              : 1;   // 0 = Not present in memory, 1 = Present in
> > memory
> > +    UINT64    ReadWrite            : 1;   // 0 = Read-Only, 1= Read/Write
> > +    UINT64    UserSupervisor       : 1;   // 0 = Supervisor, 1=User
> > +    UINT64    WriteThrough         : 1;   // 0 = Write-Back caching, 1=Write-
> Through
> > caching
> > +    UINT64    CacheDisabled        : 1;   // 0 = Cached, 1=Non-Cached
> > +    UINT64    Accessed             : 1;   // 0 = Not accessed, 1 = Accessed (set by
> CPU)
> > +    UINT64    Reserved             : 1;   // Reserved
> > +    UINT64    MustBeZero           : 2;   // Must Be Zero
> > +    UINT64    Available            : 3;   // Available for use by system software
> > +    UINT64    PageTableBaseAddress : 40;  // Page Table Base Address
> > +    UINT64    AvailableHigh        : 11;  // Available for use by system software
> > +    UINT64    Nx                   : 1;   // No Execute bit
> > +  } Bits;
> > +  UINT64    Uint64;
> > +} PAGE_MAP_AND_DIRECTORY_POINTER;
> > +
> > +//
> > +// Page Table Entry 2MB
> > +//
> > +typedef union {
> > +  struct {
> > +    UINT64    Present              : 1;   // 0 = Not present in memory, 1 = Present in
> > memory
> > +    UINT64    ReadWrite            : 1;   // 0 = Read-Only, 1= Read/Write
> > +    UINT64    UserSupervisor       : 1;   // 0 = Supervisor, 1=User
> > +    UINT64    WriteThrough         : 1;   // 0 = Write-Back caching, 1=Write-
> Through
> > caching
> > +    UINT64    CacheDisabled        : 1;   // 0 = Cached, 1=Non-Cached
> > +    UINT64    Accessed             : 1;   // 0 = Not accessed, 1 = Accessed (set by
> CPU)
> > +    UINT64    Dirty                : 1;   // 0 = Not Dirty, 1 = written by processor on
> > access to page
> > +    UINT64    MustBe1              : 1;   // Must be 1
> > +    UINT64    Global               : 1;   // 0 = Not global page, 1 = global page TLB
> not
> > cleared on CR3 write
> > +    UINT64    Available            : 3;   // Available for use by system software
> > +    UINT64    Pat                  : 1;   //
> > +    UINT64    MustBeZero           : 8;   // Must be zero
> > +    UINT64    PageTableBaseAddress : 31;  // Page Table Base Address
> > +    UINT64    AvailableHigh        : 11;  // Available for use by system software
> > +    UINT64    Nx                   : 1;   // 0 = Execute Code, 1 = No Code Execution
> > +  } Bits;
> > +  UINT64    Uint64;
> > +} PAGE_TABLE_ENTRY;
> > +
> > +//
> > +// Page Table Entry 1GB
> > +//
> > +typedef union {
> > +  struct {
> > +    UINT64    Present              : 1;   // 0 = Not present in memory, 1 = Present in
> > memory
> > +    UINT64    ReadWrite            : 1;   // 0 = Read-Only, 1= Read/Write
> > +    UINT64    UserSupervisor       : 1;   // 0 = Supervisor, 1=User
> > +    UINT64    WriteThrough         : 1;   // 0 = Write-Back caching, 1=Write-
> Through
> > caching
> > +    UINT64    CacheDisabled        : 1;   // 0 = Cached, 1=Non-Cached
> > +    UINT64    Accessed             : 1;   // 0 = Not accessed, 1 = Accessed (set by
> CPU)
> > +    UINT64    Dirty                : 1;   // 0 = Not Dirty, 1 = written by processor on
> > access to page
> > +    UINT64    MustBe1              : 1;   // Must be 1
> > +    UINT64    Global               : 1;   // 0 = Not global page, 1 = global page TLB
> not
> > cleared on CR3 write
> > +    UINT64    Available            : 3;   // Available for use by system software
> > +    UINT64    Pat                  : 1;   //
> > +    UINT64    MustBeZero           : 17;  // Must be zero;
> > +    UINT64    PageTableBaseAddress : 22;  // Page Table Base Address
> > +    UINT64    AvailableHigh        : 11;  // Available for use by system software
> > +    UINT64    Nx                   : 1;   // 0 = Execute Code, 1 = No Code Execution
> > +  } Bits;
> > +  UINT64    Uint64;
> > +} PAGE_TABLE_1G_ENTRY;
> > +
> > +#pragma pack()
> > +
> > +//
> > +// Global Descriptor Table (GDT)
> > +//
> > +GLOBAL_REMOVE_IF_UNREFERENCED IA32_SEGMENT_DESCRIPTOR
> > mGdtEntries[] = {
> > +  /* selector { Global Segment Descriptor                              } */
> > +  /* 0x00 */ {
> > +    { 0,      0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0, 0 }
> > +  },                                                                      // null descriptor
> > +  /* 0x08 */ {
> > +    { 0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }
> > +  },                                                                      // linear data segment descriptor
> > +  /* 0x10 */ {
> > +    { 0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }
> > +  },                                                                      // linear code segment descriptor
> > +  /* 0x18 */ {
> > +    { 0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }
> > +  },                                                                      // system data segment descriptor
> > +  /* 0x20 */ {
> > +    { 0xffff, 0, 0, 0xb, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }
> > +  },                                                                      // system code segment descriptor
> > +  /* 0x28 */ {
> > +    { 0,      0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0, 0 }
> > +  },                                                                      // spare segment descriptor
> > +  /* 0x30 */ {
> > +    { 0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }
> > +  },                                                                      // system data segment descriptor
> > +  /* 0x38 */ {
> > +    { 0xffff, 0, 0, 0xb, 1, 0, 1, 0xf, 0, 1, 0, 1, 0 }
> > +  },                                                                      // system code segment descriptor
> > +  /* 0x40 */ {
> > +    { 0,      0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0, 0 }
> > +  },                                                                      // spare segment descriptor
> > +};
> > +
> > +//
> > +// IA32 Gdt register
> > +//
> > +GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR  mGdt = {
> > +  sizeof (mGdtEntries) - 1,
> > +  (UINTN)mGdtEntries
> > +};
> > +
> > +/**
> > +  Calculate the total size of page table.
> > +
> > +  @return The size of page table.
> > +
> > +**/
> > +UINTN
> > +CalculatePageTableSize (
> > +  VOID
> > +  )
> > +{
> > +  UINT32   RegEax;
> > +  UINT32   RegEdx;
> > +  UINTN    TotalPagesNum;
> > +  UINT8    PhysicalAddressBits;
> > +  VOID     *Hob;
> > +  UINT32   NumberOfPml4EntriesNeeded;
> > +  UINT32   NumberOfPdpEntriesNeeded;
> > +  BOOLEAN  Page1GSupport;
> > +
> > +  Page1GSupport = FALSE;
> > +  if (PcdGetBool (PcdUse1GPageTable)) {
> > +    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
> > +    if (RegEax >= 0x80000001) {
> > +      AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
> > +      if ((RegEdx & BIT26) != 0) {
> > +        Page1GSupport = TRUE;
> > +      }
> > +    }
> > +  }
> > +
> > +  //
> > +  // Get physical address bits supported.
> > +  //
> > +  Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
> > +  if (Hob != NULL) {
> > +    PhysicalAddressBits = ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace;
> > +  } else {
> > +    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
> > +    if (RegEax >= 0x80000008) {
> > +      AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
> > +      PhysicalAddressBits = (UINT8)RegEax;
> > +    } else {
> > +      PhysicalAddressBits = 36;
> > +    }
> > +  }
> > +
> > +  //
> > +  // IA-32e paging translates 48-bit linear addresses to 52-bit physical
> addresses.
> > +  //
> > +  ASSERT (PhysicalAddressBits <= 52);
> > +  if (PhysicalAddressBits > 48) {
> > +    PhysicalAddressBits = 48;
> > +  }
> > +
> > +  //
> > +  // Calculate the table entries needed.
> > +  //
> > +  if (PhysicalAddressBits <= 39 ) {
> > +    NumberOfPml4EntriesNeeded = 1;
> > +    NumberOfPdpEntriesNeeded  = (UINT32)LShiftU64 (1, (PhysicalAddressBits
> -
> > 30));
> > +  } else {
> > +    NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits
> -
> > 39));
> > +    NumberOfPdpEntriesNeeded  = 512;
> > +  }
> > +
> > +  if (!Page1GSupport) {
> > +    TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) *
> > NumberOfPml4EntriesNeeded + 1;
> > +  } else {
> > +    TotalPagesNum = NumberOfPml4EntriesNeeded + 1;
> > +  }
> > +
> > +  return EFI_PAGES_TO_SIZE (TotalPagesNum);
> > +}
> > +
> > +/**
> > +  Allocates and fills in the Page Directory and Page Table Entries to
> > +  establish a 1:1 Virtual to Physical mapping.
> > +
> > +  @param[in]  PageTablesAddress  The base address of page table.
> > +
> > +**/
> > +VOID
> > +CreateIdentityMappingPageTables (
> > +  IN  EFI_PHYSICAL_ADDRESS  PageTablesAddress
> > +  )
> > +{
> > +  UINT32                          RegEax;
> > +  UINT32                          RegEdx;
> > +  UINT8                           PhysicalAddressBits;
> > +  EFI_PHYSICAL_ADDRESS            PageAddress;
> > +  UINTN                           IndexOfPml4Entries;
> > +  UINTN                           IndexOfPdpEntries;
> > +  UINTN                           IndexOfPageDirectoryEntries;
> > +  UINT32                          NumberOfPml4EntriesNeeded;
> > +  UINT32                          NumberOfPdpEntriesNeeded;
> > +  PAGE_MAP_AND_DIRECTORY_POINTER  *PageMapLevel4Entry;
> > +  PAGE_MAP_AND_DIRECTORY_POINTER  *PageMap;
> > +  PAGE_MAP_AND_DIRECTORY_POINTER  *PageDirectoryPointerEntry;
> > +  PAGE_TABLE_ENTRY                *PageDirectoryEntry;
> > +  UINTN                           BigPageAddress;
> > +  VOID                            *Hob;
> > +  BOOLEAN                         Page1GSupport;
> > +  PAGE_TABLE_1G_ENTRY             *PageDirectory1GEntry;
> > +
> > +  Page1GSupport = FALSE;
> > +  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
> > +  if (RegEax >= 0x80000001) {
> > +    AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
> > +    if ((RegEdx & BIT26) != 0) {
> > +      Page1GSupport = TRUE;
> > +    }
> > +  }
> > +
> > +  //
> > +  // Get physical address bits supported.
> > +  //
> > +  Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
> > +  if (Hob != NULL) {
> > +    PhysicalAddressBits = ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace;
> > +  } else {
> > +    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
> > +    if (RegEax >= 0x80000008) {
> > +      AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
> > +      PhysicalAddressBits = (UINT8)RegEax;
> > +    } else {
> > +      PhysicalAddressBits = 36;
> > +    }
> > +  }
> > +
> > +  //
> > +  // IA-32e paging translates 48-bit linear addresses to 52-bit physical
> addresses.
> > +  //
> > +  ASSERT (PhysicalAddressBits <= 52);
> > +  if (PhysicalAddressBits > 48) {
> > +    PhysicalAddressBits = 48;
> > +  }
> > +
> > +  //
> > +  // Calculate the table entries needed.
> > +  //
> > +  if (PhysicalAddressBits <= 39 ) {
> > +    NumberOfPml4EntriesNeeded = 1;
> > +    NumberOfPdpEntriesNeeded  = (UINT32)LShiftU64 (1, (PhysicalAddressBits
> -
> > 30));
> > +  } else {
> > +    NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits
> -
> > 39));
> > +    NumberOfPdpEntriesNeeded  = 512;
> > +  }
> > +
> > +  //
> > +  // Pre-allocate big pages to avoid later allocations.
> > +  //
> > +  BigPageAddress = (UINTN)PageTablesAddress;
> > +
> > +  //
> > +  // By architecture only one PageMapLevel4 exists - so lets allocate storage
> for
> > it.
> > +  //
> > +  PageMap         = (VOID *)BigPageAddress;
> > +  BigPageAddress += SIZE_4KB;
> > +
> > +  PageMapLevel4Entry = PageMap;
> > +  PageAddress        = 0;
> > +  for (IndexOfPml4Entries = 0; IndexOfPml4Entries <
> > NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++)
> {
> > +    //
> > +    // Each PML4 entry points to a page of Page Directory Pointer entires.
> > +    // So lets allocate space for them and fill them in in the IndexOfPdpEntries
> > loop.
> > +    //
> > +    PageDirectoryPointerEntry = (VOID *)BigPageAddress;
> > +    BigPageAddress           += SIZE_4KB;
> > +
> > +    //
> > +    // Make a PML4 Entry
> > +    //
> > +    PageMapLevel4Entry->Uint64         =
> > (UINT64)(UINTN)PageDirectoryPointerEntry;
> > +    PageMapLevel4Entry->Bits.ReadWrite = 1;
> > +    PageMapLevel4Entry->Bits.Present   = 1;
> > +
> > +    if (Page1GSupport) {
> > +      PageDirectory1GEntry = (VOID *)PageDirectoryPointerEntry;
> > +
> > +      for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512;
> > IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress +=
> > SIZE_1GB) {
> > +        //
> > +        // Fill in the Page Directory entries
> > +        //
> > +        PageDirectory1GEntry->Uint64         = (UINT64)PageAddress;
> > +        PageDirectory1GEntry->Bits.ReadWrite = 1;
> > +        PageDirectory1GEntry->Bits.Present   = 1;
> > +        PageDirectory1GEntry->Bits.MustBe1   = 1;
> > +      }
> > +    } else {
> > +      for (IndexOfPdpEntries = 0; IndexOfPdpEntries <
> > NumberOfPdpEntriesNeeded; IndexOfPdpEntries++,
> > PageDirectoryPointerEntry++) {
> > +        //
> > +        // Each Directory Pointer entries points to a page of Page Directory
> entires.
> > +        // So allocate space for them and fill them in in the
> > IndexOfPageDirectoryEntries loop.
> > +        //
> > +        PageDirectoryEntry = (VOID *)BigPageAddress;
> > +        BigPageAddress    += SIZE_4KB;
> > +
> > +        //
> > +        // Fill in a Page Directory Pointer Entries
> > +        //
> > +        PageDirectoryPointerEntry->Uint64         =
> > (UINT64)(UINTN)PageDirectoryEntry;
> > +        PageDirectoryPointerEntry->Bits.ReadWrite = 1;
> > +        PageDirectoryPointerEntry->Bits.Present   = 1;
> > +
> > +        for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512;
> > IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress +=
> > SIZE_2MB) {
> > +          //
> > +          // Fill in the Page Directory entries
> > +          //
> > +          PageDirectoryEntry->Uint64         = (UINT64)PageAddress;
> > +          PageDirectoryEntry->Bits.ReadWrite = 1;
> > +          PageDirectoryEntry->Bits.Present   = 1;
> > +          PageDirectoryEntry->Bits.MustBe1   = 1;
> > +        }
> > +      }
> > +
> > +      for ( ; IndexOfPdpEntries < 512; IndexOfPdpEntries++,
> > PageDirectoryPointerEntry++) {
> > +        ZeroMem (
> > +          PageDirectoryPointerEntry,
> > +          sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
> > +          );
> > +      }
> > +    }
> > +  }
> > +
> > +  //
> > +  // For the PML4 entries we are not using fill in a null entry.
> > +  //
> > +  for ( ; IndexOfPml4Entries < 512; IndexOfPml4Entries++,
> > PageMapLevel4Entry++) {
> > +    ZeroMem (
> > +      PageMapLevel4Entry,
> > +      sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
> > +      );
> > +  }
> > +}
> > +
> > +/**
> > +  If in 32 bit protection mode, and coalesce image is of X64, switch to long
> mode.
> > +
> > +  @param  Entry                     Entry of Standalone MM Foundation.
> > +  @param  Context1                  A pointer to the context to pass into the
> > EntryPoint
> > +                                    function.
> > +  @param  Context2                  A pointer to the context to pass into the
> > EntryPoint
> > +                                    function.
> > +  @retval EFI_SUCCESS               Successfully switched to long mode and
> execute
> > coalesce.
> > +  @retval Others                    Failed to execute coalesce in long mode.
> > +
> > +**/
> > +EFI_STATUS
> > +ModeSwitch (
> > +  IN EFI_PHYSICAL_ADDRESS  Entry,
> > +  IN VOID                  *Context1,
> > +  IN VOID                  *Context2
> > +  )
> > +{
> > +  UINTN            PageTableAddress;
> > +  UINTN            PageTableSize;
> > +  EFI_STATUS       Status;
> > +  IA32_DESCRIPTOR  Gdtr;
> > +
> > +  DEBUG ((DEBUG_INFO, "ModeSwitch\n"));
> > +
> > +  //
> > +  // Save IA32 GDTR
> > +  //
> > +  AsmReadGdtr (&Gdtr);
> > +
> > +  //
> > +  // Set X64 GDTR
> > +  //
> > +  AsmWriteGdtr (&mGdt);
> > +
> > +  PageTableAddress = AsmReadCr3 () & 0xFFFFF000;
> > +
> > +  //
> > +  // If page table was created, no need to create
> > +  //
> > +  if (PageTableAddress == 0) {
> > +    PageTableSize = CalculatePageTableSize ();
> > +
> > +    PageTableAddress = (UINTN)AllocatePages (EFI_SIZE_TO_PAGES
> > (PageTableSize));
> > +    ASSERT (PageTableAddress != 0);
> > +
> > +    CreateIdentityMappingPageTables (PageTableAddress);
> > +
> > +    AsmWriteCr3 ((UINTN)PageTableAddress);
> > +  }
> > +
> > +  DEBUG ((DEBUG_INFO, "AsmExecute64BitCode ...\n"));
> > +
> > +  Status = AsmExecute64BitCode (Entry, (UINT64)(UINTN)Context1,
> > (UINT64)(UINTN)Context2, NULL);
> > +  if (Status != 0) {
> > +    Status = Status | MAX_BIT;
> > +  }
> > +
> > +  DEBUG ((DEBUG_INFO, "AsmExecute64BitCode - %r\n", Status));
> > +
> > +  //
> > +  // Restore IA32 GDTR
> > +  //
> > +  AsmWriteGdtr (&Gdtr);
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Load SMM core to dispatch other Standalone MM drivers.
> > +
> > +  @param  Entry                     Entry of Standalone MM Foundation.
> > +  @param  Context1                  A pointer to the context to pass into the
> > EntryPoint
> > +                                    function.
> > +  @retval EFI_SUCCESS               Successfully loaded SMM core.
> > +  @retval Others                    Failed to load SMM core.
> > +**/
> > +EFI_STATUS
> > +LoadSmmCore (
> > +  IN EFI_PHYSICAL_ADDRESS  Entry,
> > +  IN VOID                  *Context1
> > +  )
> > +{
> > +  return ModeSwitch (Entry, Context1, NULL);
> > +}
> > diff --git
> > a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
> > b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
> > new file mode 100644
> > index 0000000000..7fa42c32fb
> > --- /dev/null
> > +++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
> > @@ -0,0 +1,787 @@
> > +/** @file
> > +  SMM IPL that load the SMM Core into SMRAM at PEI stage
> > +
> > +  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <PiPei.h>
> > +#include <PiSmm.h>
> > +#include <Ppi/SmmAccess.h>
> > +#include <Ppi/SmmControl.h>
> > +#include <Library/BaseLib.h>
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/PeCoffLib.h>
> > +#include <Library/CacheMaintenanceLib.h>
> > +#include <Library/MemoryAllocationLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Library/PeiServicesTablePointerLib.h>
> > +#include <Library/PeiServicesLib.h>
> > +#include <Library/HobLib.h>
> > +#include <Library/PcdLib.h>
> > +#include <Guid/SmramMemoryReserve.h>
> > +#include <Guid/MmCoreData.h>
> > +#include <StandaloneMmIplPei.h>
> > +
> > +//
> > +// MM Core Private Data structure that contains the data shared between
> > +// the SMM IPL and the Standalone MM Core.
> > +//
> > +MM_CORE_PRIVATE_DATA  mMmCorePrivateData = {
> > +  MM_CORE_PRIVATE_DATA_SIGNATURE,     // Signature
> > +  0,                                  // MmramRangeCount
> > +  0,                                  // MmramRanges
> > +  0,                                  // MmEntryPoint
> > +  FALSE,                              // MmEntryPointRegistered
> > +  FALSE,                              // InMm
> > +  0,                                  // Mmst
> > +  0,                                  // CommunicationBuffer
> > +  0,                                  // BufferSize
> > +  EFI_SUCCESS,                        // ReturnStatus
> > +  0,                                  // MmCoreImageBase
> > +  0,                                  // MmCoreImageSize
> > +  0,                                  // MmCoreEntryPoint
> > +  0,                                  // StandaloneBfvAddress
> > +};
> > +
> > +//
> > +// Global pointer used to access mMmCorePrivateData from outside and
> inside
> > SMM
> > +//
> > +MM_CORE_PRIVATE_DATA  *gMmCorePrivate;
> > +
> > +//
> > +// SMM IPL global variables
> > +//
> > +PEI_SMM_ACCESS_PPI    *mSmmAccess;
> > +EFI_SMRAM_DESCRIPTOR  *mCurrentSmramRange;
> > +BOOLEAN               mSmmLocked = FALSE;
> > +EFI_PHYSICAL_ADDRESS  mSmramCacheBase;
> > +UINT64                mSmramCacheSize;
> > +
> > +EFI_PEI_NOTIFY_DESCRIPTOR  mReadyToBootNotifyList = {
> > +  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> > +  &gEfiEventReadyToBootGuid,
> > +  ReadyToBootEvent
> > +};
> > +
> > +/**
> > +  This is the callback function on ready to boot.
> > +
> > +  Close and Lock smram range on ready to boot stage.
> > +
> > +  @param   PeiServices          General purpose services available to every PEIM.
> > +  @param   NotifyDescriptor     The notification structure this PEIM registered
> on
> > install.
> > +  @param   Ppi                  Pointer to the PPI data associated with this function.
> > +  @retval  EFI_SUCCESS          Close and lock smram ranges successfully.
> > +  @retval  Other                Close and lock smram ranges failed.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +ReadyToBootEvent (
> > +  IN  EFI_PEI_SERVICES           **PeiServices,
> > +  IN  EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
> > +  IN  VOID                       *Ppi
> > +  )
> > +{
> > +  EFI_STATUS  Status;
> > +
> > +  //
> > +  // Close all SMRAM ranges
> > +  //
> > +  Status = mSmmAccess->Close ((EFI_PEI_SERVICES **)PeiServices,
> > mSmmAccess, 0);
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  //
> > +  // Lock all SMRAM ranges
> > +  //
> > +  Status = mSmmAccess->Lock ((EFI_PEI_SERVICES **)PeiServices,
> > mSmmAccess, 0);
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Find the maximum SMRAM cache range that covers the range specified by
> > SmramRange.
> > +
> > +  This function searches and joins all adjacent ranges of SmramRange into a
> > range to be cached.
> > +
> > +  @param   SmramRange       The SMRAM range to search from.
> > +  @param   SmramCacheBase   The returned cache range base.
> > +  @param   SmramCacheSize   The returned cache range size.
> > +**/
> > +VOID
> > +GetSmramCacheRange (
> > +  IN  EFI_SMRAM_DESCRIPTOR  *SmramRange,
> > +  OUT EFI_PHYSICAL_ADDRESS  *SmramCacheBase,
> > +  OUT UINT64                *SmramCacheSize
> > +  )
> > +{
> > +  UINTN                 Index;
> > +  EFI_PHYSICAL_ADDRESS  RangeCpuStart;
> > +  UINT64                RangePhysicalSize;
> > +  BOOLEAN               FoundAdjacentRange;
> > +  EFI_SMRAM_DESCRIPTOR  *SmramRanges;
> > +
> > +  *SmramCacheBase = SmramRange->CpuStart;
> > +  *SmramCacheSize = SmramRange->PhysicalSize;
> > +
> > +  SmramRanges = (EFI_SMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate-
> > >MmramRanges;
> > +  do {
> > +    FoundAdjacentRange = FALSE;
> > +    for (Index = 0; Index < gMmCorePrivate->MmramRangeCount; Index++) {
> > +      RangeCpuStart     = SmramRanges[Index].CpuStart;
> > +      RangePhysicalSize = SmramRanges[Index].PhysicalSize;
> > +      if ((RangeCpuStart < *SmramCacheBase) && (*SmramCacheBase ==
> > (RangeCpuStart + RangePhysicalSize))) {
> > +        *SmramCacheBase    = RangeCpuStart;
> > +        *SmramCacheSize   += RangePhysicalSize;
> > +        FoundAdjacentRange = TRUE;
> > +      } else if (((*SmramCacheBase + *SmramCacheSize) == RangeCpuStart) &&
> > (RangePhysicalSize > 0)) {
> > +        *SmramCacheSize   += RangePhysicalSize;
> > +        FoundAdjacentRange = TRUE;
> > +      }
> > +    }
> > +  } while (FoundAdjacentRange);
> > +}
> > +
> > +/**
> > +  Get the fixed loading address from image header assigned by build tool. This
> > function only be called
> > +  when Loading module at Fixed address feature enabled.
> > +
> > +  @param  ImageContext              Pointer to the image context structure that
> > describes the PE/COFF
> > +                                    image that needs to be examined by this function.
> > +  @retval EFI_SUCCESS               An fixed loading address is assigned to this
> image
> > by build tools .
> > +  @retval EFI_NOT_FOUND             The image has no assigned fixed loading
> > address.
> > +**/
> > +EFI_STATUS
> > +GetPeCoffImageFixLoadingAssignedAddress (
> > +  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
> > +  )
> > +{
> > +  UINTN                            SectionHeaderOffset;
> > +  EFI_STATUS                       Status;
> > +  EFI_IMAGE_SECTION_HEADER         SectionHeader;
> > +  EFI_IMAGE_OPTIONAL_HEADER_UNION  *ImgHdr;
> > +  EFI_PHYSICAL_ADDRESS             FixLoadingAddress;
> > +  UINT16                           Index;
> > +  UINTN                            Size;
> > +  UINT16                           NumberOfSections;
> > +  EFI_PHYSICAL_ADDRESS             SmramBase;
> > +  UINT64                           SmmCodeSize;
> > +  UINT64                           ValueInSectionHeader;
> > +
> > +  //
> > +  // Build tool will calculate the smm code size and then patch the
> > PcdLoadFixAddressSmmCodePageNumber
> > +  //
> > +  SmmCodeSize       = EFI_PAGES_TO_SIZE (PcdGet32
> > (PcdLoadFixAddressSmmCodePageNumber));
> > +  FixLoadingAddress = 0;
> > +  Status            = EFI_NOT_FOUND;
> > +  SmramBase         = mCurrentSmramRange->CpuStart;
> > +  //
> > +  // Get PeHeader pointer
> > +  //
> > +  ImgHdr              = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8
> > *)ImageContext->Handle + ImageContext->PeCoffHeaderOffset);
> > +  SectionHeaderOffset = (UINTN)(
> > +                                ImageContext->PeCoffHeaderOffset +
> > +                                sizeof (UINT32) +
> > +                                sizeof (EFI_IMAGE_FILE_HEADER) +
> > +                                ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
> > +                                );
> > +  NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
> > +
> > +  //
> > +  // Get base address from the first section header that doesn't point to code
> > section.
> > +  //
> > +  for (Index = 0; Index < NumberOfSections; Index++) {
> > +    //
> > +    // Read section header from file
> > +    //
> > +    Size   = sizeof (EFI_IMAGE_SECTION_HEADER);
> > +    Status = ImageContext->ImageRead (
> > +                             ImageContext->Handle,
> > +                             SectionHeaderOffset,
> > +                             &Size,
> > +                             &SectionHeader
> > +                             );
> > +    if (EFI_ERROR (Status)) {
> > +      return Status;
> > +    }
> > +
> > +    Status = EFI_NOT_FOUND;
> > +
> > +    if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
> > +      //
> > +      // Build tool saves the offset to SMRAM base as image base in
> > PointerToRelocations & PointerToLineNumbers fields in the
> > +      // first section header that doesn't point to code section in image header.
> > And there is an assumption that when the
> > +      // feature is enabled, if a module is assigned a loading address by tools,
> > PointerToRelocations & PointerToLineNumbers
> > +      // fields should NOT be Zero, or else, these 2 fields should be set to Zero
> > +      //
> > +      ValueInSectionHeader = ReadUnaligned64 ((UINT64
> > *)&SectionHeader.PointerToRelocations);
> > +      if (ValueInSectionHeader != 0) {
> > +        //
> > +        // Found first section header that doesn't point to code section in which
> > build tool saves the
> > +        // offset to SMRAM base as image base in PointerToRelocations &
> > PointerToLineNumbers fields
> > +        //
> > +        FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(SmramBase +
> > (INT64)ValueInSectionHeader);
> > +
> > +        if ((SmramBase + SmmCodeSize > FixLoadingAddress) && (SmramBase <=
> > FixLoadingAddress)) {
> > +          //
> > +          // The assigned address is valid. Return the specified loading address
> > +          //
> > +          ImageContext->ImageAddress = FixLoadingAddress;
> > +          Status                     = EFI_SUCCESS;
> > +        }
> > +      }
> > +
> > +      break;
> > +    }
> > +
> > +    SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
> > +  }
> > +
> > +  DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO:
> > Loading module at fixed address %x, Status = %r \n", FixLoadingAddress,
> Status));
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Searches all the available firmware volumes and returns the first matching
> FFS
> > section.
> > +
> > +  This function searches all the firmware volumes for FFS files with FV file type
> > specified by FileType
> > +  The order that the firmware volumes is searched is not deterministic. For
> each
> > available FV a search
> > +  is made for FFS file of type FileType. If the FV contains more than one FFS
> file
> > with the same FileType,
> > +  the FileInstance instance will be the matched FFS file. For each FFS file found
> a
> > search
> > +  is made for FFS sections of type SectionType. If the FFS file contains at least
> > SectionInstance instances
> > +  of the FFS section specified by SectionType, then the SectionInstance
> instance
> > is returned in Buffer.
> > +  Buffer is allocated using AllocatePool(), and the size of the allocated buffer
> is
> > returned in Size.
> > +  It is the caller's responsibility to use FreePool() to free the allocated buffer.
> > +
> > +  If Buffer is NULL, then ASSERT().
> > +  If Size is NULL, then ASSERT().
> > +
> > +  @param  FileType             Indicates the FV file type to search for within all
> > available FVs.
> > +  @param  FileInstance         Indicates which file instance within all available
> FVs
> > specified by FileType.
> > +                               FileInstance starts from zero.
> > +  @param  SectionType          Indicates the FFS section type to search for
> within
> > the FFS file
> > +                               specified by FileType with FileInstance.
> > +  @param  SectionInstance      Indicates which section instance within the FFS
> > file
> > +                               specified by FileType with FileInstance to retrieve.
> > SectionInstance starts from zero.
> > +  @param  Buffer               On output, a pointer to a callee allocated buffer
> > containing the FFS file section that was found.
> > +                               Is it the caller's responsibility to free this buffer using
> > FreePool().
> > +  @param  Size                 On output, a pointer to the size, in bytes, of Buffer.
> > +
> > +  @retval  EFI_SUCCESS          The specified FFS section was returned.
> > +  @retval  EFI_NOT_FOUND        The specified FFS section could not be found.
> > +  @retval  EFI_OUT_OF_RESOURCES There are not enough resources
> available
> > to retrieve the matching FFS section.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +GetSectionFromAnyFvByFileType  (
> > +  IN  EFI_FV_FILETYPE   FileType,
> > +  IN  UINTN             FileInstance,
> > +  IN  EFI_SECTION_TYPE  SectionType,
> > +  IN  UINTN             SectionInstance,
> > +  OUT VOID              **Buffer,
> > +  OUT UINTN             *Size
> > +  )
> > +{
> > +  EFI_STATUS           Status;
> > +  UINTN                FvIndex;
> > +  EFI_PEI_FV_HANDLE    VolumeHandle;
> > +  EFI_PEI_FILE_HANDLE  FileHandle;
> > +  EFI_PE32_SECTION     *SectionData;
> > +  UINT32               SectionSize;
> > +
> > +  //
> > +  // Search all FV
> > +  //
> > +  VolumeHandle = NULL;
> > +  for (FvIndex = 0; ; FvIndex++) {
> > +    Status = PeiServicesFfsFindNextVolume (FvIndex, &VolumeHandle);
> > +    if (EFI_ERROR (Status)) {
> > +      break;
> > +    }
> > +
> > +    //
> > +    // Search PEIM FFS
> > +    //
> > +    FileHandle = NULL;
> > +    Status     = PeiServicesFfsFindNextFile (FileType, VolumeHandle,
> &FileHandle);
> > +    if (EFI_ERROR (Status)) {
> > +      continue;
> > +    }
> > +
> > +    //
> > +    // Search Section
> > +    //
> > +    SectionData = NULL;
> > +    Status      = PeiServicesFfsFindSectionData (SectionType, FileHandle, Buffer);
> > +    if (EFI_ERROR (Status)) {
> > +      continue;
> > +    }
> > +
> > +    //
> > +    // Great!
> > +    //
> > +    SectionData = (EFI_PE32_SECTION *)((UINT8 *)*Buffer - sizeof
> > (EFI_PE32_SECTION));
> > +    ASSERT (SectionData->Type == SectionType);
> > +    SectionSize  = *(UINT32 *)SectionData->Size;
> > +    SectionSize &= 0xFFFFFF;
> > +    *Size        = SectionSize - sizeof (EFI_PE32_SECTION);
> > +
> > +    if (FileType == EFI_FV_FILETYPE_MM_CORE_STANDALONE) {
> > +      EFI_FV_INFO  VolumeInfo;
> > +      //
> > +      // This is SMM BFV
> > +      //
> > +      Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);
> > +      if (!EFI_ERROR (Status)) {
> > +        gMmCorePrivate->StandaloneBfvAddress =
> > (EFI_PHYSICAL_ADDRESS)(UINTN)VolumeInfo.FvStart;
> > +      }
> > +    }
> > +
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  return EFI_NOT_FOUND;
> > +}
> > +
> > +/**
> > +  Load the SMM Core image into SMRAM and executes the SMM Core from
> > SMRAM.
> > +
> > +  @param[in, out] SmramRange            Descriptor for the range of SMRAM to
> > reload the
> > +                                        currently executing image, the rang of SMRAM to
> > +                                        hold SMM Core will be excluded.
> > +  @param[in, out] SmramRangeSmmCore     Descriptor for the range of
> SMRAM
> > to hold SMM Core.
> > +
> > +  @param[in]      Context               Context to pass into SMM Core
> > +
> > +  @return  EFI_STATUS
> > +
> > +**/
> > +EFI_STATUS
> > +ExecuteSmmCoreFromSmram (
> > +  IN OUT EFI_SMRAM_DESCRIPTOR  *SmramRange,
> > +  IN OUT EFI_SMRAM_DESCRIPTOR  *SmramRangeSmmCore,
> > +  IN     VOID                  *Context
> > +  )
> > +{
> > +  EFI_STATUS                    Status;
> > +  VOID                          *SourceBuffer;
> > +  UINTN                         SourceSize;
> > +  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
> > +  UINTN                         PageCount;
> > +  VOID                          *HobList;
> > +
> > +  Status = PeiServicesGetHobList (&HobList);
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  //
> > +  // Search all Firmware Volumes for a PE/COFF image in a file of type
> > SMM_CORE
> > +  //
> > +  Status = GetSectionFromAnyFvByFileType (
> > +             EFI_FV_FILETYPE_MM_CORE_STANDALONE,
> > +             0,
> > +             EFI_SECTION_PE32,
> > +             0,
> > +             &SourceBuffer,
> > +             &SourceSize
> > +             );
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  //
> > +  // Initialize ImageContext
> > +  //
> > +  ImageContext.Handle    = SourceBuffer;
> > +  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
> > +
> > +  //
> > +  // Get information about the image being loaded
> > +  //
> > +  Status = PeCoffLoaderGetImageInfo (&ImageContext);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  //
> > +  // if Loading module at Fixed Address feature is enabled, the SMM core
> driver
> > will be loaded to
> > +  // the address assigned by build tool.
> > +  //
> > +  if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) {
> > +    //
> > +    // Get the fixed loading address assigned by Build tool
> > +    //
> > +    Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);
> > +    if (!EFI_ERROR (Status)) {
> > +      //
> > +      // Since the memory range to load SMM CORE will be cut out in SMM core,
> > so no need to allocate and free this range
> > +      //
> > +      PageCount = 0;
> > +      //
> > +      // Reserved Smram Region for SmmCore is not used, and remove it from
> > SmramRangeCount.
> > +      //
> > +      gMmCorePrivate->MmramRangeCount--;
> > +    } else {
> > +      DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR: Loading
> module
> > at fixed address at address failed\n"));
> > +      //
> > +      // Allocate memory for the image being loaded from the
> > EFI_SRAM_DESCRIPTOR
> > +      // specified by SmramRange
> > +      //
> > +      PageCount = (UINTN)EFI_SIZE_TO_PAGES
> ((UINTN)ImageContext.ImageSize
> > + ImageContext.SectionAlignment);
> > +
> > +      ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);
> > +      ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));
> > +
> > +      SmramRange->PhysicalSize        -= EFI_PAGES_TO_SIZE (PageCount);
> > +      SmramRangeSmmCore->CpuStart      = SmramRange->CpuStart +
> > SmramRange->PhysicalSize;
> > +      SmramRangeSmmCore->PhysicalStart = SmramRange->PhysicalStart +
> > SmramRange->PhysicalSize;
> > +      SmramRangeSmmCore->RegionState   = SmramRange->RegionState |
> > EFI_ALLOCATED;
> > +      SmramRangeSmmCore->PhysicalSize  = EFI_PAGES_TO_SIZE (PageCount);
> > +
> > +      //
> > +      // Align buffer on section boundary
> > +      //
> > +      ImageContext.ImageAddress = SmramRangeSmmCore->CpuStart;
> > +    }
> > +  } else {
> > +    //
> > +    // Allocate memory for the image being loaded from the
> > EFI_SRAM_DESCRIPTOR
> > +    // specified by SmramRange
> > +    //
> > +    PageCount = (UINTN)EFI_SIZE_TO_PAGES
> ((UINTN)ImageContext.ImageSize +
> > ImageContext.SectionAlignment);
> > +
> > +    ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);
> > +    ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));
> > +
> > +    SmramRange->PhysicalSize        -= EFI_PAGES_TO_SIZE (PageCount);
> > +    SmramRangeSmmCore->CpuStart      = SmramRange->CpuStart +
> > SmramRange->PhysicalSize;
> > +    SmramRangeSmmCore->PhysicalStart = SmramRange->PhysicalStart +
> > SmramRange->PhysicalSize;
> > +    SmramRangeSmmCore->RegionState   = SmramRange->RegionState |
> > EFI_ALLOCATED;
> > +    SmramRangeSmmCore->PhysicalSize  = EFI_PAGES_TO_SIZE (PageCount);
> > +
> > +    //
> > +    // Align buffer on section boundary
> > +    //
> > +    ImageContext.ImageAddress = SmramRangeSmmCore->CpuStart;
> > +  }
> > +
> > +  ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
> > +  ImageContext.ImageAddress &=
> > ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
> > +
> > +  //
> > +  // Print debug message showing SMM Core load address.
> > +  //
> > +  DEBUG ((DEBUG_INFO, "SMM IPL loading SMM Core at SMRAM
> > address %p\n", (VOID *)(UINTN)ImageContext.ImageAddress));
> > +
> > +  //
> > +  // Load the image to our new buffer
> > +  //
> > +  Status = PeCoffLoaderLoadImage (&ImageContext);
> > +  if (!EFI_ERROR (Status)) {
> > +    //
> > +    // Relocate the image in our new buffer
> > +    //
> > +    Status = PeCoffLoaderRelocateImage (&ImageContext);
> > +    if (!EFI_ERROR (Status)) {
> > +      //
> > +      // Flush the instruction cache so the image data are written before we
> > execute it
> > +      //
> > +      InvalidateInstructionCacheRange ((VOID
> > *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
> > +
> > +      //
> > +      // Print debug message showing SMM Core entry point address.
> > +      //
> > +      DEBUG ((DEBUG_INFO, "SMM IPL calling SMM Core at SMRAM
> > address %p\n", (VOID *)(UINTN)ImageContext.EntryPoint));
> > +
> > +      gMmCorePrivate->MmCoreImageBase = ImageContext.ImageAddress;
> > +      gMmCorePrivate->MmCoreImageSize = ImageContext.ImageSize;
> > +      DEBUG ((DEBUG_INFO, "SmmCoreImageBase - 0x%016lx\n",
> > gMmCorePrivate->MmCoreImageBase));
> > +      DEBUG ((DEBUG_INFO, "SmmCoreImageSize - 0x%016lx\n",
> > gMmCorePrivate->MmCoreImageSize));
> > +
> > +      gMmCorePrivate->MmCoreEntryPoint = ImageContext.EntryPoint;
> > +
> > +      //
> > +      // Print debug message showing Standalone MM Core entry point address.
> > +      //
> > +      DEBUG ((DEBUG_INFO, "SMM IPL calling Standalone MM Core at SMRAM
> > address - 0x%016lx\n", gMmCorePrivate->MmCoreEntryPoint));
> > +
> > +      //
> > +      // Execute image
> > +      //
> > +      LoadSmmCore (ImageContext.EntryPoint, HobList);
> > +    }
> > +  }
> > +
> > +  //
> > +  // If the load operation, relocate operation, or the image execution return
> an
> > +  // error, then free memory allocated from the EFI_SRAM_DESCRIPTOR
> > specified by
> > +  // SmramRange
> > +  //
> > +  if (EFI_ERROR (Status)) {
> > +    SmramRange->PhysicalSize += EFI_PAGES_TO_SIZE (PageCount);
> > +  }
> > +
> > +  //
> > +  // Always free memory allocated by GetFileBufferByFilePath ()
> > +  //
> > +  FreePool (SourceBuffer);
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Get full SMRAM ranges.
> > +
> > +  It will get SMRAM ranges from SmmAccess protocol and SMRAM reserved
> > ranges from
> > +  SmmConfiguration protocol, split the entries if there is overlap between
> them.
> > +  It will also reserve one entry for SMM core.
> > +
> > +  @param[in]  PeiServices           Describes the list of possible PEI Services.
> > +  @param[out] FullSmramRangeCount   Output pointer to full SMRAM range
> > count.
> > +
> > +  @return Pointer to full SMRAM ranges.
> > +
> > +**/
> > +EFI_SMRAM_DESCRIPTOR *
> > +GetFullSmramRanges (
> > +  IN  CONST EFI_PEI_SERVICES  **PeiServices,
> > +  OUT       UINTN             *FullSmramRangeCount
> > +  )
> > +{
> > +  EFI_STATUS            Status;
> > +  UINTN                 Size;
> > +  EFI_SMRAM_DESCRIPTOR  *FullSmramRanges;
> > +  UINTN                 AdditionSmramRangeCount;
> > +  UINTN                 SmramRangeCount;
> > +
> > +  //
> > +  // Get SMRAM information.
> > +  //
> > +  Size   = 0;
> > +  Status = mSmmAccess->GetCapabilities ((EFI_PEI_SERVICES **)PeiServices,
> > mSmmAccess, &Size, NULL);
> > +  ASSERT (Status == EFI_BUFFER_TOO_SMALL);
> > +
> > +  SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
> > +
> > +  //
> > +  // Reserve one entry SMM Core in the full SMRAM ranges.
> > +  //
> > +  AdditionSmramRangeCount = 1;
> > +  if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) {
> > +    //
> > +    // Reserve two entries for all SMM drivers & SMM Core in the full SMRAM
> > ranges.
> > +    //
> > +    AdditionSmramRangeCount = 2;
> > +  }
> > +
> > +  *FullSmramRangeCount = SmramRangeCount + AdditionSmramRangeCount;
> > +  Size                 = (*FullSmramRangeCount) * sizeof
> (EFI_SMRAM_DESCRIPTOR);
> > +  FullSmramRanges      = (EFI_SMRAM_DESCRIPTOR *)AllocateZeroPool (Size);
> > +  ASSERT (FullSmramRanges != NULL);
> > +  if (FullSmramRanges == NULL) {
> > +    return NULL;
> > +  }
> > +
> > +  Status = mSmmAccess->GetCapabilities ((EFI_PEI_SERVICES **)PeiServices,
> > mSmmAccess, &Size, FullSmramRanges);
> > +
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  return FullSmramRanges;
> > +}
> > +
> > +/**
> > +  The Entry Point for SMM IPL
> > +
> > +  Load SMM Core into SMRAM.
> > +
> > +  @param  FileHandle  Handle of the file being invoked.
> > +  @param  PeiServices Describes the list of possible PEI Services.
> > +
> > +  @retval EFI_SUCCESS    The entry point is executed successfully.
> > +  @retval Other          Some error occurred when executing this entry point.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SmmIplEntry (
> > +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> > +  IN CONST EFI_PEI_SERVICES     **PeiServices
> > +  )
> > +{
> > +  EFI_STATUS             Status;
> > +  UINTN                  Index;
> > +  UINT64                 MaxSize;
> > +  UINT64                 SmmCodeSize;
> > +  MM_CORE_DATA_HOB_DATA  SmmCoreDataHobData;
> > +  EFI_SMRAM_DESCRIPTOR   *MmramRanges;
> > +  EFI_SMRAM_DESCRIPTOR   *SmramRangeSmmDriver;
> > +
> > +  //
> > +  // Build Hob for SMM and DXE phase
> > +  //
> > +  SmmCoreDataHobData.Address =
> > (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateRuntimePages (EFI_SIZE_TO_PAGES
> > (sizeof (mMmCorePrivateData)));
> > +  ASSERT (SmmCoreDataHobData.Address != 0);
> > +  gMmCorePrivate = (VOID *)(UINTN)SmmCoreDataHobData.Address;
> > +  CopyMem ((VOID *)(UINTN)SmmCoreDataHobData.Address,
> > &mMmCorePrivateData, sizeof (mMmCorePrivateData));
> > +  DEBUG ((DEBUG_INFO, "gMmCorePrivate - 0x%x\n", gMmCorePrivate));
> > +
> > +  BuildGuidDataHob (
> > +    &gMmCoreDataHobGuid,
> > +    (VOID *)&SmmCoreDataHobData,
> > +    sizeof (SmmCoreDataHobData)
> > +    );
> > +
> > +  //
> > +  // Get SMM Access Protocol
> > +  //
> > +  Status = PeiServicesLocatePpi (&gPeiSmmAccessPpiGuid, 0, NULL, (VOID
> > **)&mSmmAccess);
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  //
> > +  // Get SMRAM information
> > +  //
> > +  gMmCorePrivate->MmramRanges =
> > (EFI_PHYSICAL_ADDRESS)(UINTN)GetFullSmramRanges (PeiServices, (UINTN
> > *)&gMmCorePrivate->MmramRangeCount);
> > +  ASSERT (gMmCorePrivate->MmramRanges != 0);
> > +  if (gMmCorePrivate->MmramRanges == 0) {
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  //
> > +  // Open all SMRAM ranges
> > +  //
> > +  Status = mSmmAccess->Open ((EFI_PEI_SERVICES **)PeiServices,
> > mSmmAccess, 0);
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  //
> > +  // Print debug message that the SMRAM window is now open.
> > +  //
> > +  DEBUG ((DEBUG_INFO, "SMM IPL opened SMRAM window\n"));
> > +
> > +  //
> > +  // Find the largest SMRAM range between 1MB and 4GB that is at least
> 256KB
> > - 4K in size
> > +  //
> > +  mCurrentSmramRange = NULL;
> > +  MmramRanges        = (EFI_MMRAM_DESCRIPTOR
> *)(UINTN)gMmCorePrivate-
> > >MmramRanges;
> > +  if (MmramRanges == NULL) {
> > +    DEBUG ((DEBUG_ERROR, "Fail to retrieve MmramRanges\n"));
> > +    return EFI_UNSUPPORTED;
> > +  }
> > +
> > +  for (Index = 0, MaxSize = SIZE_256KB - EFI_PAGE_SIZE; Index <
> > gMmCorePrivate->MmramRangeCount; Index++) {
> > +    //
> > +    // Skip any SMRAM region that is already allocated, needs testing, or needs
> > ECC initialization
> > +    //
> > +    if ((MmramRanges[Index].RegionState & (EFI_ALLOCATED |
> > EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {
> > +      continue;
> > +    }
> > +
> > +    if (MmramRanges[Index].CpuStart >= BASE_1MB) {
> > +      if ((MmramRanges[Index].CpuStart + MmramRanges[Index].PhysicalSize)
> <=
> > BASE_4GB) {
> > +        if (MmramRanges[Index].PhysicalSize >= MaxSize) {
> > +          MaxSize            = MmramRanges[Index].PhysicalSize;
> > +          mCurrentSmramRange = &MmramRanges[Index];
> > +        }
> > +      }
> > +    }
> > +  }
> > +
> > +  if (mCurrentSmramRange != NULL) {
> > +    //
> > +    // Print debug message showing SMRAM window that will be used by SMM
> > IPL and SMM Core
> > +    //
> > +    DEBUG ((
> > +      DEBUG_INFO,
> > +      "SMM IPL found SMRAM window %p - %p\n",
> > +      (VOID *)(UINTN)mCurrentSmramRange->CpuStart,
> > +      (VOID *)(UINTN)(mCurrentSmramRange->CpuStart +
> > mCurrentSmramRange->PhysicalSize - 1)
> > +      ));
> > +
> > +    GetSmramCacheRange (mCurrentSmramRange, &mSmramCacheBase,
> > &mSmramCacheSize);
> > +
> > +    //
> > +    // if Loading module at Fixed Address feature is enabled, save the SMRAM
> > base to Load
> > +    // Modules At Fixed Address Configuration Table.
> > +    //
> > +    if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) {
> > +      //
> > +      // Build tool will calculate the smm code size and then patch the
> > PcdLoadFixAddressSmmCodePageNumber
> > +      //
> > +      SmmCodeSize = LShiftU64 (PcdGet32
> > (PcdLoadFixAddressSmmCodePageNumber), EFI_PAGE_SHIFT);
> > +      //
> > +      // The SMRAM available memory is assumed to be larger than
> SmmCodeSize
> > +      //
> > +      ASSERT (mCurrentSmramRange->PhysicalSize > SmmCodeSize);
> > +      //
> > +      // Fill the Smram range for all SMM code
> > +      //
> > +      MmramRanges = (EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate-
> > >MmramRanges;
> > +      //
> > +      // Note: SmramRanges specific for all SMM code will put in the
> > gMmCorePrivate->MmramRangeCount - 2.
> > +      //
> > +      SmramRangeSmmDriver                = &MmramRanges[gMmCorePrivate-
> > >MmramRangeCount - 2];
> > +      SmramRangeSmmDriver->CpuStart      = mCurrentSmramRange->CpuStart;
> > +      SmramRangeSmmDriver->PhysicalStart = mCurrentSmramRange-
> > >PhysicalStart;
> > +      SmramRangeSmmDriver->RegionState   = mCurrentSmramRange-
> > >RegionState | EFI_ALLOCATED;
> > +      SmramRangeSmmDriver->PhysicalSize  = SmmCodeSize;
> > +
> > +      mCurrentSmramRange->PhysicalSize -= SmmCodeSize;
> > +      mCurrentSmramRange->CpuStart      = mCurrentSmramRange->CpuStart +
> > SmmCodeSize;
> > +      mCurrentSmramRange->PhysicalStart = mCurrentSmramRange-
> > >PhysicalStart + SmmCodeSize;
> > +    }
> > +
> > +    //
> > +    // Load SMM Core into SMRAM and execute it from SMRAM
> > +    // Note: SmramRanges specific for SMM Core will put in the
> gMmCorePrivate-
> > >MmramRangeCount - 1.
> > +    //
> > +    Status = ExecuteSmmCoreFromSmram (
> > +               mCurrentSmramRange,
> > +               &(((EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate-
> > >MmramRanges)[gMmCorePrivate->MmramRangeCount - 1]),
> > +               gMmCorePrivate
> > +               );
> > +    if (EFI_ERROR (Status)) {
> > +      //
> > +      // Print error message that the SMM Core failed to be loaded and
> executed.
> > +      //
> > +      DEBUG ((DEBUG_ERROR, "SMM IPL could not load and execute SMM
> Core
> > from SMRAM\n"));
> > +    }
> > +  } else {
> > +    //
> > +    // Print error message that there are not enough SMRAM resources to load
> > the SMM Core.
> > +    //
> > +    DEBUG ((DEBUG_ERROR, "SMM IPL could not find a large enough SMRAM
> > region to load SMM Core\n"));
> > +  }
> > +
> > +  //
> > +  // If the SMM Core could not be loaded then close SMRAM window, free
> > allocated
> > +  // resources, and return an error so SMM IPL will be unloaded.
> > +  //
> > +  if ((mCurrentSmramRange == NULL) || EFI_ERROR (Status)) {
> > +    //
> > +    // Close all SMRAM ranges
> > +    //
> > +    Status = mSmmAccess->Close ((EFI_PEI_SERVICES **)PeiServices,
> > mSmmAccess, 0);
> > +    ASSERT_EFI_ERROR (Status);
> > +
> > +    //
> > +    // Print debug message that the SMRAM window is now closed.
> > +    //
> > +    DEBUG ((DEBUG_INFO, "SMM IPL closed SMRAM window\n"));
> > +
> > +    //
> > +    // Free all allocated resources
> > +    //
> > +    FreePool ((VOID *)(UINTN)gMmCorePrivate->MmramRanges);
> > +
> > +    return EFI_UNSUPPORTED;
> > +  }
> > +
> > +  //
> > +  // Create ready to boot for close and lock smram ranges
> > +  //
> > +  Status = PeiServicesNotifyPpi (&mReadyToBootNotifyList);
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  return EFI_SUCCESS;
> > +}
> > diff --git
> a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c
> > b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c
> > new file mode 100644
> > index 0000000000..6d3497f2ea
> > --- /dev/null
> > +++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/X64/LoadSmmCore.c
> > @@ -0,0 +1,32 @@
> > +/** @file
> > +  SMM IPL that load the SMM Core into SMRAM
> > +
> > +  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <PiPei.h>
> > +#include <PiSmm.h>
> > +#include <StandaloneMm.h>
> > +
> > +/**
> > +  Load SMM core to dispatch other Standalone MM drivers.
> > +
> > +  @param  Entry                     Entry of Standalone MM Foundation.
> > +  @param  Context1                  A pointer to the context to pass into the
> > EntryPoint
> > +                                    function.
> > +  @retval EFI_SUCCESS               Successfully loaded SMM core.
> > +  @retval Others                    Failed to load SMM core.
> > +**/
> > +EFI_STATUS
> > +LoadSmmCore (
> > +  IN EFI_PHYSICAL_ADDRESS  Entry,
> > +  IN VOID                  *Context1
> > +  )
> > +{
> > +  STANDALONE_MM_FOUNDATION_ENTRY_POINT  EntryPoint;
> > +
> > +  EntryPoint =
> (STANDALONE_MM_FOUNDATION_ENTRY_POINT)(UINTN)Entry;
> > +  return EntryPoint (Context1);
> > +}
> > diff --git
> > a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm
> > b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm
> > new file mode 100644
> > index 0000000000..7f887eb77d
> > --- /dev/null
> > +++
> b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm
> > @@ -0,0 +1,148 @@
> > +;------------------------------------------------------------------------------
> > +;
> > +; Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
> > +; SPDX-License-Identifier: BSD-2-Clause-Patent
> > +;
> > +; Module Name:
> > +;
> > +;    Thunk32To64.nasm
> > +;
> > +; Abstract:
> > +;
> > +;   This is the assembly code to transition from long mode to compatibility
> > +;   mode to execute 32-bit code and then transit back to long mode.
> > +;
> > +;------------------------------------------------------------------------------
> > +
> > +    SECTION .text
> > +
> > +;------------------------------------------------------------------------------
> > +; Procedure:    AsmExecute64BitCode
> > +;
> > +; Input:        None
> > +;
> > +; Output:       None
> > +;
> > +; Prototype:    UINT32
> > +;               AsmExecute64BitCode (
> > +;                 IN UINT64           Function,
> > +;                 IN UINT64           Param1,
> > +;                 IN UINT64           Param2,
> > +;                 IN IA32_DESCRIPTOR  *InternalGdtr
> > +;                 );
> > +;
> > +;
> > +; Description:  A thunk function to execute 32-bit code in long mode.
> > +;
> > +;------------------------------------------------------------------------------
> > +global ASM_PFX(AsmExecute64BitCode)
> > +ASM_PFX(AsmExecute64BitCode):
> > +;
> > +; +---------+
> > +; | EIP(64) |
> > +; +---------+
> > +; | CS (64) |
> > +; +---------+
> > +; | EIP(32) |
> > +; +---------+
> > +; | CS (32) |<-ESP (16 bytes aligned)
> > +; +---------+
> > +; | ...     |
> > +; +---------+
> > +; | ebx     |<-EBP
> > +; +---------+
> > +; | ebp     |<-EBP + 4
> > +; +---------+
> > +; | esi     |<-EBP + 8
> > +; +---------+
> > +; | edi     |<-EBP + 12
> > +; +---------+
> > +; | RFlags  |<-EBP + 16
> > +; +---------+
> > +; | RetAddr |<-EBP (org)
> > +; +---------+
> > +; | Func    |<-EBP + 24
> > +; | Func    |
> > +; +---------+
> > +; | Param1  |<-EBP + 32
> > +; | Param1  |
> > +; +---------+
> > +; | Param2  |<-EBP + 40
> > +; | Param2  |
> > +; +---------+
> > +; | Gdtr    |
> > +; +---------+
> > +;
> > +    ;
> > +    ; Save general purpose register and RFlags register
> > +    ;
> > +    pushfd
> > +    push    edi
> > +    push    esi
> > +    push    ebp
> > +    push    ebx
> > +    mov     ebp, esp
> > +
> > +    and     esp, 0FFFFFFF0h
> > +
> > +    push    010h                        ; protected mode selector on stack
> > +    mov     eax, Compatible             ; offset for LongMode
> > +    push    eax                         ; offset on stack
> > +
> > +    push    038h                        ; long mode selector on stack
> > +    mov     eax, LongMode               ; offset for LongMode
> > +    push    eax                         ; offset on stack
> > +
> > +    mov     eax, cr4
> > +    or      al, 020h
> > +    mov     cr4, eax                    ; enable PAE
> > +    mov     ecx, 0c0000080h
> > +    rdmsr
> > +    or      ah, 1                       ; set LME
> > +    wrmsr
> > +    mov     eax, cr0
> > +    bts     eax, 31                     ; set PG
> > +    mov     cr0, eax                    ; enable paging
> > +    retf                                ; topmost 2 dwords hold the address
> > +LongMode:                               ; long mode starts here
> > +
> > +    ; Call long mode function
> > +    DB      67h, 48h                    ; 32-bit address size, 64-bit operand size
> > +    mov     eax, [ebp + 24]             ; mov rbx, [ebp + 24]
> > +    DB      67h, 48h
> > +    mov     ecx, [ebp + 24 + 8]         ; mov rcx, [ebp + 24 + 8]
> > +    DB      67h, 48h
> > +    mov     edx, [ebp + 24 + 16]        ; mov rdx, [ebp + 24 + 16]
> > +
> > +    DB      48h
> > +    add     esp, -20h                   ; add rsp, -20h
> > +    call    eax                         ; call rax
> > +    DB      48h
> > +    add     esp, 20h                    ; add rsp, 20h
> > +
> > +    ; after long mode function call
> > +    mov     ebx, eax
> > +
> > +    retf
> > +Compatible:
> > +    mov     ecx, cr0
> > +    btc     ecx, 31                     ; clear PG
> > +    mov     cr0, ecx                    ; disable paging
> > +    mov     ecx, 0C0000080h
> > +    rdmsr
> > +    btc     eax, 8                      ; clear LME
> > +    wrmsr
> > +
> > +    ;
> > +    ; Restore C register and eax hold the return status from 32-bit function.
> > +    ; Note: Do not touch rax from now which hold the return value from IA32
> > function
> > +    ;
> > +    mov     eax, ebx                    ; put return status to EAX
> > +    mov     esp, ebp                    ; restore stack pointer
> > +    pop     ebx
> > +    pop     ebp
> > +    pop     esi
> > +    pop     edi
> > +    popfd
> > +
> > +    ret
> > diff --git
> > a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
> > b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
> > new file mode 100644
> > index 0000000000..be0aae70f0
> > --- /dev/null
> > +++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
> > @@ -0,0 +1,66 @@
> > +/** @file
> > +  Private header with declarations and definitions specific to the Standalone
> > +  MM IPL PEI driver
> > +
> > +  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#ifndef STANDALONE_MM_IPL_PEI_H_
> > +#define STANDALONE_MM_IPL_PEI_H_
> > +
> > +/**
> > +  Load SMM core to dispatch other Standalone MM drivers.
> > +
> > +  @param  Entry                     Entry of Standalone MM Foundation.
> > +  @param  Context1                  A pointer to the context to pass into the
> > EntryPoint
> > +                                    function.
> > +  @retval EFI_SUCCESS               Successfully loaded SMM core.
> > +  @retval Others                    Failed to load SMM core.
> > +**/
> > +EFI_STATUS
> > +LoadSmmCore (
> > +  IN EFI_PHYSICAL_ADDRESS  Entry,
> > +  IN VOID                  *Context1
> > +  );
> > +
> > +/**
> > +  Assembly function to transition from long mode to compatibility mode to
> > +  execute 32-bit code and then transit back to long mode.
> > +
> > +  @param[in] Function     The 32bit code entry to be executed.
> > +  @param[in] Param1       The first parameter to pass to 32bit code
> > +  @param[in] Param2       The second parameter to pass to 32bit code
> > +  @param[in] InternalGdtr The GDT and GDT descriptor used by this library
> > +
> > +  @retval status.
> > +**/
> > +UINT32
> > +AsmExecute64BitCode (
> > +  IN UINT64           Function,
> > +  IN UINT64           Param1,
> > +  IN UINT64           Param2,
> > +  IN IA32_DESCRIPTOR  *InternalGdtr
> > +  );
> > +
> > +/**
> > +  This is the callback function on ready to boot.
> > +
> > +  Close and lock smram ranges on ready to boot stage.
> > +
> > +  @param   PeiServices       General purpose services available to every PEIM.
> > +  @param   NotifyDescriptor  The notification structure this PEIM registered
> on
> > install.
> > +  @param   Ppi               Pointer to the PPI data associated with this function.
> > +  @retval  EFI_SUCCESS       Close and lock smram ranges successfully.
> > +  @retval  Other             Close and lock smram ranges failed.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +ReadyToBootEvent (
> > +  IN  EFI_PEI_SERVICES           **PeiServices,
> > +  IN  EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
> > +  IN  VOID                       *Ppi
> > +  );
> > +
> > +#endif
> > diff --git
> > a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
> > b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
> > new file mode 100644
> > index 0000000000..ff4c67a92c
> > --- /dev/null
> > +++
> b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
> > @@ -0,0 +1,75 @@
> > +## @file
> > +#  This module provide a Standalone SMM compliant implementation of SMM
> > IPL PEIM.
> > +#
> > +#  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
> > +#
> > +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 0x00010005
> > +  BASE_NAME                      = StandaloneMmIplPei
> > +  FILE_GUID                      = 578A0D17-2DC0-4C7D-A121-D8D771923BB0
> > +  MODULE_TYPE                    = PEIM
> > +  VERSION_STRING                 = 1.0
> > +  PI_SPECIFICATION_VERSION       = 0x0001000A
> > +  ENTRY_POINT                    = SmmIplEntry
> > +
> > +#
> > +# The following information is for reference only and not required by the
> build
> > tools.
> > +#
> > +#  VALID_ARCHITECTURES           = IA32 X64
> > +#
> > +
> > +[Sources]
> > +  StandaloneMmIplPei.h
> > +  StandaloneMmIplPei.c
> > +
> > +[Sources.Ia32]
> > +  Ia32/LoadSmmCore.c
> > +  Ia32/Thunk32To64.nasm
> > +
> > +[Sources.X64]
> > +  X64/LoadSmmCore.c
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  MdeModulePkg/MdeModulePkg.dec
> > +  StandaloneMmPkg/StandaloneMmPkg.dec
> > +
> > +[LibraryClasses]
> > +  PeimEntryPoint
> > +  PeiServicesTablePointerLib
> > +  PeiServicesLib
> > +  BaseLib
> > +  BaseMemoryLib
> > +  PeCoffLib
> > +  CacheMaintenanceLib
> > +  MemoryAllocationLib
> > +  DebugLib
> > +  HobLib
> > +  IntrinsicLib
> > +
> > +[Guids]
> > +  gMmCoreDataHobGuid
> > +  gEfiEventReadyToBootGuid
> > +
> > +[Ppis]
> > +  gPeiSmmAccessPpiGuid                     ## CONSUMES
> > +  gPeiSmmControlPpiGuid                    ## CONSUMES
> > +
> > +[FeaturePcd.IA32]
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode      ##
> > CONSUMES
> > +
> > +[Pcd.IA32]
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable              ##
> > SOMETIMES_CONSUMES
> > +
> > +[Pcd]
> > +
> gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber
> > ## SOMETIMES_CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable
> ##
> > CONSUMES
> > +
> > +[Depex]
> > +  gPeiSmmAccessPpiGuid AND
> > +  gPeiSmmControlPpiGuid
> > +
> > diff --git a/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
> > b/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
> > index 4777532a7e..872f7958be 100644
> > --- a/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
> > +++ b/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
> > @@ -78,7 +78,9 @@
> >      ## options defined .pytool/Plugin/SpellCheck
> >      "SpellCheck": {
> >          "AuditOnly": False,
> > -        "IgnoreFiles": [],           # use gitignore syntax to ignore errors
> > +        "IgnoreFiles": [
> > +            "Drivers/StandaloneMmIplPei/Ia32/Thunk32To64.nasm"
> > +        ],           # use gitignore syntax to ignore errors
> >                                       # in matching files
> >          "ExtendWords": [
> >              "Bsymbolic",
> > diff --git a/StandaloneMmPkg/StandaloneMmPkg.dsc
> > b/StandaloneMmPkg/StandaloneMmPkg.dsc
> > index 8012f93b7d..d88471fe82 100644
> > --- a/StandaloneMmPkg/StandaloneMmPkg.dsc
> > +++ b/StandaloneMmPkg/StandaloneMmPkg.dsc
> > @@ -20,7 +20,7 @@
> >    PLATFORM_VERSION               = 1.0
> >    DSC_SPECIFICATION              = 0x00010011
> >    OUTPUT_DIRECTORY               = Build/StandaloneMm
> > -  SUPPORTED_ARCHITECTURES        = AARCH64|X64|ARM
> > +  SUPPORTED_ARCHITECTURES        = AARCH64|X64|ARM|IA32
> >    BUILD_TARGETS                  = DEBUG|RELEASE
> >    SKUID_IDENTIFIER               = DEFAULT
> >
> > @@ -60,6 +60,14 @@
> >
> >
> StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoin
> > t/StandaloneMmDriverEntryPoint.inf
> >
> >
> VariableMmDependency|StandaloneMmPkg/Library/VariableMmDependency/V
> > ariableMmDependency.inf
> >
> > +[LibraryClasses.common.PEIM]
> > +  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
> > +  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
> > +
> >
> MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllo
> c
> > ationLib.inf
> > +  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
> > +
> >
> PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServi
> c
> > esTablePointerLib.inf
> > +  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
> > +
> >  [LibraryClasses.AARCH64, LibraryClasses.ARM]
> >    ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
> >
> >
> StandaloneMmMmuLib|ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStand
> > aloneMmLib.inf
> > @@ -104,7 +112,7 @@
> >  #       generated for it, but the binary will not be put into any firmware volume.
> >  #
> >
> >
> #################################################################
> > ##################################
> > -[Components.common]
> > +[Components.AARCH64, Components.ARM, Components.X64]
> >    #
> >    # MM Core
> >    #
> > @@ -122,6 +130,9 @@
> >    StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.inf
> >
> >
> StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/StandaloneMm
> > PeCoffExtraActionLib.inf
> >
> > +[Components.X64, Components.IA32]
> > +  StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
> > +
> >
> >
> #################################################################
> > ##################################
> >  #
> >  # BuildOptions Section - Define the module specific tool chain flags that
> should
> > be used as
> > diff --git a/UefiPayloadPkg/UniversalPayloadBuild.sh
> > b/UefiPayloadPkg/UniversalPayloadBuild.sh
> > index 9a72eedd35..bacf5233a8 100644
> > --- a/UefiPayloadPkg/UniversalPayloadBuild.sh
> > +++ b/UefiPayloadPkg/UniversalPayloadBuild.sh
> > @@ -1,17 +1,17 @@
> > -#!/usr/bin/env bash
> > -#
> > -# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > -#
> > -# SPDX-License-Identifier: BSD-2-Clause-Patent
> > -#
> > -
> > -if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
> > -    echo python_exe=${PYTHON_COMMAND}
> > -fi
> > -
> > -# Get file path of UniversalPayloadBuild.sh
> > -uplbld_filepath=${BASH_SOURCE:-$0}
> > -# Remove ".sh" extension
> > -uplbld_filepath_noext=${uplbld_filepath%.*}
> > -# execute UniversalPayloadBuild.py to build UefiPayloadPkg
> > -exec "${python_exe:-python}" "$uplbld_filepath_noext.py" "$@"
> > +#!/usr/bin/env bash
> > +#
> > +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +#
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +
> > +if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
> > +    echo python_exe=${PYTHON_COMMAND}
> > +fi
> > +
> > +# Get file path of UniversalPayloadBuild.sh
> > +uplbld_filepath=${BASH_SOURCE:-$0}
> > +# Remove ".sh" extension
> > +uplbld_filepath_noext=${uplbld_filepath%.*}
> > +# execute UniversalPayloadBuild.py to build UefiPayloadPkg
> > +exec "${python_exe:-python}" "$uplbld_filepath_noext.py" "$@"
> > diff --git a/edksetup.sh b/edksetup.sh
> > index cab3a8c113..553e1676d0 100755
> > --- a/edksetup.sh
> > +++ b/edksetup.sh
> > @@ -1,147 +1,147 @@
> > -#
> > -# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
> > -# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
> > -# SPDX-License-Identifier: BSD-2-Clause-Patent
> > -#
> > -# In *inux environment, the build tools's source is required and need to be
> > compiled
> > -# firstly, please reference
> > https://github.com/tianocore/tianocore.github.io/wiki/SourceForge-to-
> Github-
> > Quick-Start
> > -# to get how to setup build tool.
> > -#
> > -# Setup the environment for unix-like systems running a bash-like shell.
> > -# This file must be "sourced" not merely executed. For example: ".
> edksetup.sh"
> > -#
> > -# CYGWIN users: Your path and filename related environment variables
> should
> > be
> > -# set up in the unix style.  This script will make the necessary conversions to
> > -# windows style.
> > -#
> > -# Please reference edk2 user manual for more detail descriptions at
> > https://github.com/tianocore-
> > docs/Docs/raw/master/User_Docs/EDK_II_UserManual_0_7.pdf
> > -#
> > -
> > -SCRIPTNAME="edksetup.sh"
> > -RECONFIG=FALSE
> > -
> > -HelpMsg()
> > -{
> > -  echo "Usage: $SCRIPTNAME [Options]"
> > -  echo
> > -  echo "The system environment variable, WORKSPACE, is always set to the
> > current"
> > -  echo "working directory."
> > -  echo
> > -  echo "Options: "
> > -  echo "  --help, -h, -?        Print this help screen and exit."
> > -  echo
> > -  echo "  --reconfig            Overwrite the WORKSPACE/Conf/*.txt files with
> the"
> > -  echo "                        template files from the BaseTools/Conf directory."
> > -  echo
> > -  echo Please note: This script must be \'sourced\' so the environment can be
> > changed.
> > -  echo ". $SCRIPTNAME"
> > -  echo "source $SCRIPTNAME"
> > -}
> > -
> > -SetWorkspace()
> > -{
> > -  #
> > -  # If WORKSPACE is already set, then we can return right now
> > -  #
> > -  export PYTHONHASHSEED=1
> > -  if [ -n "$WORKSPACE" ]
> > -  then
> > -    return 0
> > -  fi
> > -
> > -  if [ ! -f ${SCRIPTNAME} ] && [ -z "$PACKAGES_PATH" ]
> > -  then
> > -    echo Source this script from the base of your tree.  For example:
> > -    echo "  cd /Path/To/Edk2/Clone"
> > -    echo "  . $SCRIPTNAME"
> > -    return 1
> > -  fi
> > -
> > -  #
> > -  # Check for BaseTools/BuildEnv before dirtying the user's environment.
> > -  #
> > -  if [ ! -f BaseTools/BuildEnv ] && [ -z "$EDK_TOOLS_PATH" ]
> > -  then
> > -    echo BaseTools not found in your tree, and EDK_TOOLS_PATH is not set.
> > -    echo Please point EDK_TOOLS_PATH at the directory that contains
> > -    echo the EDK2 BuildEnv script.
> > -    return 1
> > -  fi
> > -
> > -  #
> > -  # Set $WORKSPACE
> > -  #
> > -  export WORKSPACE=$PWD
> > -  return 0
> > -}
> > -
> > -SetupEnv()
> > -{
> > -  if [ -n "$EDK_TOOLS_PATH" ]
> > -  then
> > -    . $EDK_TOOLS_PATH/BuildEnv
> > -  elif [ -f "$WORKSPACE/BaseTools/BuildEnv" ]
> > -  then
> > -    . $WORKSPACE/BaseTools/BuildEnv
> > -  elif [ -n "$PACKAGES_PATH" ]
> > -  then
> > -    for DIR in $(echo $PACKAGES_PATH | tr ':' ' ')
> > -    do
> > -      if [ -f "$DIR/BaseTools/BuildEnv" ]
> > -      then
> > -        export EDK_TOOLS_PATH=$DIR/BaseTools
> > -        . $DIR/BaseTools/BuildEnv
> > -        break
> > -      fi
> > -    done
> > -  else
> > -    echo BaseTools not found in your tree, and EDK_TOOLS_PATH is not set.
> > -    echo Please check that WORKSPACE or PACKAGES_PATH is not set
> incorrectly
> > -    echo in your shell, or point EDK_TOOLS_PATH at the directory that contains
> > -    echo the EDK2 BuildEnv script.
> > -    return 1
> > -  fi
> > -}
> > -
> > -SetupPython3()
> > -{
> > -  export PYTHON_COMMAND=python3
> > -}
> > -
> > -SourceEnv()
> > -{
> > -  SetupPython3
> > -  SetWorkspace
> > -  SetupEnv
> > -}
> > -
> > -I=$#
> > -while [ $I -gt 0 ]
> > -do
> > -  case "$1" in
> > -    BaseTools)
> > -      # Ignore argument for backwards compatibility
> > -      shift
> > -    ;;
> > -    --reconfig)
> > -      RECONFIG=TRUE
> > -      shift
> > -    ;;
> > -    *)
> > -      HelpMsg
> > -      break
> > -    ;;
> > -  esac
> > -  I=$((I - 1))
> > -done
> > -
> > -if [ $I -gt 0 ]
> > -then
> > -  return 1
> > -fi
> > -
> > -SourceEnv
> > -
> > -unset SCRIPTNAME RECONFIG
> > -
> > -return $?
> > +#
> > +# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
> > +# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +# In *inux environment, the build tools's source is required and need to be
> > compiled
> > +# firstly, please reference
> > https://github.com/tianocore/tianocore.github.io/wiki/SourceForge-to-
> Github-
> > Quick-Start
> > +# to get how to setup build tool.
> > +#
> > +# Setup the environment for unix-like systems running a bash-like shell.
> > +# This file must be "sourced" not merely executed. For example: ".
> edksetup.sh"
> > +#
> > +# CYGWIN users: Your path and filename related environment variables
> should
> > be
> > +# set up in the unix style.  This script will make the necessary conversions to
> > +# windows style.
> > +#
> > +# Please reference edk2 user manual for more detail descriptions at
> > https://github.com/tianocore-
> > docs/Docs/raw/master/User_Docs/EDK_II_UserManual_0_7.pdf
> > +#
> > +
> > +SCRIPTNAME="edksetup.sh"
> > +RECONFIG=FALSE
> > +
> > +HelpMsg()
> > +{
> > +  echo "Usage: $SCRIPTNAME [Options]"
> > +  echo
> > +  echo "The system environment variable, WORKSPACE, is always set to the
> > current"
> > +  echo "working directory."
> > +  echo
> > +  echo "Options: "
> > +  echo "  --help, -h, -?        Print this help screen and exit."
> > +  echo
> > +  echo "  --reconfig            Overwrite the WORKSPACE/Conf/*.txt files with
> the"
> > +  echo "                        template files from the BaseTools/Conf directory."
> > +  echo
> > +  echo Please note: This script must be \'sourced\' so the environment can be
> > changed.
> > +  echo ". $SCRIPTNAME"
> > +  echo "source $SCRIPTNAME"
> > +}
> > +
> > +SetWorkspace()
> > +{
> > +  #
> > +  # If WORKSPACE is already set, then we can return right now
> > +  #
> > +  export PYTHONHASHSEED=1
> > +  if [ -n "$WORKSPACE" ]
> > +  then
> > +    return 0
> > +  fi
> > +
> > +  if [ ! -f ${SCRIPTNAME} ] && [ -z "$PACKAGES_PATH" ]
> > +  then
> > +    echo Source this script from the base of your tree.  For example:
> > +    echo "  cd /Path/To/Edk2/Clone"
> > +    echo "  . $SCRIPTNAME"
> > +    return 1
> > +  fi
> > +
> > +  #
> > +  # Check for BaseTools/BuildEnv before dirtying the user's environment.
> > +  #
> > +  if [ ! -f BaseTools/BuildEnv ] && [ -z "$EDK_TOOLS_PATH" ]
> > +  then
> > +    echo BaseTools not found in your tree, and EDK_TOOLS_PATH is not set.
> > +    echo Please point EDK_TOOLS_PATH at the directory that contains
> > +    echo the EDK2 BuildEnv script.
> > +    return 1
> > +  fi
> > +
> > +  #
> > +  # Set $WORKSPACE
> > +  #
> > +  export WORKSPACE=$PWD
> > +  return 0
> > +}
> > +
> > +SetupEnv()
> > +{
> > +  if [ -n "$EDK_TOOLS_PATH" ]
> > +  then
> > +    . $EDK_TOOLS_PATH/BuildEnv
> > +  elif [ -f "$WORKSPACE/BaseTools/BuildEnv" ]
> > +  then
> > +    . $WORKSPACE/BaseTools/BuildEnv
> > +  elif [ -n "$PACKAGES_PATH" ]
> > +  then
> > +    for DIR in $(echo $PACKAGES_PATH | tr ':' ' ')
> > +    do
> > +      if [ -f "$DIR/BaseTools/BuildEnv" ]
> > +      then
> > +        export EDK_TOOLS_PATH=$DIR/BaseTools
> > +        . $DIR/BaseTools/BuildEnv
> > +        break
> > +      fi
> > +    done
> > +  else
> > +    echo BaseTools not found in your tree, and EDK_TOOLS_PATH is not set.
> > +    echo Please check that WORKSPACE or PACKAGES_PATH is not set
> incorrectly
> > +    echo in your shell, or point EDK_TOOLS_PATH at the directory that contains
> > +    echo the EDK2 BuildEnv script.
> > +    return 1
> > +  fi
> > +}
> > +
> > +SetupPython3()
> > +{
> > +  export PYTHON_COMMAND=python3
> > +}
> > +
> > +SourceEnv()
> > +{
> > +  SetupPython3
> > +  SetWorkspace
> > +  SetupEnv
> > +}
> > +
> > +I=$#
> > +while [ $I -gt 0 ]
> > +do
> > +  case "$1" in
> > +    BaseTools)
> > +      # Ignore argument for backwards compatibility
> > +      shift
> > +    ;;
> > +    --reconfig)
> > +      RECONFIG=TRUE
> > +      shift
> > +    ;;
> > +    *)
> > +      HelpMsg
> > +      break
> > +    ;;
> > +  esac
> > +  I=$((I - 1))
> > +done
> > +
> > +if [ $I -gt 0 ]
> > +then
> > +  return 1
> > +fi
> > +
> > +SourceEnv
> > +
> > +unset SCRIPTNAME RECONFIG
> > +
> > +return $?
> > --
> > 2.37.0.windows.1


      reply	other threads:[~2023-06-26  1:45 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-22  5:21 [PATCH v1] StandaloneMmPkg: Add StandaloneMmIplPei driver Zhang, Hongbin1
2023-06-07  2:03 ` Ni, Ray
2023-06-07  2:29   ` Zhang, Hongbin1
2023-06-07  2:30     ` Yao, Jiewen
2023-06-07  2:37       ` Zhang, Hongbin1
2023-06-26  1:45         ` Zhang, Hongbin1 [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=SA1PR11MB5826DA452306A8F0827B85B6C126A@SA1PR11MB5826.namprd11.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox