From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.115; helo=mga14.intel.com; envelope-from=jian.j.wang@intel.com; receiver=edk2-devel@lists.01.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 727BC2095B09C for ; Thu, 12 Oct 2017 23:11:40 -0700 (PDT) Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Oct 2017 23:15:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.43,369,1503385200"; d="scan'208";a="162189255" Received: from fmsmsx108.amr.corp.intel.com ([10.18.124.206]) by fmsmga005.fm.intel.com with ESMTP; 12 Oct 2017 23:15:11 -0700 Received: from fmsmsx120.amr.corp.intel.com (10.18.124.208) by FMSMSX108.amr.corp.intel.com (10.18.124.206) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 12 Oct 2017 23:15:11 -0700 Received: from shsmsx101.ccr.corp.intel.com (10.239.4.153) by fmsmsx120.amr.corp.intel.com (10.18.124.208) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 12 Oct 2017 23:15:10 -0700 Received: from shsmsx103.ccr.corp.intel.com ([169.254.4.213]) by SHSMSX101.ccr.corp.intel.com ([169.254.1.159]) with mapi id 14.03.0319.002; Fri, 13 Oct 2017 14:15:07 +0800 From: "Wang, Jian J" To: "Dong, Eric" , "edk2-devel@lists.01.org" CC: "Zeng, Star" , "Yao, Jiewen" , "Kinney, Michael D" , "Wolman, Ayellet" Thread-Topic: [PATCH 2/5] MdeModulePkg/PiSmmCore: Implement heap guard feature for SMM mode Thread-Index: AQHTQj+nF6GMfcjJ6Eq14ENJQWJ2MKLg/5swgABQ4VA= Date: Fri, 13 Oct 2017 06:15:07 +0000 Message-ID: References: <20171011031824.17060-1-jian.j.wang@intel.com> <20171011031824.17060-3-jian.j.wang@intel.com> In-Reply-To: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.0.0.116 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH 2/5] MdeModulePkg/PiSmmCore: Implement heap guard feature for SMM mode X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 13 Oct 2017 06:11:40 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Ok. I'll change it to follow required coding style. Thanks for catching it. > -----Original Message----- > From: Dong, Eric > Sent: Friday, October 13, 2017 9:27 AM > To: Wang, Jian J ; edk2-devel@lists.01.org > Cc: Zeng, Star ; Yao, Jiewen ; > Kinney, Michael D ; Wolman, Ayellet > > Subject: RE: [PATCH 2/5] MdeModulePkg/PiSmmCore: Implement heap guard > feature for SMM mode >=20 > Hi Jian, >=20 > I think below code not follow EDKII coding style, EDKII requires definiti= on and > assignment in different code. >=20 > + UINTN LevelShift[GUARDED_HEAP_MAP_TABLE_DEPTH] > + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_SHIFTS; > + UINTN LevelMask[GUARDED_HEAP_MAP_TABLE_DEPTH] > + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_MASKS; >=20 > Thanks, > Eric > > -----Original Message----- > > From: Wang, Jian J > > Sent: Wednesday, October 11, 2017 11:18 AM > > To: edk2-devel@lists.01.org > > Cc: Zeng, Star ; Dong, Eric ;= Yao, > > Jiewen ; Kinney, Michael D > > ; Wolman, Ayellet > > > > Subject: [PATCH 2/5] MdeModulePkg/PiSmmCore: Implement heap guard > > feature for SMM mode > > > > This feature makes use of paging mechanism to add a hidden (not present= ) > > page just before and after the allocated memory block. If the code trie= s > > to access memory outside of the allocated part, page fault exception wi= ll > > be triggered. > > > > This feature is controlled by three PCDs: > > > > gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask > > gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType > > gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPageType > > > > BIT2 and BIT3 of PcdHeapGuardPropertyMask can be used to enable or > > disable > > memory guard for SMM page and pool respectively. PcdHeapGuardPoolType > > and/or > > PcdHeapGuardPageType are used to enable or disable guard for specific t= ype > > of memory. For example, we can turn on guard only for EfiBootServicesDa= ta > > and EfiRuntimeServicesData by setting the PCD with value 0x50. > > > > Pool memory is not ususally integer multiple of one page, and is more l= ikely > > less than a page. There's no way to monitor the overflow at both top an= d > > bottom of pool memory. BIT7 of PcdHeapGuardPropertyMask is used to > > control > > how to position the head of pool memory so that it's easier to catch me= mory > > overflow in memory growing direction or in decreasing direction. > > > > Cc: Star Zeng > > Cc: Eric Dong > > Cc: Jiewen Yao > > Cc: Michael Kinney > > Cc: Ayellet Wolman > > Suggested-by: Ayellet Wolman > > Contributed-under: TianoCore Contribution Agreement 1.1 > > Signed-off-by: Jian J Wang > > --- > > MdeModulePkg/Core/PiSmmCore/Misc/HeapGuard.c | 1438 > > ++++++++++++++++++++++++++ > > MdeModulePkg/Core/PiSmmCore/Misc/HeapGuard.h | 395 +++++++ > > MdeModulePkg/Core/PiSmmCore/Misc/PageTable.c | 704 > > +++++++++++++ > > MdeModulePkg/Core/PiSmmCore/Misc/PageTable.h | 174 ++++ > > MdeModulePkg/Core/PiSmmCore/Page.c | 51 +- > > MdeModulePkg/Core/PiSmmCore/PiSmmCore.c | 12 +- > > MdeModulePkg/Core/PiSmmCore/PiSmmCore.h | 80 +- > > MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf | 8 + > > MdeModulePkg/Core/PiSmmCore/Pool.c | 77 +- > > 9 files changed, 2911 insertions(+), 28 deletions(-) > > create mode 100644 MdeModulePkg/Core/PiSmmCore/Misc/HeapGuard.c > > create mode 100644 MdeModulePkg/Core/PiSmmCore/Misc/HeapGuard.h > > create mode 100644 MdeModulePkg/Core/PiSmmCore/Misc/PageTable.c > > create mode 100644 MdeModulePkg/Core/PiSmmCore/Misc/PageTable.h > > > > diff --git a/MdeModulePkg/Core/PiSmmCore/Misc/HeapGuard.c > > b/MdeModulePkg/Core/PiSmmCore/Misc/HeapGuard.c > > new file mode 100644 > > index 0000000000..c64eaea5d1 > > --- /dev/null > > +++ b/MdeModulePkg/Core/PiSmmCore/Misc/HeapGuard.c > > @@ -0,0 +1,1438 @@ > > +/** @file > > + UEFI Heap Guard functions. > > + > > +Copyright (c) 2017, Intel Corporation. All rights reserved.
> > +This program and the accompanying materials > > +are licensed and made available under the terms and conditions of the = BSD > > License > > +which accompanies this distribution. The full text of the license may= be > > found at > > +http://opensource.org/licenses/bsd-license.php > > + > > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > > BASIS, > > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > > EXPRESS OR IMPLIED. > > + > > +**/ > > + > > +#include "HeapGuard.h" > > + > > +// > > +// Pointer to table tracking the Guarded memory with bitmap, in which = '1' > > +// is used to indicate memory guarded. '0' might be free memory or Gua= rd > > +// page itself, depending on status of memory adjacent to it. > > +// > > +GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mGuardedMemoryMap =3D > > NULL; > > + > > +// > > +// Current depth level of map table pointed by mGuardedMemoryMap. > > +// mMapLevel must be initialized at least by 1. It will be automatical= ly > > +// updated according to the address of memory just tracked. > > +// > > +GLOBAL_REMOVE_IF_UNREFERENCED UINTN mMapLevel =3D 1; > > + > > +// > > +// SMM status flag > > +// > > +BOOLEAN mIsSmmCpuMode =3D FALSE; > > + > > +/** > > + Set corresponding bits in bitmap table to 1 according to the address > > + > > + @param[in] Address Start address to set for > > + @param[in] BitNumber Number of bits to set > > + @param[in] BitMap Pointer to bitmap which covers the Address > > + > > + @return VOID > > +**/ > > +STATIC > > +VOID > > +SetBits ( > > + IN EFI_PHYSICAL_ADDRESS Address, > > + IN UINTN BitNumber, > > + IN UINT64 *BitMap > > + ) > > +{ > > + UINTN Lsbs; > > + UINTN Qwords; > > + UINTN Msbs; > > + UINTN StartBit; > > + UINTN EndBit; > > + > > + StartBit =3D (UINTN)GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address); > > + EndBit =3D (StartBit + BitNumber - 1) % GUARDED_HEAP_MAP_ENTRY_BI= TS; > > + > > + if ((StartBit + BitNumber) > GUARDED_HEAP_MAP_ENTRY_BITS) { > > + Msbs =3D (GUARDED_HEAP_MAP_ENTRY_BITS - StartBit) % > > + GUARDED_HEAP_MAP_ENTRY_BITS; > > + Lsbs =3D (EndBit + 1) % GUARDED_HEAP_MAP_ENTRY_BITS; > > + Qwords =3D (BitNumber - Msbs) / GUARDED_HEAP_MAP_ENTRY_BITS; > > + } else { > > + Msbs =3D BitNumber; > > + Lsbs =3D 0; > > + Qwords =3D 0; > > + } > > + > > + if (Msbs > 0) { > > + *BitMap |=3D LShiftU64 (LShiftU64 (1, Msbs) - 1, StartBit); > > + BitMap +=3D 1; > > + } > > + > > + if (Qwords > 0) { > > + SetMem64 ((VOID *)BitMap, Qwords * > > GUARDED_HEAP_MAP_ENTRY_BYTES, > > + (UINT64)-1); > > + BitMap +=3D Qwords; > > + } > > + > > + if (Lsbs > 0) { > > + *BitMap |=3D (LShiftU64 (1, Lsbs) - 1); > > + } > > +} > > + > > +/** > > + Set corresponding bits in bitmap table to 0 according to the address > > + > > + @param[in] Address Start address to set for > > + @param[in] BitNumber Number of bits to set > > + @param[in] BitMap Pointer to bitmap which covers the Address > > + > > + @return VOID > > +**/ > > +STATIC > > +VOID > > +ClearBits ( > > + IN EFI_PHYSICAL_ADDRESS Address, > > + IN UINTN BitNumber, > > + IN UINT64 *BitMap > > + ) > > +{ > > + UINTN Lsbs; > > + UINTN Qwords; > > + UINTN Msbs; > > + UINTN StartBit; > > + UINTN EndBit; > > + > > + StartBit =3D (UINTN)GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address); > > + EndBit =3D (StartBit + BitNumber - 1) % GUARDED_HEAP_MAP_ENTRY_BI= TS; > > + > > + if ((StartBit + BitNumber) > GUARDED_HEAP_MAP_ENTRY_BITS) { > > + Msbs =3D (GUARDED_HEAP_MAP_ENTRY_BITS - StartBit) % > > + GUARDED_HEAP_MAP_ENTRY_BITS; > > + Lsbs =3D (EndBit + 1) % GUARDED_HEAP_MAP_ENTRY_BITS; > > + Qwords =3D (BitNumber - Msbs) / GUARDED_HEAP_MAP_ENTRY_BITS; > > + } else { > > + Msbs =3D BitNumber; > > + Lsbs =3D 0; > > + Qwords =3D 0; > > + } > > + > > + if (Msbs > 0) { > > + *BitMap &=3D ~LShiftU64 (LShiftU64 (1, Msbs) - 1, StartBit); > > + BitMap +=3D 1; > > + } > > + > > + if (Qwords > 0) { > > + SetMem64 ((VOID *)BitMap, Qwords * > > GUARDED_HEAP_MAP_ENTRY_BYTES, 0); > > + BitMap +=3D Qwords; > > + } > > + > > + if (Lsbs > 0) { > > + *BitMap &=3D ~(LShiftU64 (1, Lsbs) - 1); > > + } > > +} > > + > > +/** > > + Get corresponding bits in bitmap table according to the address > > + > > + The value of bit 0 corresponds to the status of memory at given Addr= ess. > > + No more than 64 bits can be retrieved in one call. > > + > > + @param[in] Address Start address to retrieve bits for > > + @param[in] BitNumber Number of bits to get > > + @param[in] BitMap Pointer to bitmap which covers the Address > > + > > + @return An integer containing the bits information > > +**/ > > +STATIC > > +UINT64 > > +GetBits ( > > + IN EFI_PHYSICAL_ADDRESS Address, > > + IN UINTN BitNumber, > > + IN UINT64 *BitMap > > + ) > > +{ > > + UINTN StartBit; > > + UINTN EndBit; > > + UINTN Lsbs; > > + UINTN Msbs; > > + UINT64 Result; > > + > > + ASSERT (BitNumber <=3D GUARDED_HEAP_MAP_ENTRY_BITS); > > + > > + StartBit =3D (UINTN)GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address); > > + EndBit =3D (StartBit + BitNumber - 1) % GUARDED_HEAP_MAP_ENTRY_BI= TS; > > + > > + if ((StartBit + BitNumber) > GUARDED_HEAP_MAP_ENTRY_BITS) { > > + Msbs =3D GUARDED_HEAP_MAP_ENTRY_BITS - StartBit; > > + Lsbs =3D (EndBit + 1) % GUARDED_HEAP_MAP_ENTRY_BITS; > > + } else { > > + Msbs =3D BitNumber; > > + Lsbs =3D 0; > > + } > > + > > + Result =3D RShiftU64 ((*BitMap), StartBit) & (LShiftU64 (1, Msbs)= - 1); > > + if (Lsbs > 0) { > > + BitMap +=3D 1; > > + Result |=3D LShiftU64 ((*BitMap) & (LShiftU64 (1, Lsbs) - 1), Msb= s); > > + } > > + > > + return Result; > > +} > > + > > +/** > > + Helper function to allocate pages without Guard for internal uses > > + > > + @param[in] Pages Page number > > + > > + @return Address of memory allocated > > +**/ > > +VOID * > > +PageAlloc ( > > + IN UINTN Pages > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_PHYSICAL_ADDRESS Memory; > > + > > + Status =3D SmmInternalAllocatePages (AllocateAnyPages, > > EfiRuntimeServicesData, > > + Pages, &Memory, FALSE); > > + if (EFI_ERROR (Status)) { > > + Memory =3D 0; > > + } > > + > > + return (VOID *)(UINTN)Memory; > > +} > > + > > +/** > > + Locate the pointer of bitmap from the guarded memory bitmap tables, > > which > > + covers the given Address. > > + > > + @param[in] Address Start address to search the bitmap for > > + @param[in] AllocMapUnit Flag to indicate memory allocation for the= table > > + @param[out] BitMap Pointer to bitmap which covers the Address > > + > > + @return The bit number from given Address to the end of current map > > table > > +**/ > > +UINTN > > +FindGuardedMemoryMap ( > > + IN EFI_PHYSICAL_ADDRESS Address, > > + IN BOOLEAN AllocMapUnit, > > + OUT UINT64 **BitMap > > + ) > > +{ > > + UINTN Level; > > + UINTN LevelShift[GUARDED_HEAP_MAP_TABLE_DEPTH] > > + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_SHIFTS; > > + UINTN LevelMask[GUARDED_HEAP_MAP_TABLE_DEPTH] > > + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_MASKS; > > + UINT64 **GuardMap; > > + UINT64 *MapMemory; > > + UINTN Index; > > + UINTN Size; > > + UINTN BitsToUnitEnd; > > + > > + // > > + // Adjust current map table depth according to the address to access > > + // > > + while (mMapLevel < GUARDED_HEAP_MAP_TABLE_DEPTH > > + && > > + RShiftU64 ( > > + Address, > > + LevelShift[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1] > > + ) !=3D 0) { > > + > > + if (mGuardedMemoryMap !=3D NULL) { > > + Size =3D (LevelMask[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - > > 1] + 1) > > + * GUARDED_HEAP_MAP_ENTRY_BYTES; > > + MapMemory =3D PageAlloc (EFI_SIZE_TO_PAGES (Size)); > > + ASSERT (MapMemory !=3D NULL); > > + > > + SetMem ((VOID *)MapMemory, Size, 0); > > + > > + *(UINT64 **)MapMemory =3D mGuardedMemoryMap; > > + mGuardedMemoryMap =3D MapMemory; > > + } > > + > > + mMapLevel++; > > + > > + } > > + > > + GuardMap =3D &mGuardedMemoryMap; > > + for (Level =3D GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel; > > + Level < GUARDED_HEAP_MAP_TABLE_DEPTH; > > + ++Level) { > > + > > + if (*GuardMap =3D=3D NULL) { > > + if (!AllocMapUnit) { > > + GuardMap =3D NULL; > > + break; > > + } > > + > > + Size =3D (LevelMask[Level] + 1) * GUARDED_HEAP_MAP_ENTRY_BYTES; > > + MapMemory =3D PageAlloc (EFI_SIZE_TO_PAGES (Size)); > > + ASSERT (MapMemory !=3D NULL); > > + > > + SetMem ((VOID *)MapMemory, Size, 0); > > + *GuardMap =3D (UINT64 *)MapMemory; > > + } > > + > > + Index =3D (UINTN)RShiftU64 (Address, LevelShift[Level]); > > + Index &=3D LevelMask[Level]; > > + GuardMap =3D (UINT64 **)((*GuardMap) + Index); > > + > > + } > > + > > + BitsToUnitEnd =3D GUARDED_HEAP_MAP_BITS - > > GUARDED_HEAP_MAP_BIT_INDEX (Address); > > + *BitMap =3D (UINT64 *)GuardMap; > > + > > + return BitsToUnitEnd; > > +} > > + > > +/** > > + Set corresponding bits in bitmap table to 1 according to given memor= y > > range > > + > > + @param[in] Address Memory address to guard from > > + @param[in] NumberOfPages Number of pages to guard > > + > > + @return VOID > > +**/ > > +VOID > > +EFIAPI > > +SetGuardedMemoryBits ( > > + IN EFI_PHYSICAL_ADDRESS Address, > > + IN UINTN NumberOfPages > > + ) > > +{ > > + UINT64 *BitMap; > > + UINTN Bits; > > + UINTN BitsToUnitEnd; > > + > > + while (NumberOfPages > 0) { > > + BitsToUnitEnd =3D FindGuardedMemoryMap (Address, TRUE, &BitMap); > > + ASSERT (BitMap !=3D NULL); > > + > > + if (NumberOfPages > BitsToUnitEnd) { > > + // Cross map unit > > + Bits =3D BitsToUnitEnd; > > + } else { > > + Bits =3D NumberOfPages; > > + } > > + > > + SetBits (Address, Bits, BitMap); > > + > > + NumberOfPages -=3D Bits; > > + Address +=3D EFI_PAGES_TO_SIZE (Bits); > > + } > > +} > > + > > +/** > > + Clear corresponding bits in bitmap table according to given memory r= ange > > + > > + @param[in] Address Memory address to unset from > > + @param[in] NumberOfPages Number of pages to unset guard > > + > > + @return VOID > > +**/ > > +VOID > > +EFIAPI > > +ClearGuardedMemoryBits ( > > + IN EFI_PHYSICAL_ADDRESS Address, > > + IN UINTN NumberOfPages > > + ) > > +{ > > + UINT64 *BitMap; > > + UINTN Bits; > > + UINTN BitsToUnitEnd; > > + > > + while (NumberOfPages > 0) { > > + BitsToUnitEnd =3D FindGuardedMemoryMap (Address, TRUE, &BitMap); > > + ASSERT (BitMap !=3D NULL); > > + > > + if (NumberOfPages > BitsToUnitEnd) { > > + // Cross map unit > > + Bits =3D BitsToUnitEnd; > > + } else { > > + Bits =3D NumberOfPages; > > + } > > + > > + ClearBits (Address, Bits, BitMap); > > + > > + NumberOfPages -=3D Bits; > > + Address +=3D EFI_PAGES_TO_SIZE (Bits); > > + } > > +} > > + > > +/** > > + Retrieve corresponding bits in bitmap table according to given memor= y > > range > > + > > + @param[in] Address Memory address to retrieve from > > + @param[in] NumberOfPages Number of pages to retrieve > > + > > + @return VOID > > +**/ > > +UINTN > > +GetGuardedMemoryBits ( > > + IN EFI_PHYSICAL_ADDRESS Address, > > + IN UINTN NumberOfPages > > + ) > > +{ > > + UINT64 *BitMap; > > + UINTN Bits; > > + UINTN Result; > > + UINTN Shift; > > + UINTN BitsToUnitEnd; > > + > > + ASSERT (NumberOfPages <=3D GUARDED_HEAP_MAP_ENTRY_BITS); > > + > > + Result =3D 0; > > + Shift =3D 0; > > + while (NumberOfPages > 0) { > > + BitsToUnitEnd =3D FindGuardedMemoryMap (Address, FALSE, &BitMap); > > + > > + if (NumberOfPages > BitsToUnitEnd) { > > + // Cross map unit > > + Bits =3D BitsToUnitEnd; > > + } else { > > + Bits =3D NumberOfPages; > > + } > > + > > + if (BitMap !=3D NULL) { > > + Result |=3D LShiftU64 (GetBits (Address, Bits, BitMap), Shift); > > + } > > + > > + Shift +=3D Bits; > > + NumberOfPages -=3D Bits; > > + Address +=3D EFI_PAGES_TO_SIZE (Bits); > > + } > > + > > + return Result; > > +} > > + > > +/** > > + Get bit value in bitmap table for the given address > > + > > + @param[in] Address The address to retrieve for > > + > > + @return 1 or 0 > > +**/ > > +UINTN > > +EFIAPI > > +GetGuardMapBit ( > > + IN EFI_PHYSICAL_ADDRESS Address > > + ) > > +{ > > + UINT64 *GuardMap; > > + > > + FindGuardedMemoryMap (Address, FALSE, &GuardMap); > > + if (GuardMap !=3D NULL) { > > + if (RShiftU64 (*GuardMap, > > + GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address)) & 1) { > > + return 1; > > + } > > + } > > + > > + return 0; > > +} > > + > > +/** > > + Set the bit in bitmap table for the given address > > + > > + @param[in] Address The address to set for > > + > > + @return VOID > > +**/ > > +VOID > > +EFIAPI > > +SetGuardMapBit ( > > + IN EFI_PHYSICAL_ADDRESS Address > > + ) > > +{ > > + UINT64 *GuardMap; > > + UINT64 BitMask; > > + > > + FindGuardedMemoryMap (Address, TRUE, &GuardMap); > > + if (GuardMap !=3D NULL) { > > + BitMask =3D LShiftU64 (1, GUARDED_HEAP_MAP_ENTRY_BIT_INDEX > > (Address)); > > + *GuardMap |=3D BitMask; > > + } > > +} > > + > > +/** > > + Clear the bit in bitmap table for the given address > > + > > + @param[in] Address The address to clear for > > + > > + @return VOID > > +**/ > > +VOID > > +EFIAPI > > +ClearGuardMapBit ( > > + IN EFI_PHYSICAL_ADDRESS Address > > + ) > > +{ > > + UINT64 *GuardMap; > > + UINTN BitMask; > > + > > + FindGuardedMemoryMap (Address, TRUE, &GuardMap); > > + if (GuardMap !=3D NULL) { > > + BitMask =3D LShiftU64 (1, GUARDED_HEAP_MAP_ENTRY_BIT_INDEX > > (Address)); > > + *GuardMap &=3D ~BitMask; > > + } > > +} > > + > > +/** > > + Check to see if the page at the given address is a Guard page or not > > + > > + @param[in] Address The address to check for > > + > > + @return TRUE The page at Address is a Guard page > > + @return FALSE The page at Address is not a Guard page > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsGuardPage ( > > + IN EFI_PHYSICAL_ADDRESS Address > > + ) > > +{ > > + UINTN BitMap; > > + > > + BitMap =3D GetGuardedMemoryBits (Address - EFI_PAGE_SIZE, 3); > > + return (BitMap =3D=3D 0b001 || BitMap =3D=3D 0b100 || BitMap =3D=3D = 0b101); > > +} > > + > > +/** > > + Check to see if the page at the given address is a head Guard page o= r not > > + > > + @param[in] Address The address to check for > > + > > + @return TRUE The page at Address is a head Guard page > > + @return FALSE The page at Address is not a head Guard page > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsHeadGuard ( > > + IN EFI_PHYSICAL_ADDRESS Address > > + ) > > +{ > > + return (GetGuardedMemoryBits (Address, 2) =3D=3D 0b10); > > +} > > + > > +/** > > + Check to see if the page at the given address is a tail Guard page o= r not > > + > > + @param[in] Address The address to check for > > + > > + @return TRUE The page at Address is a tail Guard page > > + @return FALSE The page at Address is not a tail Guard page > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsTailGuard ( > > + IN EFI_PHYSICAL_ADDRESS Address > > + ) > > +{ > > + return (GetGuardedMemoryBits (Address - EFI_PAGE_SIZE, 2) =3D=3D 0b0= 1); > > +} > > + > > +/** > > + Check to see if the page at the given address is guarded or not > > + > > + @param[in] Address The address to check for > > + > > + @return TRUE The page at Address is guarded > > + @return FALSE The page at Address is not guarded > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsMemoryGuarded ( > > + IN EFI_PHYSICAL_ADDRESS Address > > + ) > > +{ > > + return (GetGuardMapBit (Address) =3D=3D 1); > > +} > > + > > +/** > > + Set the page at the given address to be a Guard page. > > + > > + This is done by changing the page table attribute to be NOT PRSENT. > > + > > + @param[in] Address Page address to Guard at > > + > > + @return VOID > > +**/ > > +VOID > > +EFIAPI > > +SetGuardPage ( > > + IN EFI_PHYSICAL_ADDRESS BaseAddress > > + ) > > +{ > > + if (mIsSmmCpuMode) { > > + SmmSetMemoryAttributes (BaseAddress, EFI_PAGE_SIZE, > > EFI_MEMORY_RP); > > + } > > +} > > + > > +/** > > + Unset the Guard page at the given address to the normal memory. > > + > > + This is done by changing the page table attribute to be PRSENT. > > + > > + @param[in] Address Page address to Guard at > > + > > + @return VOID > > +**/ > > +VOID > > +EFIAPI > > +UnsetGuardPage ( > > + IN EFI_PHYSICAL_ADDRESS BaseAddress > > + ) > > +{ > > + if (mIsSmmCpuMode) { > > + SmmClearMemoryAttributes (BaseAddress, EFI_PAGE_SIZE, > > EFI_MEMORY_RP); > > + } > > +} > > + > > +/** > > + Check to see if the memory at the given address should be guarded or= not > > + > > + @param[in] MemoryType Memory type to check > > + @param[in] AllocateType Allocation type to check > > + @param[in] PageOrPool Indicate a page allocation or pool alloc= ation > > + > > + > > + @return TRUE The given type of memory should be guarded > > + @return FALSE The given type of memory should not be guarded > > +**/ > > +BOOLEAN > > +IsMemoryTypeToGuard ( > > + IN EFI_MEMORY_TYPE MemoryType, > > + IN EFI_ALLOCATE_TYPE AllocateType, > > + IN UINT8 PageOrPool > > + ) > > +{ > > + UINT64 TestBit; > > + UINT64 ConfigBit; > > + > > + if ((PcdGet8 (PcdHeapGuardPropertyMask) & PageOrPool) =3D=3D 0 || > > + AllocateType =3D=3D AllocateAddress) { > > + return FALSE; > > + } > > + > > + ConfigBit =3D 0; > > + if (PageOrPool & GUARD_HEAP_TYPE_POOL) { > > + ConfigBit |=3D PcdGet64 (PcdHeapGuardPoolType); > > + } > > + > > + if (PageOrPool & GUARD_HEAP_TYPE_PAGE) { > > + ConfigBit |=3D PcdGet64 (PcdHeapGuardPageType); > > + } > > + > > + if (MemoryType =3D=3D EfiRuntimeServicesData || > > + MemoryType =3D=3D EfiRuntimeServicesCode) { > > + TestBit =3D LShiftU64 (1, MemoryType); > > + } else if (MemoryType =3D=3D EfiMaxMemoryType) { > > + TestBit =3D (UINT64)-1; > > + } else { > > + TestBit =3D 0; > > + } > > + > > + return ((ConfigBit & TestBit) !=3D 0); > > +} > > + > > +/** > > + Check to see if the pool at the given address should be guarded or n= ot > > + > > + @param[in] MemoryType Pool type to check > > + > > + > > + @return TRUE The given type of pool should be guarded > > + @return FALSE The given type of pool should not be guarded > > +**/ > > +BOOLEAN > > +IsPoolTypeToGuard ( > > + IN EFI_MEMORY_TYPE MemoryType > > + ) > > +{ > > + return IsMemoryTypeToGuard (MemoryType, AllocateAnyPages, > > + GUARD_HEAP_TYPE_POOL); > > +} > > + > > +/** > > + Check to see if the page at the given address should be guarded or n= ot > > + > > + @param[in] MemoryType Page type to check > > + @param[in] AllocateType Allocation type to check > > + > > + @return TRUE The given type of page should be guarded > > + @return FALSE The given type of page should not be guarded > > +**/ > > +BOOLEAN > > +IsPageTypeToGuard ( > > + IN EFI_MEMORY_TYPE MemoryType, > > + IN EFI_ALLOCATE_TYPE AllocateType > > + ) > > +{ > > + return IsMemoryTypeToGuard (MemoryType, AllocateType, > > GUARD_HEAP_TYPE_PAGE); > > +} > > + > > +/** > > + Check to see if the heap guard is enabled for page and/or pool alloc= ation > > + > > + @return TRUE/FALSE > > +**/ > > +BOOLEAN > > +IsHeapGuardEnabled ( > > + VOID > > + ) > > +{ > > + return IsMemoryTypeToGuard (EfiMaxMemoryType, AllocateAnyPages, > > + GUARD_HEAP_TYPE_POOL|GUARD_HEAP_TYPE_PAG= E); > > +} > > + > > +/** > > + Set head Guard and tail Guard for the given memory range > > + > > + @param[in] Memory Base address of memory to set guard for > > + @param[in] NumberOfPages Memory size in pages > > + > > + @return VOID > > +**/ > > +VOID > > +SetGuardForMemory ( > > + IN EFI_PHYSICAL_ADDRESS Memory, > > + IN UINTN NumberOfPages > > + ) > > +{ > > + EFI_PHYSICAL_ADDRESS GuardPage; > > + > > + // > > + // Set tail Guard > > + // > > + GuardPage =3D Memory + EFI_PAGES_TO_SIZE (NumberOfPages); > > + if (!IsGuardPage (GuardPage)) { > > + SetGuardPage (GuardPage); > > + } > > + > > + // Set head Guard > > + GuardPage =3D Memory - EFI_PAGES_TO_SIZE (1); > > + if (!IsGuardPage (GuardPage)) { > > + SetGuardPage (GuardPage); > > + } > > + > > + // > > + // Mark the memory range as Guarded > > + // > > + SetGuardedMemoryBits (Memory, NumberOfPages); > > +} > > + > > +/** > > + Unset head Guard and tail Guard for the given memory range > > + > > + @param[in] Memory Base address of memory to unset guard fo= r > > + @param[in] NumberOfPages Memory size in pages > > + > > + @return VOID > > +**/ > > +VOID > > +UnsetGuardForMemory ( > > + IN EFI_PHYSICAL_ADDRESS Memory, > > + IN UINTN NumberOfPages > > + ) > > +{ > > + EFI_PHYSICAL_ADDRESS GuardPage; > > + > > + if (NumberOfPages =3D=3D 0) { > > + return; > > + } > > + > > + // > > + // Head Guard must be one page before, if any. > > + // > > + GuardPage =3D Memory - EFI_PAGES_TO_SIZE (1); > > + if (IsHeadGuard (GuardPage)) { > > + if (!IsMemoryGuarded (GuardPage - EFI_PAGES_TO_SIZE (1))) { > > + // > > + // If the head Guard is not a tail Guard of adjacent memory bloc= k, > > + // unset it. > > + // > > + UnsetGuardPage (GuardPage); > > + } > > + } else if (IsMemoryGuarded (GuardPage)) { > > + // > > + // Pages before memory to free are still in Guard. It's a partial = free > > + // case. Turn first page of memory block to free into a new Guard. > > + // > > + SetGuardPage (Memory); > > + } > > + > > + // > > + // Tail Guard must be the page after this memory block to free, if a= ny. > > + // > > + GuardPage =3D Memory + EFI_PAGES_TO_SIZE (NumberOfPages); > > + if (IsTailGuard (GuardPage)) { > > + if (!IsMemoryGuarded (GuardPage + EFI_PAGES_TO_SIZE (1))) { > > + // > > + // If the tail Guard is not a head Guard of adjacent memory bloc= k, > > + // free it; otherwise, keep it. > > + // > > + UnsetGuardPage (GuardPage); > > + } > > + } else if (IsMemoryGuarded (GuardPage)) { > > + // > > + // Pages after memory to free are still in Guard. It's a partial f= ree > > + // case. We need to keep one page to be a head Guard. > > + // > > + SetGuardPage (GuardPage - EFI_PAGES_TO_SIZE (1)); > > + } > > + > > + // > > + // No matter what, we just clear the mark of the Guarded memory. > > + // > > + ClearGuardedMemoryBits(Memory, NumberOfPages); > > +} > > + > > +/** > > + Adjust address of free memory according to existing and/or required > > Guard > > + > > + This function will check if there're existing Guard pages of adjacen= t > > + memory blocks, and try to use it as the Guard page of the memory to = be > > + allocated. > > + > > + @param[in] Start Start address of free memory block > > + @param[in] Size Size of free memory block > > + @param[in] SizeRequested Size of memory to allocate > > + > > + @return The end address of memory block found > > + @return 0 if no enough space for the required size of memory and its > > Guard > > +**/ > > +UINT64 > > +AdjustMemoryS ( > > + IN UINT64 Start, > > + IN UINT64 Size, > > + IN UINT64 SizeRequested > > + ) > > +{ > > + UINT64 Target; > > + > > + Target =3D Start + Size - SizeRequested; > > + > > + // > > + // At least one more page needed for Guard page. > > + // > > + if (Size < (SizeRequested + EFI_PAGES_TO_SIZE (1))) { > > + return 0; > > + } > > + > > + if (!IsGuardPage (Start + Size)) { > > + // No Guard at tail to share. One more page is needed. > > + Target -=3D EFI_PAGES_TO_SIZE (1); > > + } > > + > > + // Out of range? > > + if (Target < Start) { > > + return 0; > > + } > > + > > + // At the edge? > > + if (Target =3D=3D Start) { > > + if (!IsGuardPage (Target - EFI_PAGES_TO_SIZE (1))) { > > + // No enough space for a new head Guard if no Guard at head to s= hare. > > + return 0; > > + } > > + } > > + > > + // OK, we have enough pages for memory and its Guards. Return the En= d > > of the > > + // free space. > > + return Target + SizeRequested - 1; > > +} > > + > > +/** > > + Adjust the start address and number of pages to free according to Gu= ard > > + > > + The purpose of this function is to keep the shared Guard page with > > adjacent > > + memory block if it's still in guard, or free it if no more sharing. = Another > > + is to reserve pages as Guard pages in partial page free situation. > > + > > + @param[in/out] Memory Base address of memory to free > > + @param[in/out] NumberOfPages Size of memory to free > > + > > + @return VOID > > +**/ > > +VOID > > +AdjustMemoryF ( > > + IN OUT EFI_PHYSICAL_ADDRESS *Memory, > > + IN OUT UINTN *NumberOfPages > > + ) > > +{ > > + EFI_PHYSICAL_ADDRESS Start; > > + EFI_PHYSICAL_ADDRESS MemoryToTest; > > + UINTN PagesToFree; > > + > > + if (Memory =3D=3D NULL || NumberOfPages =3D=3D NULL || *NumberOfPage= s =3D=3D > > 0) { > > + return; > > + } > > + > > + Start =3D *Memory; > > + PagesToFree =3D *NumberOfPages; > > + > > + // > > + // Head Guard must be one page before, if any. > > + // > > + MemoryToTest =3D Start - EFI_PAGES_TO_SIZE (1); > > + if (IsHeadGuard (MemoryToTest)) { > > + if (!IsMemoryGuarded (MemoryToTest - EFI_PAGES_TO_SIZE (1))) { > > + // > > + // If the head Guard is not a tail Guard of adjacent memory bloc= k, > > + // free it; otherwise, keep it. > > + // > > + Start -=3D EFI_PAGES_TO_SIZE (1); > > + PagesToFree +=3D 1; > > + } > > + } else if (IsMemoryGuarded (MemoryToTest)) { > > + // > > + // Pages before memory to free are still in Guard. It's a partial = free > > + // case. We need to keep one page to be a tail Guard. > > + // > > + Start +=3D EFI_PAGES_TO_SIZE (1); > > + PagesToFree -=3D 1; > > + } > > + > > + // > > + // Tail Guard must be the page after this memory block to free, if a= ny. > > + // > > + MemoryToTest =3D Start + EFI_PAGES_TO_SIZE (PagesToFree); > > + if (IsTailGuard (MemoryToTest)) { > > + if (!IsMemoryGuarded (MemoryToTest + EFI_PAGES_TO_SIZE (1))) { > > + // > > + // If the tail Guard is not a head Guard of adjacent memory bloc= k, > > + // free it; otherwise, keep it. > > + // > > + PagesToFree +=3D 1; > > + } > > + } else if (IsMemoryGuarded (MemoryToTest)) { > > + // > > + // Pages after memory to free are still in Guard. It's a partial f= ree > > + // case. We need to keep one page to be a head Guard. > > + // > > + PagesToFree -=3D 1; > > + } > > + > > + *Memory =3D Start; > > + *NumberOfPages =3D PagesToFree; > > +} > > + > > +/** > > + Adjust the base and number of pages to really allocate according to = Guard > > + > > + @param[in/out] Memory Base address of free memory > > + @param[in/out] NumberOfPages Size of memory to allocate > > + > > + @return VOID > > +**/ > > +VOID > > +AdjustMemoryA ( > > + IN OUT EFI_PHYSICAL_ADDRESS *Memory, > > + IN OUT UINTN *NumberOfPages > > + ) > > +{ > > + // > > + // FindFreePages() has already taken the Guard into account. It's sa= fe to > > + // adjust the start address and/or number of pages here, to make sur= e > > that > > + // the Guards are also "allocated". > > + // > > + if (!IsGuardPage (*Memory + EFI_PAGES_TO_SIZE (*NumberOfPages))) { > > + // No tail Guard, add one. > > + *NumberOfPages +=3D 1; > > + } > > + > > + if (!IsGuardPage (*Memory - EFI_PAGE_SIZE)) { > > + // No head Guard, add one. > > + *Memory -=3D EFI_PAGE_SIZE; > > + *NumberOfPages +=3D 1; > > + } > > +} > > + > > +/** > > + Adjust the pool head position to make sure the Guard page is adjaven= t to > > + pool tail or pool head. > > + > > + @param[in] Memory Base address of memory allocated > > + @param[in] NoPages Number of pages actually allocated > > + @param[in] Size Size of memory requested > > + (plus pool head/tail overhead) > > + > > + @return Address of pool head > > +**/ > > +VOID * > > +AdjustPoolHeadA ( > > + IN EFI_PHYSICAL_ADDRESS Memory, > > + IN UINTN NoPages, > > + IN UINTN Size > > + ) > > +{ > > + if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) !=3D 0) { > > + // > > + // Pool head is put near the head Guard > > + // > > + return (VOID *)(UINTN)Memory; > > + } > > + > > + // > > + // Pool head is put near the tail Guard > > + // > > + return (VOID *)(UINTN)(Memory + EFI_PAGES_TO_SIZE (NoPages) - Size); > > +} > > + > > +/** > > + Get the page base address according to pool head address > > + > > + @param[in] Memory Head address of pool to free > > + > > + @return Address of pool head > > +**/ > > +VOID * > > +AdjustPoolHeadF ( > > + IN EFI_PHYSICAL_ADDRESS Memory > > + ) > > +{ > > + if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) !=3D 0) { > > + // > > + // Pool head is put near the head Guard > > + // > > + return (VOID *)(UINTN)Memory; > > + } > > + > > + // > > + // Pool head is put near the tail Guard > > + // > > + return (VOID *)(UINTN)(Memory & ~EFI_PAGE_MASK); > > +} > > + > > +/** > > + Helper function of memory allocation with Guard pages > > + > > + @param FreePageList The free page node. > > + @param NumberOfPages Number of pages to be allocated. > > + @param MaxAddress Request to allocate memory below this > > address. > > + @param MemoryType Type of memory requested. > > + > > + @return Memory address of allocated pages. > > +**/ > > +UINTN > > +InternalAllocMaxAddressWithGuard ( > > + IN OUT LIST_ENTRY *FreePageList, > > + IN UINTN NumberOfPages, > > + IN UINTN MaxAddress, > > + IN EFI_MEMORY_TYPE MemoryType > > + > > + ) > > +{ > > + LIST_ENTRY *Node; > > + FREE_PAGE_LIST *Pages; > > + UINTN PagesToAlloc; > > + UINTN HeadGuard; > > + UINTN TailGuard; > > + UINTN Address; > > + > > + for (Node =3D FreePageList->BackLink; Node !=3D FreePageList; > > + Node =3D Node->BackLink) { > > + Pages =3D BASE_CR (Node, FREE_PAGE_LIST, Link); > > + if (Pages->NumberOfPages >=3D NumberOfPages && > > + (UINTN)Pages + EFI_PAGES_TO_SIZE (NumberOfPages) - 1 <=3D > > MaxAddress) { > > + > > + // > > + // We may need 1 or 2 more pages for Guard. Check it out. > > + // > > + PagesToAlloc =3D NumberOfPages; > > + TailGuard =3D (UINTN)Pages + EFI_PAGES_TO_SIZE (Pages- > > >NumberOfPages); > > + if (!IsGuardPage (TailGuard)) { > > + // > > + // Add one if no Guard at the end of current free memory block= . > > + // > > + PagesToAlloc +=3D 1; > > + TailGuard =3D 0; > > + } > > + > > + HeadGuard =3D (UINTN)Pages + > > + EFI_PAGES_TO_SIZE (Pages->NumberOfPages - PagesToAll= oc) - > > + EFI_PAGE_SIZE; > > + if (!IsGuardPage (HeadGuard)) { > > + // > > + // Add one if no Guard at the page before the address to alloc= ate > > + // > > + PagesToAlloc +=3D 1; > > + HeadGuard =3D 0; > > + } > > + > > + if (Pages->NumberOfPages < PagesToAlloc) { > > + // Not enough space to allocate memory with Guards? Try next b= lock. > > + continue; > > + } > > + > > + Address =3D InternalAllocPagesOnOneNode (Pages, PagesToAlloc, > > MaxAddress); > > + ConvertSmmMemoryMapEntry(MemoryType, Address, PagesToAlloc, > > FALSE); > > + CoreFreeMemoryMapStack(); > > + if (!HeadGuard) { > > + // Don't pass the Guard page to user. > > + Address +=3D EFI_PAGE_SIZE; > > + } > > + SetGuardForMemory (Address, NumberOfPages); > > + return Address; > > + } > > + } > > + > > + return (UINTN)(-1); > > +} > > + > > +/** > > + Helper function of memory free with Guard pages > > + > > + @param[in] Memory Base address of memory being free= d. > > + @param[in] NumberOfPages The number of pages to free. > > + @param[in] AddRegion If this memory is new added regio= n. > > + > > + @retval EFI_NOT_FOUND Could not find the entry that covers = the > > range. > > + @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero = or > > NumberOfPages is zero. > > + @return EFI_SUCCESS Pages successfully freed. > > +**/ > > +EFI_STATUS > > +SmmInternalFreePagesExWithGuard ( > > + IN EFI_PHYSICAL_ADDRESS Memory, > > + IN UINTN NumberOfPages, > > + IN BOOLEAN AddRegion > > + ) > > +{ > > + EFI_PHYSICAL_ADDRESS MemoryToFree; > > + UINTN PagesToFree; > > + > > + MemoryToFree =3D Memory; > > + PagesToFree =3D NumberOfPages; > > + > > + AdjustMemoryF (&MemoryToFree, &PagesToFree); > > + UnsetGuardForMemory (Memory, NumberOfPages); > > + > > + return SmmInternalFreePagesEx (MemoryToFree, PagesToFree, > > AddRegion); > > +} > > + > > +/** > > + Set all Guard pages which cannot be set during the non-SMM mode time > > +**/ > > +VOID > > +SetAllGuardPages ( > > + VOID > > + ) > > +{ > > + UINT64 Entries[GUARDED_HEAP_MAP_TABLE_DEPTH] > > + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_MASKS; > > + UINT64 Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH] > > + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_SHIFTS; > > + UINT64 *Tables[GUARDED_HEAP_MAP_TABLE_DEPTH]; > > + UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH]; > > + UINT64 Indices[GUARDED_HEAP_MAP_TABLE_DEPTH]; > > + UINT64 TableEntry; > > + UINT64 Address; > > + UINT64 GuardPage; > > + INTN Level; > > + UINTN Index; > > + BOOLEAN OnGuarding; > > + > > + SetMem64 (Tables, sizeof(Tables), 0); > > + SetMem64 (Addresses, sizeof(Addresses), 0); > > + SetMem64 (Indices, sizeof(Indices), 0); > > + > > + Level =3D GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel; > > + Tables[Level] =3D mGuardedMemoryMap; > > + Address =3D 0; > > + OnGuarding =3D FALSE; > > + > > + DEBUG_CODE ( > > + DumpGuardedMemoryBitmap (); > > + ); > > + > > + while (TRUE) { > > + if (Indices[Level] > Entries[Level]) { > > + Tables[Level] =3D 0; > > + Level -=3D 1; > > + } else { > > + > > + TableEntry =3D Tables[Level][Indices[Level]]; > > + Address =3D Addresses[Level]; > > + > > + if (TableEntry =3D=3D 0) { > > + > > + OnGuarding =3D FALSE; > > + > > + } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) { > > + > > + Level +=3D 1; > > + Tables[Level] =3D (UINT64 *)TableEntry; > > + Addresses[Level] =3D Address; > > + Indices[Level] =3D 0; > > + > > + continue; > > + > > + } else { > > + > > + Index =3D 0; > > + while (Index < GUARDED_HEAP_MAP_ENTRY_BITS) { > > + if ((TableEntry & 1) =3D=3D 1) { > > + if (OnGuarding) { > > + GuardPage =3D 0; > > + } else { > > + GuardPage =3D Address - EFI_PAGE_SIZE; > > + } > > + OnGuarding =3D TRUE; > > + } else { > > + if (OnGuarding) { > > + GuardPage =3D Address; > > + } else { > > + GuardPage =3D 0; > > + } > > + OnGuarding =3D FALSE; > > + } > > + > > + if (GuardPage !=3D 0) { > > + SetGuardPage (GuardPage); > > + } > > + > > + if (TableEntry =3D=3D 0) { > > + break; > > + } > > + > > + TableEntry =3D RShiftU64 (TableEntry, 1); > > + Address +=3D EFI_PAGE_SIZE; > > + Index +=3D 1; > > + } > > + } > > + } > > + > > + if (Level < (GUARDED_HEAP_MAP_TABLE_DEPTH - (INTN)mMapLevel)) { > > + break; > > + } > > + > > + Indices[Level] +=3D 1; > > + Address =3D (Level =3D=3D 0) ? 0 : Addresses[Level - 1]; > > + Addresses[Level] =3D Address | LShiftU64(Indices[Level], Shifts[Le= vel]); > > + > > + } > > +} > > + > > +/** > > + Hook function used to set all Guard pages after entering SMM mode > > +**/ > > +VOID > > +SmmEntryPointMemoryManagementHook ( > > + VOID > > + ) > > +{ > > + EFI_STATUS Status; > > + VOID *SmmCpu; > > + > > + if (!mIsSmmCpuMode) { > > + Status =3D SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, > > &SmmCpu); > > + if (!EFI_ERROR(Status)) { > > + mIsSmmCpuMode =3D TRUE; > > + SetAllGuardPages (); > > + } > > + } > > +} > > + > > +/** > > + Helper function to convert a UINT64 value in binary to a string > > + > > + @param[in] Value Value of a UINT64 integer > > + @param[in] BinString String buffer to contain the conversion resu= lt > > + > > + @return VOID > > +**/ > > +VOID > > +Uint64ToBinString ( > > + IN UINT64 Value, > > + OUT CHAR8 *BinString > > + ) > > +{ > > + UINTN Index; > > + > > + if (BinString =3D=3D NULL) { > > + return; > > + } > > + > > + for (Index =3D 64; Index > 0; --Index) { > > + BinString[Index - 1] =3D '0' + (Value & 1); > > + Value =3D RShiftU64 (Value, 1); > > + } > > + BinString[64] =3D '\0'; > > +} > > + > > +/** > > + Dump the guarded memory bit map > > + > > + @return VOID > > +**/ > > +VOID > > +EFIAPI > > +DumpGuardedMemoryBitmap ( > > + VOID > > + ) > > +{ > > + UINT64 Entries[GUARDED_HEAP_MAP_TABLE_DEPTH] > > + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_MASKS; > > + UINT64 Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH] > > + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_SHIFTS; > > + UINT64 *Tables[GUARDED_HEAP_MAP_TABLE_DEPTH]; > > + UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH]; > > + UINT64 Indices[GUARDED_HEAP_MAP_TABLE_DEPTH]; > > + UINT64 TableEntry; > > + UINT64 Address; > > + INTN Level; > > + UINTN RepeatZero; > > + CHAR8 String[GUARDED_HEAP_MAP_ENTRY_BITS + 1]; > > + CHAR8 *Ruler1 =3D " 3 2" > > + " 1 0"; > > + CHAR8 *Ruler2 =3D "FEDCBA9876543210FEDCBA9876543210" > > + "FEDCBA9876543210FEDCBA9876543210"; > > + > > + if (mGuardedMemoryMap =3D=3D NULL) { > > + return; > > + } > > + > > + DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D" > > + " Guarded Memory Bitmap " > > + "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\r\n")); > > + DEBUG ((DEBUG_INFO, " %a\r\n", Ruler1)); > > + DEBUG ((DEBUG_INFO, " %a\r\n", Ruler2)); > > + > > + > > + SetMem64 (Tables, sizeof(Tables), 0); > > + SetMem64 (Addresses, sizeof(Addresses), 0); > > + SetMem64 (Indices, sizeof(Indices), 0); > > + > > + Level =3D GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel; > > + Tables[Level] =3D mGuardedMemoryMap; > > + Address =3D 0; > > + RepeatZero =3D 0; > > + > > + while (TRUE) { > > + if (Indices[Level] > Entries[Level]) { > > + > > + Tables[Level] =3D 0; > > + Level -=3D 1; > > + RepeatZero =3D 0; > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D" > > + "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\r\n" > > + )); > > + > > + } else { > > + > > + TableEntry =3D Tables[Level][Indices[Level]]; > > + Address =3D Addresses[Level]; > > + > > + if (TableEntry =3D=3D 0) { > > + > > + if (Level =3D=3D GUARDED_HEAP_MAP_TABLE_DEPTH - 1) { > > + if (RepeatZero =3D=3D 0) { > > + Uint64ToBinString(TableEntry, String); > > + DEBUG ((DEBUG_INFO, "%016lx: %a\r\n", Address, String)); > > + } else if (RepeatZero =3D=3D 1) { > > + DEBUG ((DEBUG_INFO, "... : ...\r\n")); > > + } > > + RepeatZero +=3D 1; > > + } > > + > > + } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) { > > + > > + Level +=3D 1; > > + Tables[Level] =3D (UINT64 *)TableEntry; > > + Addresses[Level] =3D Address; > > + Indices[Level] =3D 0; > > + RepeatZero =3D 0; > > + > > + continue; > > + > > + } else { > > + > > + RepeatZero =3D 0; > > + Uint64ToBinString(TableEntry, String); > > + DEBUG ((DEBUG_INFO, "%016lx: %a\r\n", Address, String)); > > + > > + } > > + } > > + > > + if (Level < (GUARDED_HEAP_MAP_TABLE_DEPTH - (INTN)mMapLevel)) { > > + break; > > + } > > + > > + Indices[Level] +=3D 1; > > + Address =3D (Level =3D=3D 0) ? 0 : Addresses[Level - 1]; > > + Addresses[Level] =3D Address | LShiftU64(Indices[Level], Shifts[Le= vel]); > > + > > + } > > +} > > + > > +/** > > + Debug function used to verify if the Guard page is well set or not > > + > > + @param[in] BaseAddress Address of memory to check > > + @param[in] NumberOfPages Size of memory in pages > > + > > + @return TRUE The head Guard and tail Guard are both well set > > + @return FALSE The head Guard and/or tail Guard are not well set > > +**/ > > +BOOLEAN > > +VerifyMemoryGuard ( > > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > > + IN UINTN NumberOfPages > > + ) > > +{ > > + UINT64 *PageEntry; > > + PAGE_ATTRIBUTE Attribute; > > + EFI_PHYSICAL_ADDRESS Address; > > + > > + if (!mIsSmmCpuMode) { > > + return TRUE; > > + } > > + > > + Address =3D BaseAddress - EFI_PAGE_SIZE; > > + PageEntry =3D GetPageTableEntry (Address, &Attribute); > > + if (PageEntry =3D=3D NULL || Attribute !=3D Page4K) { > > + DEBUG ((DEBUG_ERROR, "Head Guard is not set at: %016lx!!!\r\n", > > Address)); > > + DumpGuardedMemoryBitmap (); > > + return FALSE; > > + } > > + > > + if ((*PageEntry & IA32_PG_P) !=3D 0) { > > + DEBUG ((DEBUG_ERROR, "Head Guard is not set at: %016lx > > (%016lX)!!!\r\n", > > + Address, *PageEntry)); > > + *(UINT8 *) Address =3D 0; > > + DumpGuardedMemoryBitmap (); > > + return FALSE; > > + } > > + > > + Address =3D BaseAddress + EFI_PAGES_TO_SIZE (NumberOfPages); > > + PageEntry =3D GetPageTableEntry (Address, &Attribute); > > + if (PageEntry =3D=3D NULL || Attribute !=3D Page4K) { > > + DEBUG ((DEBUG_ERROR, "Tail Guard is not set at: %016lx!!!\r\n", > > Address)); > > + DumpGuardedMemoryBitmap (); > > + return FALSE; > > + } > > + > > + if ((*PageEntry & IA32_PG_P) !=3D 0) { > > + DEBUG ((DEBUG_ERROR, "Tail Guard is not set at: %016lx (%016lX)!!!= \r\n", > > + Address, *PageEntry)); > > + *(UINT8 *) Address =3D 0; > > + DumpGuardedMemoryBitmap (); > > + return FALSE; > > + } > > + > > + return TRUE; > > +} > > + > > diff --git a/MdeModulePkg/Core/PiSmmCore/Misc/HeapGuard.h > > b/MdeModulePkg/Core/PiSmmCore/Misc/HeapGuard.h > > new file mode 100644 > > index 0000000000..ecc10e83a7 > > --- /dev/null > > +++ b/MdeModulePkg/Core/PiSmmCore/Misc/HeapGuard.h > > @@ -0,0 +1,395 @@ > > +/** @file > > + Data structure and functions to allocate and free memory space. > > + > > +Copyright (c) 2017, Intel Corporation. All rights reserved.
> > +This program and the accompanying materials > > +are licensed and made available under the terms and conditions of the = BSD > > License > > +which accompanies this distribution. The full text of the license may= be > > found at > > +http://opensource.org/licenses/bsd-license.php > > + > > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > > BASIS, > > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > > EXPRESS OR IMPLIED. > > + > > +**/ > > + > > +#ifndef _HEAPGUARD_H_ > > +#define _HEAPGUARD_H_ > > + > > +#include "PiSmmCore.h" > > +#include "PageTable.h" > > + > > +// > > +// Following macros are used to define and access the guarded memory > > bitmap > > +// table. > > +// > > +// To simplify the access and reduce the memory used for this table, t= he > > +// table is constructed in the similar way as page table structure but= in > > +// reverse direction, i.e. from bottom growing up to top. > > +// > > +// - 1-bit tracks 1 page (4KB) > > +// - 1-UINT64 map entry tracks 256KB memory > > +// - 1K-UINT64 map table tracks 256MB memory > > +// - Five levels of tables can track any address of memory of 64-bi= t > > +// system, like below. > > +// > > +// 512 * 512 * 512 * 512 * 1K * 64b * 4= K > > +// 111111111 111111111 111111111 111111111 1111111111 111111 > > 111111111111 > > +// 63 54 45 36 27 17 11 = 0 > > +// 9b 9b 9b 9b 10b 6b 12= b > > +// L0 -> L1 -> L2 -> L3 -> L4 -> bits -> pa= ge > > +// 1FF 1FF 1FF 1FF 3FF 3F FF= F > > +// > > +// L4 table has 1K * sizeof(UINT64) =3D 8K (2-page), which can track 2= 56MB > > +// memory. Each table of L0-L3 will be allocated when its memory addre= ss > > +// range is to be tracked. Only 1-page will be allocated each time. Th= is > > +// can save memories used to establish this map table. > > +// > > +// For a normal configuration of system with 4G memory, two levels of > > tables > > +// can track the whole memory, because two levels (L3+L4) of map table= s > > have > > +// already coverred 37-bit of memory address. And for a normal UEFI BI= OS, > > +// less than 128M memory would be consumed during boot. That means we > > just > > +// need > > +// > > +// 1-page (L3) + 2-page (L4) > > +// > > +// memory (3 pages) to track the memory allocation works. In this case= , > > +// there's no need to setup L0-L2 tables. > > +// > > + > > +// > > +// Each entry occupies 8B/64b. 1-page can hold 512 entries, which span= s 9 > > +// bits in address. (512 =3D 1 << 9) > > +// > > +#define BYTE_LENGTH_SHIFT 3 // (8 =3D 1 = << 3) > > + > > +#define GUARDED_HEAP_MAP_TABLE_ENTRY_SHIFT \ > > + (EFI_PAGE_SHIFT - BYTE_LENGTH_SHIFT) > > + > > +#define GUARDED_HEAP_MAP_TABLE_DEPTH 5 > > + > > +// Use UINT64_index + bit_index_of_UINT64 to locate the bit in may > > +#define GUARDED_HEAP_MAP_ENTRY_BIT_SHIFT 6 // (64 =3D 1= << 6) > > + > > +#define GUARDED_HEAP_MAP_ENTRY_BITS \ > > + (1 << GUARDED_HEAP_MAP_ENTRY_BIT_SHIFT) > > + > > +#define GUARDED_HEAP_MAP_ENTRY_BYTES \ > > + (GUARDED_HEAP_MAP_ENTRY_BITS / 8) > > + > > +// L4 table address width: 64 - 9 * 4 - 6 - 12 =3D 10b > > +#define GUARDED_HEAP_MAP_ENTRY_SHIFT \ > > + (GUARDED_HEAP_MAP_ENTRY_BITS \ > > + - GUARDED_HEAP_MAP_TABLE_ENTRY_SHIFT * 4 \ > > + - GUARDED_HEAP_MAP_ENTRY_BIT_SHIFT \ > > + - EFI_PAGE_SHIFT) > > + > > +// L4 table address mask: (1 << 10 - 1) =3D 0x3FF > > +#define GUARDED_HEAP_MAP_ENTRY_MASK \ > > + ((1 << GUARDED_HEAP_MAP_ENTRY_SHIFT) - 1) > > + > > +// Size of each L4 table: (1 << 10) * 8 =3D 8KB =3D 2-page > > +#define GUARDED_HEAP_MAP_SIZE \ > > + ((1 << GUARDED_HEAP_MAP_ENTRY_SHIFT) * > > GUARDED_HEAP_MAP_ENTRY_BYTES) > > + > > +// Memory size tracked by one L4 table: 8KB * 8 * 4KB =3D 256MB > > +#define GUARDED_HEAP_MAP_UNIT_SIZE \ > > + (GUARDED_HEAP_MAP_SIZE * 8 * EFI_PAGE_SIZE) > > + > > +// L4 table entry number: 8KB / 8 =3D 1024 > > +#define GUARDED_HEAP_MAP_ENTRIES_PER_UNIT \ > > + (GUARDED_HEAP_MAP_SIZE / GUARDED_HEAP_MAP_ENTRY_BYTES) > > + > > +// L4 table entry indexing > > +#define GUARDED_HEAP_MAP_ENTRY_INDEX(Address) \ > > + (RShiftU64 (Address, EFI_PAGE_SHIFT \ > > + + GUARDED_HEAP_MAP_ENTRY_BIT_SHIFT) \ > > + & GUARDED_HEAP_MAP_ENTRY_MASK) > > + > > +// L4 table entry bit indexing > > +#define GUARDED_HEAP_MAP_ENTRY_BIT_INDEX(Address) \ > > + (RShiftU64 (Address, EFI_PAGE_SHIFT) \ > > + & ((1 << GUARDED_HEAP_MAP_ENTRY_BIT_SHIFT) - 1)) > > + > > +// > > +// Total bits (pages) tracked by one L4 table (65536-bit) > > +// > > +#define GUARDED_HEAP_MAP_BITS \ > > + (1 << (GUARDED_HEAP_MAP_ENTRY_SHIFT \ > > + + GUARDED_HEAP_MAP_ENTRY_BIT_SHIFT)) > > + > > +// > > +// Bit indexing inside the whole L4 table (0 - 65535) > > +// > > +#define GUARDED_HEAP_MAP_BIT_INDEX(Address) \ > > + (RShiftU64 (Address, EFI_PAGE_SHIFT) \ > > + & ((1 << (GUARDED_HEAP_MAP_ENTRY_SHIFT \ > > + + GUARDED_HEAP_MAP_ENTRY_BIT_SHIFT)) - 1)) > > + > > +// > > +// Memory address bit width tracked by L4 table: 10 + 6 + 12 =3D 28 > > +// > > +#define GUARDED_HEAP_MAP_TABLE_SHIFT = \ > > + (GUARDED_HEAP_MAP_ENTRY_SHIFT + > > GUARDED_HEAP_MAP_ENTRY_BIT_SHIFT \ > > + + EFI_PAGE_SHIFT) > > + > > +// > > +// Macro used to initialize the local array variable for map table tra= versing > > +// {55, 46, 37, 28, 18} > > +// > > +#define GUARDED_HEAP_MAP_TABLE_DEPTH_SHIFTS = \ > > + { = \ > > + GUARDED_HEAP_MAP_TABLE_SHIFT + > > GUARDED_HEAP_MAP_TABLE_ENTRY_SHIFT * 3, \ > > + GUARDED_HEAP_MAP_TABLE_SHIFT + > > GUARDED_HEAP_MAP_TABLE_ENTRY_SHIFT * 2, \ > > + GUARDED_HEAP_MAP_TABLE_SHIFT + > > GUARDED_HEAP_MAP_TABLE_ENTRY_SHIFT, \ > > + GUARDED_HEAP_MAP_TABLE_SHIFT, = \ > > + EFI_PAGE_SHIFT + GUARDED_HEAP_MAP_ENTRY_BIT_SHIFT = \ > > + } > > + > > +// > > +// Masks used to extract address range of each level of table > > +// {0x1FF, 0x1FF, 0x1FF, 0x1FF, 0x3FF} > > +// > > +#define GUARDED_HEAP_MAP_TABLE_DEPTH_MASKS = \ > > + { = \ > > + (1 << GUARDED_HEAP_MAP_TABLE_ENTRY_SHIFT) - 1, = \ > > + (1 << GUARDED_HEAP_MAP_TABLE_ENTRY_SHIFT) - 1, = \ > > + (1 << GUARDED_HEAP_MAP_TABLE_ENTRY_SHIFT) - 1, = \ > > + (1 << GUARDED_HEAP_MAP_TABLE_ENTRY_SHIFT) - 1, = \ > > + (1 << GUARDED_HEAP_MAP_ENTRY_SHIFT) - 1 = \ > > + } > > + > > +// > > +// Memory type to guard (matching the related PCD definition) > > +// > > +#define GUARD_HEAP_TYPE_POOL BIT2 > > +#define GUARD_HEAP_TYPE_PAGE BIT3 > > + > > +typedef struct { > > + UINT32 TailMark; > > + UINT32 HeadMark; > > + EFI_PHYSICAL_ADDRESS Address; > > + LIST_ENTRY Link; > > +} HEAP_GUARD_NODE; > > + > > +/** > > + Set head Guard and tail Guard for the given memory range > > + > > + @param[in] Memory Base address of memory to set guard for > > + @param[in] NumberOfPages Memory size in pages > > + > > + @return VOID > > +**/ > > +VOID > > +SetGuardForMemory ( > > + IN EFI_PHYSICAL_ADDRESS Memory, > > + IN UINTN NumberOfPages > > + ); > > + > > +/** > > + Unset head Guard and tail Guard for the given memory range > > + > > + @param[in] Memory Base address of memory to unset guard fo= r > > + @param[in] NumberOfPages Memory size in pages > > + > > + @return VOID > > +**/ > > +VOID > > +UnsetGuardForMemory ( > > + IN EFI_PHYSICAL_ADDRESS Memory, > > + IN UINTN NumberOfPages > > + ); > > + > > +/** > > + Adjust the base and number of pages to really allocate according to = Guard > > + > > + @param[in/out] Memory Base address of free memory > > + @param[in/out] NumberOfPages Size of memory to allocate > > + > > + @return VOID > > +**/ > > +VOID > > +AdjustMemoryA ( > > + IN OUT EFI_PHYSICAL_ADDRESS *Memory, > > + IN OUT UINTN *NumberOfPages > > + ); > > + > > +/** > > + Adjust the start address and number of pages to free according to Gu= ard > > + > > + The purpose of this function is to keep the shared Guard page with > > adjacent > > + memory block if it's still in guard, or free it if no more sharing. = Another > > + is to reserve pages as Guard pages in partial page free situation. > > + > > + @param[in/out] Memory Base address of memory to free > > + @param[in/out] NumberOfPages Size of memory to free > > + > > + @return VOID > > +**/ > > +VOID > > +AdjustMemoryF ( > > + IN OUT EFI_PHYSICAL_ADDRESS *Memory, > > + IN OUT UINTN *NumberOfPages > > + ); > > + > > +/** > > + Check to see if the pool at the given address should be guarded or n= ot > > + > > + @param[in] MemoryType Pool type to check > > + > > + > > + @return TRUE The given type of pool should be guarded > > + @return FALSE The given type of pool should not be guarded > > +**/ > > +BOOLEAN > > +IsPoolTypeToGuard ( > > + IN EFI_MEMORY_TYPE MemoryType > > + ); > > + > > +/** > > + Check to see if the page at the given address should be guarded or n= ot > > + > > + @param[in] MemoryType Page type to check > > + @param[in] AllocateType Allocation type to check > > + > > + @return TRUE The given type of page should be guarded > > + @return FALSE The given type of page should not be guarded > > +**/ > > +BOOLEAN > > +IsPageTypeToGuard ( > > + IN EFI_MEMORY_TYPE MemoryType, > > + IN EFI_ALLOCATE_TYPE AllocateType > > + ); > > + > > +/** > > + Check to see if the page at the given address is guarded or not > > + > > + @param[in] Address The address to check for > > + > > + @return TRUE The page at Address is guarded > > + @return FALSE The page at Address is not guarded > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsMemoryGuarded ( > > + IN EFI_PHYSICAL_ADDRESS Address > > + ); > > + > > +/** > > + Check to see if the page at the given address is a Guard page or not > > + > > + @param[in] Address The address to check for > > + > > + @return TRUE The page at Address is a Guard page > > + @return FALSE The page at Address is not a Guard page > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsGuardPage ( > > + IN EFI_PHYSICAL_ADDRESS Address > > + ); > > + > > +/** > > + Dump the guarded memory bit map > > + > > + @return VOID > > +**/ > > +VOID > > +EFIAPI > > +DumpGuardedMemoryBitmap ( > > + VOID > > + ); > > + > > +/** > > + Adjust the pool head position to make sure the Guard page is adjaven= t to > > + pool tail or pool head. > > + > > + @param[in] Memory Base address of memory allocated > > + @param[in] NoPages Number of pages actually allocated > > + @param[in] Size Size of memory requested > > + (plus pool head/tail overhead) > > + > > + @return Address of pool head > > +**/ > > +VOID * > > +AdjustPoolHeadA ( > > + IN EFI_PHYSICAL_ADDRESS Memory, > > + IN UINTN NoPages, > > + IN UINTN Size > > + ); > > + > > +/** > > + Get the page base address according to pool head address > > + > > + @param[in] Memory Head address of pool to free > > + > > + @return Address of pool head > > +**/ > > +VOID * > > +AdjustPoolHeadF ( > > + IN EFI_PHYSICAL_ADDRESS Memory > > + ); > > + > > +/** > > + Helper function of memory allocation with Guard pages > > + > > + @param FreePageList The free page node. > > + @param NumberOfPages Number of pages to be allocated. > > + @param MaxAddress Request to allocate memory below this > > address. > > + @param MemoryType Type of memory requested. > > + > > + @return Memory address of allocated pages. > > +**/ > > +UINTN > > +InternalAllocMaxAddressWithGuard ( > > + IN OUT LIST_ENTRY *FreePageList, > > + IN UINTN NumberOfPages, > > + IN UINTN MaxAddress, > > + IN EFI_MEMORY_TYPE MemoryType > > + ); > > + > > +/** > > + Helper function of memory free with Guard pages > > + > > + @param[in] Memory Base address of memory being free= d. > > + @param[in] NumberOfPages The number of pages to free. > > + @param[in] AddRegion If this memory is new added regio= n. > > + > > + @retval EFI_NOT_FOUND Could not find the entry that covers = the > > range. > > + @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero = or > > NumberOfPages is zero. > > + @return EFI_SUCCESS Pages successfully freed. > > +**/ > > +EFI_STATUS > > +SmmInternalFreePagesExWithGuard ( > > + IN EFI_PHYSICAL_ADDRESS Memory, > > + IN UINTN NumberOfPages, > > + IN BOOLEAN AddRegion > > + ); > > + > > +/** > > + Check to see if the heap guard is enabled for page and/or pool alloc= ation > > + > > + @return TRUE/FALSE > > +**/ > > +BOOLEAN > > +IsHeapGuardEnabled ( > > + VOID > > + ); > > + > > +/** > > + Debug function used to verify if the Guard page is well set or not > > + > > + @param[in] BaseAddress Address of memory to check > > + @param[in] NumberOfPages Size of memory in pages > > + > > + @return TRUE The head Guard and tail Guard are both well set > > + @return FALSE The head Guard and/or tail Guard are not well set > > +**/ > > +BOOLEAN > > +VerifyMemoryGuard ( > > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > > + IN UINTN NumberOfPages > > + ); > > + > > +extern BOOLEAN mOnGuarding; > > + > > +#endif > > diff --git a/MdeModulePkg/Core/PiSmmCore/Misc/PageTable.c > > b/MdeModulePkg/Core/PiSmmCore/Misc/PageTable.c > > new file mode 100644 > > index 0000000000..d41b3e923f > > --- /dev/null > > +++ b/MdeModulePkg/Core/PiSmmCore/Misc/PageTable.c > > @@ -0,0 +1,704 @@ > > +/** @file > > + > > +Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
> > +This program and the accompanying materials > > +are licensed and made available under the terms and conditions of the = BSD > > License > > +which accompanies this distribution. The full text of the license may= be > > found at > > +http://opensource.org/licenses/bsd-license.php > > + > > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > > BASIS, > > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > > EXPRESS OR IMPLIED. > > + > > +**/ > > + > > +#include "PiSmmCore.h" > > +#include "PageTable.h" > > + > > +#include > > + > > +UINT64 mAddressEncMask =3D 0; > > +UINT8 mPhysicalAddressBits =3D 32; > > + > > +PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] =3D { > > + {PageNone, 0, 0}, > > + {Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64}, > > + {Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64}, > > + {Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64}, > > +}; > > + > > +/** > > + Calculate the maximum support address. > > + > > + @return the maximum support address. > > +**/ > > +UINT8 > > +CalculateMaximumSupportAddress ( > > + VOID > > + ) > > +{ > > + UINT32 RegEax; > > + UINT8 PhysicalAddressBits; > > + VOID *Hob; > > + > > + // > > + // Get physical address bits supported. > > + // > > + Hob =3D GetFirstHob (EFI_HOB_TYPE_CPU); > > + if (Hob !=3D NULL) { > > + PhysicalAddressBits =3D ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; > > + } else { > > + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); > > + if (RegEax >=3D 0x80000008) { > > + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); > > + PhysicalAddressBits =3D (UINT8) RegEax; > > + } else { > > + PhysicalAddressBits =3D 36; > > + } > > + } > > + > > + // > > + // IA-32e paging translates 48-bit linear addresses to 52-bit physic= al > > addresses. > > + // > > + ASSERT (PhysicalAddressBits <=3D 52); > > + if (PhysicalAddressBits > 48) { > > + PhysicalAddressBits =3D 48; > > + } > > + return PhysicalAddressBits; > > +} > > + > > +/** > > + Return page table base. > > + > > + @return page table base. > > +**/ > > +UINTN > > +GetPageTableBase ( > > + VOID > > + ) > > +{ > > + return (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64); > > +} > > + > > +/** > > + Return length according to page attributes. > > + > > + @param[in] PageAttributes The page attribute of the page entry. > > + > > + @return The length of page entry. > > +**/ > > +UINTN > > +PageAttributeToLength ( > > + IN PAGE_ATTRIBUTE PageAttribute > > + ) > > +{ > > + if (PageAttribute <=3D Page1G) { > > + return (UINTN)mPageAttributeTable[PageAttribute].Length; > > + } > > + return 0; > > +} > > + > > +/** > > + Return address mask according to page attributes. > > + > > + @param[in] PageAttributes The page attribute of the page entry. > > + > > + @return The address mask of page entry. > > +**/ > > +UINTN > > +PageAttributeToMask ( > > + IN PAGE_ATTRIBUTE PageAttribute > > + ) > > +{ > > + if (PageAttribute <=3D Page1G) { > > + return (UINTN)mPageAttributeTable[PageAttribute].AddressMask; > > + } > > + return 0; > > +} > > + > > +/** > > + Return page table entry to match the address. > > + > > + @param[in] Address The address to be checked. > > + @param[out] PageAttributes The page attribute of the page entry. > > + > > + @return The page entry. > > +**/ > > +VOID * > > +GetPageTableEntry ( > > + IN PHYSICAL_ADDRESS Address, > > + OUT PAGE_ATTRIBUTE *PageAttribute > > + ) > > +{ > > + UINTN Index1; > > + UINTN Index2; > > + UINTN Index3; > > + UINTN Index4; > > + UINT64 *L1PageTable; > > + UINT64 *L2PageTable; > > + UINT64 *L3PageTable; > > + UINT64 *L4PageTable; > > + > > + Index4 =3D ((UINTN)RShiftU64 (Address, 39)) & PAGING_PAE_INDEX_MASK; > > + Index3 =3D ((UINTN)Address >> 30) & PAGING_PAE_INDEX_MASK; > > + Index2 =3D ((UINTN)Address >> 21) & PAGING_PAE_INDEX_MASK; > > + Index1 =3D ((UINTN)Address >> 12) & PAGING_PAE_INDEX_MASK; > > + > > + if (sizeof(UINTN) =3D=3D sizeof(UINT64)) { > > + L4PageTable =3D (UINT64 *)GetPageTableBase (); > > + if (L4PageTable[Index4] =3D=3D 0) { > > + *PageAttribute =3D PageNone; > > + return NULL; > > + } > > + > > + L3PageTable =3D (UINT64 *)(UINTN)(L4PageTable[Index4] & > > ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64); > > + } else { > > + L3PageTable =3D (UINT64 *)GetPageTableBase (); > > + } > > + if (L3PageTable[Index3] =3D=3D 0) { > > + *PageAttribute =3D PageNone; > > + return NULL; > > + } > > + if ((L3PageTable[Index3] & IA32_PG_PS) !=3D 0) { > > + // 1G > > + *PageAttribute =3D Page1G; > > + return &L3PageTable[Index3]; > > + } > > + > > + L2PageTable =3D (UINT64 *)(UINTN)(L3PageTable[Index3] & > > ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64); > > + if (L2PageTable[Index2] =3D=3D 0) { > > + *PageAttribute =3D PageNone; > > + return NULL; > > + } > > + if ((L2PageTable[Index2] & IA32_PG_PS) !=3D 0) { > > + // 2M > > + *PageAttribute =3D Page2M; > > + return &L2PageTable[Index2]; > > + } > > + > > + // 4k > > + L1PageTable =3D (UINT64 *)(UINTN)(L2PageTable[Index2] & > > ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64); > > + if ((L1PageTable[Index1] =3D=3D 0) && (Address !=3D 0)) { > > + *PageAttribute =3D PageNone; > > + return NULL; > > + } > > + *PageAttribute =3D Page4K; > > + return &L1PageTable[Index1]; > > +} > > + > > +/** > > + Return memory attributes of page entry. > > + > > + @param[in] PageEntry The page entry. > > + > > + @return Memory attributes of page entry. > > +**/ > > +UINT64 > > +GetAttributesFromPageEntry ( > > + IN UINT64 *PageEntry > > + ) > > +{ > > + UINT64 Attributes; > > + Attributes =3D 0; > > + if ((*PageEntry & IA32_PG_P) =3D=3D 0) { > > + Attributes |=3D EFI_MEMORY_RP; > > + } > > + if ((*PageEntry & IA32_PG_RW) =3D=3D 0) { > > + Attributes |=3D EFI_MEMORY_RO; > > + } > > + if ((*PageEntry & IA32_PG_NX) !=3D 0) { > > + Attributes |=3D EFI_MEMORY_XP; > > + } > > + return Attributes; > > +} > > + > > +/** > > + Modify memory attributes of page entry. > > + > > + @param[in] PageEntry The page entry. > > + @param[in] Attributes The bit mask of attributes to modify f= or the > > memory region. > > + @param[in] IsSet TRUE means to set attributes. FALSE me= ans to > > clear attributes. > > + @param[out] IsModified TRUE means page table modified. FALSE > > means page table not modified. > > +**/ > > +VOID > > +ConvertPageEntryAttribute ( > > + IN UINT64 *PageEntry, > > + IN UINT64 Attributes, > > + IN BOOLEAN IsSet, > > + OUT BOOLEAN *IsModified > > + ) > > +{ > > + UINT64 CurrentPageEntry; > > + UINT64 NewPageEntry; > > + > > + CurrentPageEntry =3D *PageEntry; > > + NewPageEntry =3D CurrentPageEntry; > > + if ((Attributes & EFI_MEMORY_RP) !=3D 0) { > > + if (IsSet) { > > + NewPageEntry &=3D ~(UINT64)IA32_PG_P; > > + } else { > > + NewPageEntry |=3D IA32_PG_P; > > + } > > + } > > + if ((Attributes & EFI_MEMORY_RO) !=3D 0) { > > + if (IsSet) { > > + NewPageEntry &=3D ~(UINT64)IA32_PG_RW; > > + } else { > > + NewPageEntry |=3D IA32_PG_RW; > > + } > > + } > > + if ((Attributes & EFI_MEMORY_XP) !=3D 0) { > > + if (IsSet) { > > + NewPageEntry |=3D IA32_PG_NX; > > + } else { > > + NewPageEntry &=3D ~IA32_PG_NX; > > + } > > + } > > + > > + if (CurrentPageEntry !=3D NewPageEntry) { > > + *PageEntry =3D NewPageEntry; > > + *IsModified =3D TRUE; > > + DEBUG ((DEBUG_INFO, "(SMM)ConvertPageEntryAttribute 0x%lx", > > CurrentPageEntry)); > > + DEBUG ((DEBUG_INFO, "->0x%lx\n", NewPageEntry)); > > + } else { > > + *IsModified =3D FALSE; > > + } > > +} > > + > > +/** > > + This function returns if there is need to split page entry. > > + > > + @param[in] BaseAddress The base address to be checked. > > + @param[in] Length The length to be checked. > > + @param[in] PageEntry The page entry to be checked. > > + @param[in] PageAttribute The page attribute of the page entry. > > + > > + @retval SplitAttributes on if there is need to split page entry. > > +**/ > > +PAGE_ATTRIBUTE > > +NeedSplitPage ( > > + IN PHYSICAL_ADDRESS BaseAddress, > > + IN UINT64 Length, > > + IN UINT64 *PageEntry, > > + IN PAGE_ATTRIBUTE PageAttribute > > + ) > > +{ > > + UINT64 PageEntryLength; > > + > > + PageEntryLength =3D PageAttributeToLength (PageAttribute); > > + > > + if (((BaseAddress & (PageEntryLength - 1)) =3D=3D 0) && (Length >=3D > > PageEntryLength)) { > > + return PageNone; > > + } > > + > > + if (((BaseAddress & PAGING_2M_MASK) !=3D 0) || (Length < SIZE_2MB)) = { > > + return Page4K; > > + } > > + > > + return Page2M; > > +} > > + > > +/** > > + This function splits one page entry to small page entries. > > + > > + @param[in] PageEntry The page entry to be splitted. > > + @param[in] PageAttribute The page attribute of the page entry. > > + @param[in] SplitAttribute How to split the page entry. > > + > > + @retval RETURN_SUCCESS The page entry is splitted. > > + @retval RETURN_UNSUPPORTED The page entry does not support to > > be splitted. > > + @retval RETURN_OUT_OF_RESOURCES No resource to split page entry. > > +**/ > > +RETURN_STATUS > > +SplitPage ( > > + IN UINT64 *PageEntry, > > + IN PAGE_ATTRIBUTE PageAttribute, > > + IN PAGE_ATTRIBUTE SplitAttribute > > + ) > > +{ > > + UINT64 BaseAddress; > > + UINT64 *NewPageEntry; > > + UINTN Index; > > + > > + ASSERT (PageAttribute =3D=3D Page2M || PageAttribute =3D=3D Page1G); > > + > > + if (PageAttribute =3D=3D Page2M) { > > + // > > + // Split 2M to 4K > > + // > > + ASSERT (SplitAttribute =3D=3D Page4K); > > + if (SplitAttribute =3D=3D Page4K) { > > + NewPageEntry =3D PageAlloc (1); > > + DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry)); > > + if (NewPageEntry =3D=3D NULL) { > > + return RETURN_OUT_OF_RESOURCES; > > + } > > + BaseAddress =3D *PageEntry & PAGING_2M_ADDRESS_MASK_64; > > + for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) { > > + NewPageEntry[Index] =3D (BaseAddress + SIZE_4KB * Index) | > > mAddressEncMask | ((*PageEntry) & PAGE_PROGATE_BITS); > > + } > > + (*PageEntry) =3D (UINT64)(UINTN)NewPageEntry | mAddressEncMask | > > PAGE_ATTRIBUTE_BITS; > > + return RETURN_SUCCESS; > > + } else { > > + return RETURN_UNSUPPORTED; > > + } > > + } else if (PageAttribute =3D=3D Page1G) { > > + // > > + // Split 1G to 2M > > + // No need support 1G->4K directly, we should use 1G->2M, then 2M-= >4K > > to get more compact page table. > > + // > > + ASSERT (SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page= 4K); > > + if ((SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K)= ) { > > + NewPageEntry =3D PageAlloc (1); > > + DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry)); > > + if (NewPageEntry =3D=3D NULL) { > > + return RETURN_OUT_OF_RESOURCES; > > + } > > + BaseAddress =3D *PageEntry & PAGING_1G_ADDRESS_MASK_64; > > + for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) { > > + NewPageEntry[Index] =3D (BaseAddress + SIZE_2MB * Index) | > > mAddressEncMask | IA32_PG_PS | ((*PageEntry) & PAGE_PROGATE_BITS); > > + } > > + (*PageEntry) =3D (UINT64)(UINTN)NewPageEntry | mAddressEncMask | > > PAGE_ATTRIBUTE_BITS; > > + return RETURN_SUCCESS; > > + } else { > > + return RETURN_UNSUPPORTED; > > + } > > + } else { > > + return RETURN_UNSUPPORTED; > > + } > > +} > > + > > +/** > > + This function modifies the page attributes for the memory region spe= cified > > by BaseAddress and > > + Length from their current attributes to the attributes specified by > > Attributes. > > + > > + Caller should make sure BaseAddress and Length is at page boundary. > > + > > + @param[in] BaseAddress The physical address that is the start= address > > of a memory region. > > + @param[in] Length The size in bytes of the memory region= . > > + @param[in] Attributes The bit mask of attributes to modify f= or the > > memory region. > > + @param[in] IsSet TRUE means to set attributes. FALSE me= ans to > > clear attributes. > > + @param[out] IsSplitted TRUE means page table splitted. FALSE = means > > page table not splitted. > > + @param[out] IsModified TRUE means page table modified. FALSE > > means page table not modified. > > + > > + @retval RETURN_SUCCESS The attributes were modified for th= e > > memory region. > > + @retval RETURN_ACCESS_DENIED The attributes for the memory > > resource range specified by > > + BaseAddress and Length cannot be mo= dified. > > + @retval RETURN_INVALID_PARAMETER Length is zero. > > + Attributes specified an illegal com= bination of attributes > > that > > + cannot be set together. > > + @retval RETURN_OUT_OF_RESOURCES There are not enough system > > resources to modify the attributes of > > + the memory resource range. > > + @retval RETURN_UNSUPPORTED The processor does not support one > > or more bytes of the memory > > + resource range specified by BaseAdd= ress and Length. > > + The bit mask of attributes is not s= upport for the memory > > resource > > + range specified by BaseAddress and = Length. > > +**/ > > +RETURN_STATUS > > +EFIAPI > > +ConvertMemoryPageAttributes ( > > + IN PHYSICAL_ADDRESS BaseAddress, > > + IN UINT64 Length, > > + IN UINT64 Attributes, > > + IN BOOLEAN IsSet, > > + OUT BOOLEAN *IsSplitted, OPTIONAL > > + OUT BOOLEAN *IsModified OPTIONAL > > + ) > > +{ > > + UINT64 *PageEntry; > > + PAGE_ATTRIBUTE PageAttribute; > > + UINTN PageEntryLength; > > + PAGE_ATTRIBUTE SplitAttribute; > > + RETURN_STATUS Status; > > + BOOLEAN IsEntryModified; > > + EFI_PHYSICAL_ADDRESS MaximumSupportMemAddress; > > + > > + ASSERT (Attributes !=3D 0); > > + ASSERT ((Attributes & ~(EFI_MEMORY_RP | EFI_MEMORY_RO | > > EFI_MEMORY_XP)) =3D=3D 0); > > + > > + ASSERT ((BaseAddress & (SIZE_4KB - 1)) =3D=3D 0); > > + ASSERT ((Length & (SIZE_4KB - 1)) =3D=3D 0); > > + > > + if (Length =3D=3D 0) { > > + return RETURN_INVALID_PARAMETER; > > + } > > + > > + MaximumSupportMemAddress =3D > > (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, mPhysicalAddressBits) - 1); > > + if (BaseAddress > MaximumSupportMemAddress) { > > + return RETURN_UNSUPPORTED; > > + } > > + if (Length > MaximumSupportMemAddress) { > > + return RETURN_UNSUPPORTED; > > + } > > + if ((Length !=3D 0) && (BaseAddress > MaximumSupportMemAddress - > > (Length - 1))) { > > + return RETURN_UNSUPPORTED; > > + } > > + > > +// DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - > > %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes)); > > + > > + if (IsSplitted !=3D NULL) { > > + *IsSplitted =3D FALSE; > > + } > > + if (IsModified !=3D NULL) { > > + *IsModified =3D FALSE; > > + } > > + > > + // > > + // Below logic is to check 2M/4K page to make sure we do not waste > > memory. > > + // > > + while (Length !=3D 0) { > > + PageEntry =3D GetPageTableEntry (BaseAddress, &PageAttribute); > > + if (PageEntry =3D=3D NULL) { > > + return RETURN_UNSUPPORTED; > > + } > > + PageEntryLength =3D PageAttributeToLength (PageAttribute); > > + SplitAttribute =3D NeedSplitPage (BaseAddress, Length, PageEntry, > > PageAttribute); > > + if (SplitAttribute =3D=3D PageNone) { > > + ConvertPageEntryAttribute (PageEntry, Attributes, IsSet, > > &IsEntryModified); > > + if (IsEntryModified) { > > + if (IsModified !=3D NULL) { > > + *IsModified =3D TRUE; > > + } > > + } > > + // > > + // Convert success, move to next > > + // > > + BaseAddress +=3D PageEntryLength; > > + Length -=3D PageEntryLength; > > + } else { > > + Status =3D SplitPage (PageEntry, PageAttribute, SplitAttribute); > > + if (RETURN_ERROR (Status)) { > > + return RETURN_UNSUPPORTED; > > + } > > + if (IsSplitted !=3D NULL) { > > + *IsSplitted =3D TRUE; > > + } > > + if (IsModified !=3D NULL) { > > + *IsModified =3D TRUE; > > + } > > + // > > + // Just split current page > > + // Convert success in next around > > + // > > + } > > + } > > + > > + return RETURN_SUCCESS; > > +} > > + > > +/** > > + FlushTlb on current processor. > > + > > + @param[in,out] Buffer Pointer to private data buffer. > > +**/ > > +VOID > > +EFIAPI > > +FlushTlbOnCurrentProcessor ( > > + IN OUT VOID *Buffer > > + ) > > +{ > > + CpuFlushTlb (); > > +} > > + > > +/** > > + FlushTlb for all processors. > > +**/ > > +VOID > > +FlushTlbForAll ( > > + VOID > > + ) > > +{ > > + UINTN Index; > > + > > + FlushTlbOnCurrentProcessor (NULL); > > + > > + if (gSmmCoreSmst.SmmStartupThisAp =3D=3D NULL) { > > + DEBUG ((DEBUG_WARN, "Cannot flush TLB for APs\r\n")); > > + return; > > + } > > + > > + for (Index =3D 0; Index < gSmmCoreSmst.NumberOfCpus; Index++) { > > + if (Index !=3D gSmmCoreSmst.CurrentlyExecutingCpu) { > > + // Force to start up AP in blocking mode, > > + gSmmCoreSmst.SmmStartupThisAp (FlushTlbOnCurrentProcessor, Index= , > > NULL); > > + // Do not check return status, because AP might not be present i= n some > > corner cases. > > + } > > + } > > +} > > + > > +/** > > + This function sets the attributes for the memory region specified by > > BaseAddress and > > + Length from their current attributes to the attributes specified by > > Attributes. > > + > > + @param[in] BaseAddress The physical address that is the start= address > > of a memory region. > > + @param[in] Length The size in bytes of the memory region= . > > + @param[in] Attributes The bit mask of attributes to set for = the > > memory region. > > + @param[out] IsSplitted TRUE means page table splitted. FALSE = means > > page table not splitted. > > + > > + @retval EFI_SUCCESS The attributes were set for the memory= region. > > + @retval EFI_ACCESS_DENIED The attributes for the memory resource > > range specified by > > + BaseAddress and Length cannot be modif= ied. > > + @retval EFI_INVALID_PARAMETER Length is zero. > > + Attributes specified an illegal combin= ation of attributes that > > + cannot be set together. > > + @retval EFI_OUT_OF_RESOURCES There are not enough system > > resources to modify the attributes of > > + the memory resource range. > > + @retval EFI_UNSUPPORTED The processor does not support one or > > more bytes of the memory > > + resource range specified by BaseAddres= s and Length. > > + The bit mask of attributes is not supp= ort for the memory > > resource > > + range specified by BaseAddress and Len= gth. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SmmSetMemoryAttributesEx ( > > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > > + IN UINT64 Length, > > + IN UINT64 Attributes, > > + OUT BOOLEAN *IsSplitted OPTIONAL > > + ) > > +{ > > + EFI_STATUS Status; > > + BOOLEAN IsModified; > > + > > + Status =3D ConvertMemoryPageAttributes (BaseAddress, Length, Attribu= tes, > > TRUE, IsSplitted, &IsModified); > > + if (!EFI_ERROR(Status)) { > > + if (IsModified) { > > + // > > + // Flush TLB as last step > > + // > > + FlushTlbForAll(); > > + } > > + } > > + > > + return Status; > > +} > > + > > +/** > > + This function clears the attributes for the memory region specified = by > > BaseAddress and > > + Length from their current attributes to the attributes specified by > > Attributes. > > + > > + @param[in] BaseAddress The physical address that is the start= address > > of a memory region. > > + @param[in] Length The size in bytes of the memory region= . > > + @param[in] Attributes The bit mask of attributes to clear fo= r the > > memory region. > > + @param[out] IsSplitted TRUE means page table splitted. FALSE = means > > page table not splitted. > > + > > + @retval EFI_SUCCESS The attributes were cleared for the me= mory > > region. > > + @retval EFI_ACCESS_DENIED The attributes for the memory resource > > range specified by > > + BaseAddress and Length cannot be modif= ied. > > + @retval EFI_INVALID_PARAMETER Length is zero. > > + Attributes specified an illegal combin= ation of attributes that > > + cannot be set together. > > + @retval EFI_OUT_OF_RESOURCES There are not enough system > > resources to modify the attributes of > > + the memory resource range. > > + @retval EFI_UNSUPPORTED The processor does not support one or > > more bytes of the memory > > + resource range specified by BaseAddres= s and Length. > > + The bit mask of attributes is not supp= ort for the memory > > resource > > + range specified by BaseAddress and Len= gth. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SmmClearMemoryAttributesEx ( > > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > > + IN UINT64 Length, > > + IN UINT64 Attributes, > > + OUT BOOLEAN *IsSplitted OPTIONAL > > + ) > > +{ > > + EFI_STATUS Status; > > + BOOLEAN IsModified; > > + > > + Status =3D ConvertMemoryPageAttributes (BaseAddress, Length, Attribu= tes, > > FALSE, IsSplitted, &IsModified); > > + if (!EFI_ERROR(Status)) { > > + if (IsModified) { > > + // > > + // Flush TLB as last step > > + // > > + FlushTlbForAll(); > > + } > > + } > > + > > + return Status; > > +} > > + > > +/** > > + This function sets the attributes for the memory region specified by > > BaseAddress and > > + Length from their current attributes to the attributes specified by > > Attributes. > > + > > + @param[in] BaseAddress The physical address that is the start = address > > of a memory region. > > + @param[in] Length The size in bytes of the memory region. > > + @param[in] Attributes The bit mask of attributes to set for t= he memory > > region. > > + > > + @retval EFI_SUCCESS The attributes were set for the memory= region. > > + @retval EFI_ACCESS_DENIED The attributes for the memory resource > > range specified by > > + BaseAddress and Length cannot be modif= ied. > > + @retval EFI_INVALID_PARAMETER Length is zero. > > + Attributes specified an illegal combin= ation of attributes that > > + cannot be set together. > > + @retval EFI_OUT_OF_RESOURCES There are not enough system > > resources to modify the attributes of > > + the memory resource range. > > + @retval EFI_UNSUPPORTED The processor does not support one or > > more bytes of the memory > > + resource range specified by BaseAddres= s and Length. > > + The bit mask of attributes is not supp= ort for the memory > > resource > > + range specified by BaseAddress and Len= gth. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SmmSetMemoryAttributes ( > > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > > + IN UINT64 Length, > > + IN UINT64 Attributes > > + ) > > +{ > > + return SmmSetMemoryAttributesEx (BaseAddress, Length, Attributes, > > NULL); > > +} > > + > > +/** > > + This function clears the attributes for the memory region specified = by > > BaseAddress and > > + Length from their current attributes to the attributes specified by > > Attributes. > > + > > + @param[in] BaseAddress The physical address that is the start = address > > of a memory region. > > + @param[in] Length The size in bytes of the memory region. > > + @param[in] Attributes The bit mask of attributes to clear for= the > > memory region. > > + > > + @retval EFI_SUCCESS The attributes were cleared for the me= mory > > region. > > + @retval EFI_ACCESS_DENIED The attributes for the memory resource > > range specified by > > + BaseAddress and Length cannot be modif= ied. > > + @retval EFI_INVALID_PARAMETER Length is zero. > > + Attributes specified an illegal combin= ation of attributes that > > + cannot be set together. > > + @retval EFI_OUT_OF_RESOURCES There are not enough system > > resources to modify the attributes of > > + the memory resource range. > > + @retval EFI_UNSUPPORTED The processor does not support one or > > more bytes of the memory > > + resource range specified by BaseAddres= s and Length. > > + The bit mask of attributes is not supp= ort for the memory > > resource > > + range specified by BaseAddress and Len= gth. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SmmClearMemoryAttributes ( > > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > > + IN UINT64 Length, > > + IN UINT64 Attributes > > + ) > > +{ > > + return SmmClearMemoryAttributesEx (BaseAddress, Length, Attributes, > > NULL); > > +} > > + > > +/** > > + Initialize the Page Table lib. > > +**/ > > +VOID > > +InitializePageTableLib ( > > + VOID > > + ) > > +{ > > + mAddressEncMask =3D PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) > > & PAGING_1G_ADDRESS_MASK_64; > > + mPhysicalAddressBits =3D CalculateMaximumSupportAddress (); > > + DEBUG ((DEBUG_INFO, "mAddressEncMask =3D 0x%lx\r\n", > > mAddressEncMask)); > > + DEBUG ((DEBUG_INFO, "mPhysicalAddressBits =3D %d\r\n", > > mPhysicalAddressBits)); > > + return ; > > +} > > + > > diff --git a/MdeModulePkg/Core/PiSmmCore/Misc/PageTable.h > > b/MdeModulePkg/Core/PiSmmCore/Misc/PageTable.h > > new file mode 100644 > > index 0000000000..61a64af370 > > --- /dev/null > > +++ b/MdeModulePkg/Core/PiSmmCore/Misc/PageTable.h > > @@ -0,0 +1,174 @@ > > +/** @file > > + Page table management header file. > > + > > + Copyright (c) 2017, Intel Corporation. All rights reserved.
> > + This program and the accompanying materials > > + are licensed and made available under the terms and conditions of th= e BSD > > License > > + which accompanies this distribution. The full text of the license m= ay be > > found at > > + http://opensource.org/licenses/bsd-license.php > > + > > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > > BASIS, > > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > > EXPRESS OR IMPLIED. > > + > > +**/ > > + > > +#ifndef _PAGE_TABLE_LIB_H_ > > +#define _PAGE_TABLE_LIB_H_ > > + > > +/// > > +/// Page Table Entry > > +/// > > +#define IA32_PG_P BIT0 > > +#define IA32_PG_RW BIT1 > > +#define IA32_PG_U BIT2 > > +#define IA32_PG_WT BIT3 > > +#define IA32_PG_CD BIT4 > > +#define IA32_PG_A BIT5 > > +#define IA32_PG_D BIT6 > > +#define IA32_PG_PS BIT7 > > +#define IA32_PG_PAT_2M BIT12 > > +#define IA32_PG_PAT_4K IA32_PG_PS > > +#define IA32_PG_PMNT BIT62 > > +#define IA32_PG_NX BIT63 > > + > > +#define PAGE_ATTRIBUTE_BITS (IA32_PG_D | IA32_PG_A | > > IA32_PG_U | IA32_PG_RW | IA32_PG_P) > > +// > > +// Bits 1, 2, 5, 6 are reserved in the IA32 PAE PDPTE > > +// X64 PAE PDPTE does not have such restriction > > +// > > +#define IA32_PAE_PDPTE_ATTRIBUTE_BITS (IA32_PG_P) > > + > > +#define PAGE_PROGATE_BITS (IA32_PG_NX | PAGE_ATTRIBUTE_BITS) > > + > > +#define PAGING_4K_MASK 0xFFF > > +#define PAGING_2M_MASK 0x1FFFFF > > +#define PAGING_1G_MASK 0x3FFFFFFF > > + > > +#define PAGING_PAE_INDEX_MASK 0x1FF > > + > > +#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull > > +#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull > > +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull > > + > > +#define SMRR_MAX_ADDRESS BASE_4GB > > + > > +typedef enum { > > + PageNone =3D 0, > > + Page4K, > > + Page2M, > > + Page1G, > > +} PAGE_ATTRIBUTE; > > + > > +typedef struct { > > + PAGE_ATTRIBUTE Attribute; > > + UINT64 Length; > > + UINT64 AddressMask; > > +} PAGE_ATTRIBUTE_TABLE; > > + > > +/** > > + Helper function to allocate pages without Guard for internal uses > > + > > + @param[in] Pages Page number > > + > > + @return Address of memory allocated > > +**/ > > +VOID * > > +PageAlloc ( > > + IN UINTN Pages > > + ); > > + > > +/** > > + This function sets the attributes for the memory region specified by > > BaseAddress and > > + Length from their current attributes to the attributes specified by > > Attributes. > > + > > + @param[in] BaseAddress The physical address that is the start= address > > of a memory region. > > + @param[in] Length The size in bytes of the memory region= . > > + @param[in] Attributes The bit mask of attributes to set for = the > > memory region. > > + @param[out] IsSplitted TRUE means page table splitted. FALSE = means > > page table not splitted. > > + > > + @retval EFI_SUCCESS The attributes were set for the memory= region. > > + @retval EFI_ACCESS_DENIED The attributes for the memory resource > > range specified by > > + BaseAddress and Length cannot be modif= ied. > > + @retval EFI_INVALID_PARAMETER Length is zero. > > + Attributes specified an illegal combin= ation of attributes that > > + cannot be set together. > > + @retval EFI_OUT_OF_RESOURCES There are not enough system > > resources to modify the attributes of > > + the memory resource range. > > + @retval EFI_UNSUPPORTED The processor does not support one or > > more bytes of the memory > > + resource range specified by BaseAddres= s and Length. > > + The bit mask of attributes is not supp= ort for the memory > > resource > > + range specified by BaseAddress and Len= gth. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SmmSetMemoryAttributes ( > > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > > + IN UINT64 Length, > > + IN UINT64 Attributes > > + ); > > + > > +/** > > + This function clears the attributes for the memory region specified = by > > BaseAddress and > > + Length from their current attributes to the attributes specified by > > Attributes. > > + > > + @param[in] BaseAddress The physical address that is the start= address > > of a memory region. > > + @param[in] Length The size in bytes of the memory region= . > > + @param[in] Attributes The bit mask of attributes to clear fo= r the > > memory region. > > + @param[out] IsSplitted TRUE means page table splitted. FALSE = means > > page table not splitted. > > + > > + @retval EFI_SUCCESS The attributes were cleared for the me= mory > > region. > > + @retval EFI_ACCESS_DENIED The attributes for the memory resource > > range specified by > > + BaseAddress and Length cannot be modif= ied. > > + @retval EFI_INVALID_PARAMETER Length is zero. > > + Attributes specified an illegal combin= ation of attributes that > > + cannot be set together. > > + @retval EFI_OUT_OF_RESOURCES There are not enough system > > resources to modify the attributes of > > + the memory resource range. > > + @retval EFI_UNSUPPORTED The processor does not support one or > > more bytes of the memory > > + resource range specified by BaseAddres= s and Length. > > + The bit mask of attributes is not supp= ort for the memory > > resource > > + range specified by BaseAddress and Len= gth. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +SmmClearMemoryAttributes ( > > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > > + IN UINT64 Length, > > + IN UINT64 Attributes > > + ); > > + > > +/** > > + Initialize the Page Table lib. > > +**/ > > +VOID > > +InitializePageTableLib ( > > + VOID > > + ); > > + > > +/** > > + Return page table base. > > + > > + @return page table base. > > +**/ > > +UINTN > > +GetPageTableBase ( > > + VOID > > + ); > > + > > +/** > > + Return page table entry to match the address. > > + > > + @param[in] Address The address to be checked. > > + @param[out] PageAttributes The page attribute of the page entry. > > + > > + @return The page entry. > > +**/ > > +VOID * > > +GetPageTableEntry ( > > + IN PHYSICAL_ADDRESS Address, > > + OUT PAGE_ATTRIBUTE *PageAttribute > > + ); > > + > > +#endif > > diff --git a/MdeModulePkg/Core/PiSmmCore/Page.c > > b/MdeModulePkg/Core/PiSmmCore/Page.c > > index 4154c2e6a1..29d1311f5a 100644 > > --- a/MdeModulePkg/Core/PiSmmCore/Page.c > > +++ b/MdeModulePkg/Core/PiSmmCore/Page.c > > @@ -64,6 +64,8 @@ LIST_ENTRY mFreeMemoryMapEntryList =3D > > INITIALIZE_LIST_HEAD_VARIABLE (mFreeMemor > > @param[out] Memory A pointer to receive the base al= located > > memory > > address. > > @param[in] AddRegion If this memory is new added regi= on. > > + @param[in] NeedGuard Flag to indicate Guard page is n= eeded > > + or not > > > > @retval EFI_INVALID_PARAMETER Parameters violate checking rules > > defined in spec. > > @retval EFI_NOT_FOUND Could not allocate pages match the > > requirement. > > @@ -77,7 +79,8 @@ SmmInternalAllocatePagesEx ( > > IN EFI_MEMORY_TYPE MemoryType, > > IN UINTN NumberOfPages, > > OUT EFI_PHYSICAL_ADDRESS *Memory, > > - IN BOOLEAN AddRegion > > + IN BOOLEAN AddRegion, > > + IN BOOLEAN NeedGuard > > ); > > > > /** > > @@ -112,7 +115,8 @@ AllocateMemoryMapEntry ( > > EfiRuntimeServicesData, > > EFI_SIZE_TO_PAGES (RUNTIME_PAGE_ALLOCATION_GRANULARITY)= , > > &Mem, > > - TRUE > > + TRUE, > > + FALSE > > ); > > ASSERT_EFI_ERROR (Status); > > if(!EFI_ERROR (Status)) { > > @@ -688,6 +692,8 @@ InternalAllocAddress ( > > @param[out] Memory A pointer to receive the base al= located > > memory > > address. > > @param[in] AddRegion If this memory is new added regi= on. > > + @param[in] NeedGuard Flag to indicate Guard page is n= eeded > > + or not > > > > @retval EFI_INVALID_PARAMETER Parameters violate checking rules > > defined in spec. > > @retval EFI_NOT_FOUND Could not allocate pages match the > > requirement. > > @@ -701,7 +707,8 @@ SmmInternalAllocatePagesEx ( > > IN EFI_MEMORY_TYPE MemoryType, > > IN UINTN NumberOfPages, > > OUT EFI_PHYSICAL_ADDRESS *Memory, > > - IN BOOLEAN AddRegion > > + IN BOOLEAN AddRegion, > > + IN BOOLEAN NeedGuard > > ) > > { > > UINTN RequestedAddress; > > @@ -723,6 +730,21 @@ SmmInternalAllocatePagesEx ( > > case AllocateAnyPages: > > RequestedAddress =3D (UINTN)(-1); > > case AllocateMaxAddress: > > + if (NeedGuard) { > > + *Memory =3D InternalAllocMaxAddressWithGuard ( > > + &mSmmMemoryMap, > > + NumberOfPages, > > + RequestedAddress, > > + MemoryType > > + ); > > + if (*Memory =3D=3D (UINTN)-1) { > > + return EFI_OUT_OF_RESOURCES; > > + } else { > > + ASSERT (VerifyMemoryGuard(*Memory, NumberOfPages) =3D=3D TRU= E); > > + return EFI_SUCCESS; > > + } > > + } > > + > > *Memory =3D InternalAllocMaxAddress ( > > &mSmmMemoryMap, > > NumberOfPages, > > @@ -766,6 +788,8 @@ SmmInternalAllocatePagesEx ( > > @param[in] NumberOfPages The number of pages to allocate. > > @param[out] Memory A pointer to receive the base al= located > > memory > > address. > > + @param[in] NeedGuard Flag to indicate Guard page is n= eeded > > + or not > > > > @retval EFI_INVALID_PARAMETER Parameters violate checking rules > > defined in spec. > > @retval EFI_NOT_FOUND Could not allocate pages match the > > requirement. > > @@ -779,10 +803,12 @@ SmmInternalAllocatePages ( > > IN EFI_ALLOCATE_TYPE Type, > > IN EFI_MEMORY_TYPE MemoryType, > > IN UINTN NumberOfPages, > > - OUT EFI_PHYSICAL_ADDRESS *Memory > > + OUT EFI_PHYSICAL_ADDRESS *Memory, > > + IN BOOLEAN NeedGuard > > ) > > { > > - return SmmInternalAllocatePagesEx (Type, MemoryType, NumberOfPages, > > Memory, FALSE); > > + return SmmInternalAllocatePagesEx (Type, MemoryType, > > NumberOfPages, Memory, > > + FALSE, NeedGuard); > > } > > > > /** > > @@ -811,8 +837,11 @@ SmmAllocatePages ( > > ) > > { > > EFI_STATUS Status; > > + BOOLEAN NeedGuard; > > > > - Status =3D SmmInternalAllocatePages (Type, MemoryType, NumberOfPages= , > > Memory); > > + NeedGuard =3D IsPageTypeToGuard (MemoryType, Type); > > + Status =3D SmmInternalAllocatePages (Type, MemoryType, NumberOfPages= , > > Memory, > > + NeedGuard); > > if (!EFI_ERROR (Status)) { > > SmmCoreUpdateProfile ( > > (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), > > @@ -941,9 +970,13 @@ EFI_STATUS > > EFIAPI > > SmmInternalFreePages ( > > IN EFI_PHYSICAL_ADDRESS Memory, > > - IN UINTN NumberOfPages > > + IN UINTN NumberOfPages, > > + IN BOOLEAN IsGuarded > > ) > > { > > + if (IsGuarded) { > > + return SmmInternalFreePagesExWithGuard (Memory, NumberOfPages, > > FALSE); > > + } > > return SmmInternalFreePagesEx (Memory, NumberOfPages, FALSE); > > } > > > > @@ -966,8 +999,10 @@ SmmFreePages ( > > ) > > { > > EFI_STATUS Status; > > + BOOLEAN IsGuarded; > > > > - Status =3D SmmInternalFreePages (Memory, NumberOfPages); > > + IsGuarded =3D IsHeapGuardEnabled () && IsMemoryGuarded (Memory); > > + Status =3D SmmInternalFreePages (Memory, NumberOfPages, IsGuarded); > > if (!EFI_ERROR (Status)) { > > SmmCoreUpdateProfile ( > > (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), > > diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c > > b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c > > index 9e4390e15a..b4609c2fed 100644 > > --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c > > +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c > > @@ -451,6 +451,11 @@ SmmEntryPoint ( > > // > > PlatformHookBeforeSmmDispatch (); > > > > + // > > + // Call memory management hook function > > + // > > + SmmEntryPointMemoryManagementHook (); > > + > > // > > // If a legacy boot has occured, then make sure gSmmCorePrivate is n= ot > > accessed > > // > > @@ -644,7 +649,12 @@ SmmMain ( > > // > > gSmmCorePrivate->Smst =3D &gSmmCoreSmst; > > gSmmCorePrivate->SmmEntryPoint =3D SmmEntryPoint; > > - > > + > > + // > > + // Initialize page table operations > > + // > > + InitializePageTableLib(); > > + > > // > > // No need to initialize memory service. > > // It is done in constructor of PiSmmCoreMemoryAllocationLib(), > > diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h > > b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h > > index b6f815c68d..8c61fdcf0c 100644 > > --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h > > +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h > > @@ -59,6 +59,7 @@ > > #include > > > > #include "PiSmmCorePrivateData.h" > > +#include "Misc/HeapGuard.h" > > > > // > > // Used to build a table of SMI Handlers that the SMM Core registers > > @@ -317,6 +318,7 @@ SmmAllocatePages ( > > @param NumberOfPages The number of pages to allocate > > @param Memory A pointer to receive the base allocat= ed memory > > address > > + @param NeedGuard Flag to indicate Guard page is needed= or not > > > > @retval EFI_INVALID_PARAMETER Parameters violate checking rules > > defined in spec. > > @retval EFI_NOT_FOUND Could not allocate pages match the > > requirement. > > @@ -330,7 +332,8 @@ SmmInternalAllocatePages ( > > IN EFI_ALLOCATE_TYPE Type, > > IN EFI_MEMORY_TYPE MemoryType, > > IN UINTN NumberOfPages, > > - OUT EFI_PHYSICAL_ADDRESS *Memory > > + OUT EFI_PHYSICAL_ADDRESS *Memory, > > + IN BOOLEAN NeedGuard > > ); > > > > /** > > @@ -356,6 +359,8 @@ SmmFreePages ( > > > > @param Memory Base address of memory being freed > > @param NumberOfPages The number of pages to free > > + @param IsGuarded Flag to indicate if the memory is gua= rded > > + or not > > > > @retval EFI_NOT_FOUND Could not find the entry that covers = the > > range > > @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero = or > > NumberOfPages is zero. > > @@ -366,7 +371,8 @@ EFI_STATUS > > EFIAPI > > SmmInternalFreePages ( > > IN EFI_PHYSICAL_ADDRESS Memory, > > - IN UINTN NumberOfPages > > + IN UINTN NumberOfPages, > > + IN BOOLEAN IsGuarded > > ); > > > > /** > > @@ -1231,4 +1237,74 @@ typedef enum { > > > > extern LIST_ENTRY > > mSmmPoolLists[SmmPoolTypeMax][MAX_POOL_INDEX]; > > > > +/** > > + Internal Function. Allocate n pages from given free page node. > > + > > + @param Pages The free page node. > > + @param NumberOfPages Number of pages to be allocated. > > + @param MaxAddress Request to allocate memory below this > > address. > > + > > + @return Memory address of allocated pages. > > + > > +**/ > > +UINTN > > +InternalAllocPagesOnOneNode ( > > + IN OUT FREE_PAGE_LIST *Pages, > > + IN UINTN NumberOfPages, > > + IN UINTN MaxAddress > > + ); > > + > > +/** > > + Update SMM memory map entry. > > + > > + @param[in] Type The type of allocation to perform= . > > + @param[in] Memory The base of memory address. > > + @param[in] NumberOfPages The number of pages to allocate. > > + @param[in] AddRegion If this memory is new added regio= n. > > +**/ > > +VOID > > +ConvertSmmMemoryMapEntry ( > > + IN EFI_MEMORY_TYPE Type, > > + IN EFI_PHYSICAL_ADDRESS Memory, > > + IN UINTN NumberOfPages, > > + IN BOOLEAN AddRegion > > + ); > > + > > +/** > > + Internal function. Moves any memory descriptors that are on the > > + temporary descriptor stack to heap. > > + > > +**/ > > +VOID > > +CoreFreeMemoryMapStack ( > > + VOID > > + ); > > + > > +/** > > + Frees previous allocated pages. > > + > > + @param[in] Memory Base address of memory being free= d. > > + @param[in] NumberOfPages The number of pages to free. > > + @param[in] AddRegion If this memory is new added regio= n. > > + > > + @retval EFI_NOT_FOUND Could not find the entry that covers = the > > range. > > + @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero = or > > NumberOfPages is zero. > > + @return EFI_SUCCESS Pages successfully freed. > > + > > +**/ > > +EFI_STATUS > > +SmmInternalFreePagesEx ( > > + IN EFI_PHYSICAL_ADDRESS Memory, > > + IN UINTN NumberOfPages, > > + IN BOOLEAN AddRegion > > + ); > > + > > +/** > > + Hook function used to set all Guard pages after entering SMM mode > > +**/ > > +VOID > > +SmmEntryPointMemoryManagementHook ( > > + VOID > > + ); > > + > > #endif > > diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf > > b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf > > index 49ae6fbb57..e505b165bc 100644 > > --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf > > +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf > > @@ -40,6 +40,8 @@ > > SmramProfileRecord.c > > MemoryAttributesTable.c > > SmiHandlerProfile.c > > + Misc/HeapGuard.c > > + Misc/PageTable.c > > > > [Packages] > > MdePkg/MdePkg.dec > > @@ -65,6 +67,7 @@ > > HobLib > > SmmMemLib > > DxeServicesLib > > + CpuLib > > > > [Protocols] > > gEfiDxeSmmReadyToLockProtocolGuid ## UNDEFINED # > > SmiHandlerRegister > > @@ -88,6 +91,7 @@ > > gEfiSmmGpiDispatch2ProtocolGuid ## SOMETIMES_CONSUMES > > gEfiSmmIoTrapDispatch2ProtocolGuid ## SOMETIMES_CONSUMES > > gEfiSmmUsbDispatch2ProtocolGuid ## SOMETIMES_CONSUMES > > + gEfiSmmCpuProtocolGuid ## SOMETIMES_CONSUMES > > > > [Pcd] > > > > gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNum > > ber ## SOMETIMES_CONSUMES > > @@ -96,6 +100,10 @@ > > gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask > > ## CONSUMES > > gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileDriverPath > > ## CONSUMES > > gEfiMdeModulePkgTokenSpaceGuid.PcdSmiHandlerProfilePropertyMask > > ## CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPageType = ## > > CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType = ## > > CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask > > ## CONSUMES > > + > > gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrM > > ask ## CONSUMES > > > > [Guids] > > gAprioriGuid ## SOMETIMES_CONSUMES = ## File > > diff --git a/MdeModulePkg/Core/PiSmmCore/Pool.c > > b/MdeModulePkg/Core/PiSmmCore/Pool.c > > index 36317563c4..1f9213ea6e 100644 > > --- a/MdeModulePkg/Core/PiSmmCore/Pool.c > > +++ b/MdeModulePkg/Core/PiSmmCore/Pool.c > > @@ -144,7 +144,9 @@ InternalAllocPoolByIndex ( > > Status =3D EFI_SUCCESS; > > Hdr =3D NULL; > > if (PoolIndex =3D=3D MAX_POOL_INDEX) { > > - Status =3D SmmInternalAllocatePages (AllocateAnyPages, PoolType, > > EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1), &Address); > > + Status =3D SmmInternalAllocatePages (AllocateAnyPages, PoolType, > > + EFI_SIZE_TO_PAGES (MAX_POOL_SIZ= E << 1), > > + &Address, FALSE); > > if (EFI_ERROR (Status)) { > > return EFI_OUT_OF_RESOURCES; > > } > > @@ -243,6 +245,9 @@ SmmInternalAllocatePool ( > > EFI_STATUS Status; > > EFI_PHYSICAL_ADDRESS Address; > > UINTN PoolIndex; > > + BOOLEAN HasPoolTail; > > + BOOLEAN NeedGuard; > > + UINTN NoPages; > > > > Address =3D 0; > > > > @@ -251,25 +256,45 @@ SmmInternalAllocatePool ( > > return EFI_INVALID_PARAMETER; > > } > > > > + NeedGuard =3D IsPoolTypeToGuard (PoolType); > > + HasPoolTail =3D !(NeedGuard && > > + ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) =3D=3D = 0)); > > + > > // > > // Adjust the size by the pool header & tail overhead > > // > > Size +=3D POOL_OVERHEAD; > > - if (Size > MAX_POOL_SIZE) { > > - Size =3D EFI_SIZE_TO_PAGES (Size); > > - Status =3D SmmInternalAllocatePages (AllocateAnyPages, PoolType, S= ize, > > &Address); > > + if (Size > MAX_POOL_SIZE || NeedGuard) { > > + if (!HasPoolTail) { > > + Size -=3D sizeof (POOL_TAIL); > > + } > > + > > + NoPages =3D EFI_SIZE_TO_PAGES (Size); > > + Status =3D SmmInternalAllocatePages (AllocateAnyPages, PoolType, > > NoPages, > > + &Address, NeedGuard); > > if (EFI_ERROR (Status)) { > > return Status; > > } > > > > + if (NeedGuard) { > > + ASSERT (VerifyMemoryGuard(Address, NoPages) =3D=3D TRUE); > > + DEBUG ((DEBUG_INFO, "SmmInternalAllocatePool: %lx ->", Address))= ; > > + Address =3D (EFI_PHYSICAL_ADDRESS)AdjustPoolHeadA (Address, > > NoPages, Size); > > + DEBUG ((DEBUG_INFO, " %lx %d %x\r\n", Address, NoPages, Size)); > > + } > > + > > PoolHdr =3D (POOL_HEADER*)(UINTN)Address; > > PoolHdr->Signature =3D POOL_HEAD_SIGNATURE; > > - PoolHdr->Size =3D EFI_PAGES_TO_SIZE (Size); > > + PoolHdr->Size =3D Size; //EFI_PAGES_TO_SIZE (NoPages) > > PoolHdr->Available =3D FALSE; > > PoolHdr->Type =3D PoolType; > > - PoolTail =3D HEAD_TO_TAIL(PoolHdr); > > - PoolTail->Signature =3D POOL_TAIL_SIGNATURE; > > - PoolTail->Size =3D PoolHdr->Size; > > + > > + if (HasPoolTail) { > > + PoolTail =3D HEAD_TO_TAIL (PoolHdr); > > + PoolTail->Signature =3D POOL_TAIL_SIGNATURE; > > + PoolTail->Size =3D PoolHdr->Size; > > + } > > + > > *Buffer =3D PoolHdr + 1; > > return Status; > > } > > @@ -341,28 +366,45 @@ SmmInternalFreePool ( > > { > > FREE_POOL_HEADER *FreePoolHdr; > > POOL_TAIL *PoolTail; > > + BOOLEAN HasPoolTail; > > + BOOLEAN MemoryGuarded; > > > > if (Buffer =3D=3D NULL) { > > return EFI_INVALID_PARAMETER; > > } > > > > + MemoryGuarded =3D IsHeapGuardEnabled () && > > + IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer= ); > > + HasPoolTail =3D !(MemoryGuarded && > > + ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) =3D= =3D 0)); > > + > > FreePoolHdr =3D (FREE_POOL_HEADER*)((POOL_HEADER*)Buffer - 1); > > ASSERT (FreePoolHdr->Header.Signature =3D=3D POOL_HEAD_SIGNATURE); > > ASSERT (!FreePoolHdr->Header.Available); > > - PoolTail =3D HEAD_TO_TAIL(&FreePoolHdr->Header); > > - ASSERT (PoolTail->Signature =3D=3D POOL_TAIL_SIGNATURE); > > - ASSERT (FreePoolHdr->Header.Size =3D=3D PoolTail->Size); > > - > > if (FreePoolHdr->Header.Signature !=3D POOL_HEAD_SIGNATURE) { > > return EFI_INVALID_PARAMETER; > > } > > > > - if (PoolTail->Signature !=3D POOL_TAIL_SIGNATURE) { > > - return EFI_INVALID_PARAMETER; > > + if (HasPoolTail) { > > + PoolTail =3D HEAD_TO_TAIL (&FreePoolHdr->Header); > > + ASSERT (PoolTail->Signature =3D=3D POOL_TAIL_SIGNATURE); > > + ASSERT (FreePoolHdr->Header.Size =3D=3D PoolTail->Size); > > + if (PoolTail->Signature !=3D POOL_TAIL_SIGNATURE) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (FreePoolHdr->Header.Size !=3D PoolTail->Size) { > > + return EFI_INVALID_PARAMETER; > > + } > > } > > > > - if (FreePoolHdr->Header.Size !=3D PoolTail->Size) { > > - return EFI_INVALID_PARAMETER; > > + if (MemoryGuarded) { > > + Buffer =3D AdjustPoolHeadF > > ((EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr); > > + return SmmInternalFreePages ( > > + (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, > > + EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size), > > + TRUE > > + ); > > } > > > > if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) { > > @@ -370,7 +412,8 @@ SmmInternalFreePool ( > > ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) =3D=3D 0); > > return SmmInternalFreePages ( > > (EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr, > > - EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size) > > + EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size), > > + FALSE > > ); > > } > > return InternalFreePoolByIndex (FreePoolHdr, PoolTail); > > -- > > 2.14.1.windows.1