From nobody Sat Apr 27 08:23:48 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1511161468059747.5096666222155; Sun, 19 Nov 2017 23:04:28 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 78BA22034711A; Sun, 19 Nov 2017 23:00:12 -0800 (PST) Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) (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 4610820347116 for ; Sun, 19 Nov 2017 23:00:10 -0800 (PST) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 19 Nov 2017 23:04:22 -0800 Received: from jwang36-mobl2.ccr.corp.intel.com ([10.239.192.35]) by fmsmga002.fm.intel.com with ESMTP; 19 Nov 2017 23:04:18 -0800 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.100; helo=mga07.intel.com; envelope-from=jian.j.wang@intel.com; receiver=edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,425,1505804400"; d="scan'208";a="1246273417" From: Jian J Wang To: edk2-devel@lists.01.org Date: Mon, 20 Nov 2017 15:04:15 +0800 Message-Id: <20171120070415.7376-1-jian.j.wang@intel.com> X-Mailer: git-send-email 2.14.1.windows.1 Subject: [edk2] [PATCH] MdeModulePkg/UefiCpuPkg: Fix unix style of EOL 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: , Cc: Wu Hao , Eric Dong , Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Cc: Wu Hao Cc: Star Zeng Cc: Eric Dong Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jian J Wang --- MdeModulePkg/Core/Dxe/DxeMain.inf | 8 +- MdeModulePkg/Core/Dxe/Mem/HeapGuard.c | 2384 ++++++++-------- MdeModulePkg/Core/Dxe/Mem/HeapGuard.h | 788 +++--- MdeModulePkg/Core/Dxe/Mem/Imem.h | 70 +- MdeModulePkg/Core/Dxe/Mem/Page.c | 210 +- MdeModulePkg/Core/Dxe/Mem/Pool.c | 242 +- MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c | 6 +- MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 2 +- MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c | 64 +- MdeModulePkg/Core/PiSmmCore/HeapGuard.c | 2934 ++++++++++------= ---- MdeModulePkg/Core/PiSmmCore/HeapGuard.h | 796 +++--- MdeModulePkg/Core/PiSmmCore/Page.c | 88 +- MdeModulePkg/Core/PiSmmCore/PiSmmCore.c | 12 +- MdeModulePkg/Core/PiSmmCore/PiSmmCore.h | 158 +- MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf | 12 +- MdeModulePkg/Core/PiSmmCore/Pool.c | 128 +- MdeModulePkg/Include/Protocol/SmmMemoryAttribute.h | 272 +- MdeModulePkg/MdeModulePkg.dec | 120 +- MdeModulePkg/MdeModulePkg.uni | 116 +- UefiCpuPkg/CpuDxe/CpuPageTable.c | 4 +- UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c | 20 +- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c | 40 +- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h | 196 +- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf | 4 +- UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 326 +-- UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c | 28 +- 26 files changed, 4514 insertions(+), 4514 deletions(-) diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeM= ain.inf index 9793333a44..f2155fcab1 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -56,7 +56,7 @@ Mem/MemData.c Mem/Imem.h Mem/MemoryProfileRecord.c - Mem/HeapGuard.c + Mem/HeapGuard.c FwVolBlock/FwVolBlock.c FwVolBlock/FwVolBlock.h FwVol/FwVolWrite.c @@ -194,9 +194,9 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy = ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy = ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask = ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPageType = ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType = ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask = ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPageType = ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType = ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask = ## CONSUMES =20 # [Hob] # RESOURCE_DESCRIPTOR ## CONSUMES diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c b/MdeModulePkg/Core/Dxe/= Mem/HeapGuard.c index 98d597b180..fac5e38df4 100644 --- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c +++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c @@ -1,1192 +1,1192 @@ -/** @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 IMPLI= ED. - -**/ - -#include "DxeMain.h" -#include "Imem.h" -#include "HeapGuard.h" - -// -// Global to avoid infinite reentrance of memory allocation when updating -// page table attributes, which may need allocate pages for new PDE/PTE. -// -GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mOnGuarding =3D FALSE; - -// -// Pointer to table tracking the Guarded memory with bitmap, in which '1' -// is used to indicate memory guarded. '0' might be free memory or Guard -// page itself, depending on status of memory adjacent to it. -// -GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mGuardedMemoryMap =3D 0; - -// -// Current depth level of map table pointed by mGuardedMemoryMap. -// mMapLevel must be initialized at least by 1. It will be automatically -// updated according to the address of memory just tracked. -// -GLOBAL_REMOVE_IF_UNREFERENCED UINTN mMapLevel =3D 1; - -// -// Shift and mask for each level of map table -// -GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLevelShift[GUARDED_HEAP_MAP_TABLE_DEP= TH] - =3D GUARDED_HEAP_MAP_TABLE_DEPTH_SHIFT= S; -GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLevelMask[GUARDED_HEAP_MAP_TABLE_DEPT= H] - =3D GUARDED_HEAP_MAP_TABLE_DEPTH_MASKS; - -/** - 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_BITS; - - 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_BITS; - - 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 Address. - 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_BITS; - - 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), Msbs); - } - - return Result; -} - -/** - 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 tab= le. - @param[out] BitMap Pointer to bitmap which covers the Address. - - @return The bit number from given Address to the end of current map tabl= e. -**/ -UINTN -FindGuardedMemoryMap ( - IN EFI_PHYSICAL_ADDRESS Address, - IN BOOLEAN AllocMapUnit, - OUT UINT64 **BitMap - ) -{ - UINTN Level; - UINT64 *GuardMap; - UINT64 MapMemory; - UINTN Index; - UINTN Size; - UINTN BitsToUnitEnd; - EFI_STATUS Status; - - // - // Adjust current map table depth according to the address to access - // - while (mMapLevel < GUARDED_HEAP_MAP_TABLE_DEPTH - && - RShiftU64 ( - Address, - mLevelShift[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1] - ) !=3D 0) { - - if (mGuardedMemoryMap !=3D 0) { - Size =3D (mLevelMask[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1] += 1) - * GUARDED_HEAP_MAP_ENTRY_BYTES; - Status =3D CoreInternalAllocatePages ( - AllocateAnyPages, - EfiBootServicesData, - EFI_SIZE_TO_PAGES (Size), - &MapMemory, - FALSE - ); - ASSERT_EFI_ERROR (Status); - ASSERT (MapMemory !=3D 0); - - SetMem ((VOID *)(UINTN)MapMemory, Size, 0); - - *(UINT64 *)(UINTN)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 0) { - if (!AllocMapUnit) { - GuardMap =3D NULL; - break; - } - - Size =3D (mLevelMask[Level] + 1) * GUARDED_HEAP_MAP_ENTRY_BYTES; - Status =3D CoreInternalAllocatePages ( - AllocateAnyPages, - EfiBootServicesData, - EFI_SIZE_TO_PAGES (Size), - &MapMemory, - FALSE - ); - ASSERT_EFI_ERROR (Status); - ASSERT (MapMemory !=3D 0); - - SetMem ((VOID *)(UINTN)MapMemory, Size, 0); - *GuardMap =3D MapMemory; - } - - Index =3D (UINTN)RShiftU64 (Address, mLevelShift[Level]); - Index &=3D mLevelMask[Level]; - GuardMap =3D (UINT64 *)(UINTN)((*GuardMap) + Index * sizeof (UINT64)); - - } - - BitsToUnitEnd =3D GUARDED_HEAP_MAP_BITS - GUARDED_HEAP_MAP_BIT_INDEX (Ad= dress); - *BitMap =3D GuardMap; - - return BitsToUnitEnd; -} - -/** - Set corresponding bits in bitmap table to 1 according to given memory ra= nge. - - @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 range. - - @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 memory ra= nge. - - @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; - UINT64 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 or no= t. - - @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 or no= t. - - @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 0b01); -} - -/** - 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] BaseAddress Page address to Guard at - - @return VOID -**/ -VOID -EFIAPI -SetGuardPage ( - IN EFI_PHYSICAL_ADDRESS BaseAddress - ) -{ - // - // Set flag to make sure allocating memory without GUARD for page table - // operation; otherwise infinite loops could be caused. - // - mOnGuarding =3D TRUE; - // - // Note: This might overwrite other attributes needed by other features, - // such as memory protection (NX). Please make sure they are not enabled - // at the same time. - // - gCpu->SetMemoryAttributes (gCpu, BaseAddress, EFI_PAGE_SIZE, EFI_MEMORY_= RP); - mOnGuarding =3D FALSE; -} - -/** - 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] BaseAddress Page address to Guard at. - - @return VOID. -**/ -VOID -EFIAPI -UnsetGuardPage ( - IN EFI_PHYSICAL_ADDRESS BaseAddress - ) -{ - // - // Set flag to make sure allocating memory without GUARD for page table - // operation; otherwise infinite loops could be caused. - // - mOnGuarding =3D TRUE; - // - // Note: This might overwrite other attributes needed by other features, - // such as memory protection (NX). Please make sure they are not enabled - // at the same time. - // - gCpu->SetMemoryAttributes (gCpu, BaseAddress, EFI_PAGE_SIZE, 0); - mOnGuarding =3D FALSE; -} - -/** - 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 allocatio= n. - - - @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; - BOOLEAN InSmm; - - if (gCpu =3D=3D NULL || AllocateType =3D=3D AllocateAddress) { - return FALSE; - } - - InSmm =3D FALSE; - if (gSmmBase2 !=3D NULL) { - gSmmBase2->InSmm (gSmmBase2, &InSmm); - } - - if (InSmm) { - return FALSE; - } - - if ((PcdGet8 (PcdHeapGuardPropertyMask) & PageOrPool) =3D=3D 0) { - return FALSE; - } - - if (PageOrPool =3D=3D GUARD_HEAP_TYPE_POOL) { - ConfigBit =3D PcdGet64 (PcdHeapGuardPoolType); - } else if (PageOrPool =3D=3D GUARD_HEAP_TYPE_PAGE) { - ConfigBit =3D PcdGet64 (PcdHeapGuardPageType); - } else { - ConfigBit =3D (UINT64)-1; - } - - if ((UINT32)MemoryType >=3D MEMORY_TYPE_OS_RESERVED_MIN) { - TestBit =3D BIT63; - } else if ((UINT32) MemoryType >=3D MEMORY_TYPE_OEM_RESERVED_MIN) { - TestBit =3D BIT62; - } else if (MemoryType < EfiMaxMemoryType) { - 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 not. - - @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 not. - - @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_PA= GE); -} - -/** - 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 for. - @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 block, - // 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 any. - // - 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 block, - // free it; otherwise, keep it. - // - UnsetGuardPage (GuardPage); - } - } else if (IsMemoryGuarded (GuardPage)) { - // - // Pages after memory to free are still in Guard. It's a partial free - // 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 Guar= d. - - This function will check if there're existing Guard pages of adjacent - 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 Gua= rd. -**/ -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 share. - return 0; - } - } - - // OK, we have enough pages for memory and its Guards. Return the End of= the - // free space. - return Target + SizeRequested - 1; -} - -/** - Adjust the start address and number of pages to free according to Guard. - - The purpose of this function is to keep the shared Guard page with adjac= ent - memory block if it's still in guard, or free it if no more sharing. Anot= her - 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 || *NumberOfPages = =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 block, - // 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 any. - // - 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 block, - // 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 free - // 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 Guar= d. - - @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 safe to - // adjust the start address and/or number of pages here, to make sure th= at - // 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 adjavent 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); -} - -/** - Allocate or free guarded memory. - - @param[in] Start Start address of memory to allocate or free. - @param[in] NumberOfPages Memory size in pages. - @param[in] NewType Memory type to convert to. - - @return VOID. -**/ -EFI_STATUS -CoreConvertPagesWithGuard ( - IN UINT64 Start, - IN UINTN NumberOfPages, - IN EFI_MEMORY_TYPE NewType - ) -{ - if (NewType =3D=3D EfiConventionalMemory) { - AdjustMemoryF (&Start, &NumberOfPages); - } else { - AdjustMemoryA (&Start, &NumberOfPages); - } - - return CoreConvertPages(Start, NumberOfPages, NewType); -} - -/** - Helper function to convert a UINT64 value in binary to a string. - - @param[in] Value Value of a UINT64 integer. - @param[out] BinString String buffer to contain the conversion result. - - @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. -**/ -VOID -EFIAPI -DumpGuardedMemoryBitmap ( - VOID - ) -{ - UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINT64 TableEntry; - UINT64 Address; - INTN Level; - UINTN RepeatZero; - CHAR8 String[GUARDED_HEAP_MAP_ENTRY_BITS + 1]; - CHAR8 *Ruler1; - CHAR8 *Ruler2; - - if (mGuardedMemoryMap =3D=3D 0) { - return; - } - - Ruler1 =3D " 3 2 1 = 0"; - Ruler2 =3D "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA987654= 3210"; - - DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "=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 ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler1)); - DEBUG ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler2)); - - CopyMem (Entries, mLevelMask, sizeof (Entries)); - CopyMem (Shifts, mLevelShift, sizeof (Shifts)); - - SetMem (Indices, sizeof(Indices), 0); - SetMem (Tables, sizeof(Tables), 0); - SetMem (Addresses, sizeof(Addresses), 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 (( - HEAP_GUARD_DEBUG_LEVEL, - "=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 ((UINT64 *)(UINTN)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 ((HEAP_GUARD_DEBUG_LEVEL, "%016lx: %a\r\n", Address, Str= ing)); - } else if (RepeatZero =3D=3D 1) { - DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "... : ...\r\n")); - } - RepeatZero +=3D 1; - } - - } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) { - - Level +=3D 1; - Tables[Level] =3D TableEntry; - Addresses[Level] =3D Address; - Indices[Level] =3D 0; - RepeatZero =3D 0; - - continue; - - } else { - - RepeatZero =3D 0; - Uint64ToBinString(TableEntry, String); - DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "%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[Level]= ); - - } -} - +/** @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 IMPLI= ED. + +**/ + +#include "DxeMain.h" +#include "Imem.h" +#include "HeapGuard.h" + +// +// Global to avoid infinite reentrance of memory allocation when updating +// page table attributes, which may need allocate pages for new PDE/PTE. +// +GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mOnGuarding =3D FALSE; + +// +// Pointer to table tracking the Guarded memory with bitmap, in which '1' +// is used to indicate memory guarded. '0' might be free memory or Guard +// page itself, depending on status of memory adjacent to it. +// +GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mGuardedMemoryMap =3D 0; + +// +// Current depth level of map table pointed by mGuardedMemoryMap. +// mMapLevel must be initialized at least by 1. It will be automatically +// updated according to the address of memory just tracked. +// +GLOBAL_REMOVE_IF_UNREFERENCED UINTN mMapLevel =3D 1; + +// +// Shift and mask for each level of map table +// +GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLevelShift[GUARDED_HEAP_MAP_TABLE_DEP= TH] + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_SHIFT= S; +GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLevelMask[GUARDED_HEAP_MAP_TABLE_DEPT= H] + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_MASKS; + +/** + 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_BITS; + + 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_BITS; + + 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 Address. + 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_BITS; + + 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), Msbs); + } + + return Result; +} + +/** + 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 tab= le. + @param[out] BitMap Pointer to bitmap which covers the Address. + + @return The bit number from given Address to the end of current map tabl= e. +**/ +UINTN +FindGuardedMemoryMap ( + IN EFI_PHYSICAL_ADDRESS Address, + IN BOOLEAN AllocMapUnit, + OUT UINT64 **BitMap + ) +{ + UINTN Level; + UINT64 *GuardMap; + UINT64 MapMemory; + UINTN Index; + UINTN Size; + UINTN BitsToUnitEnd; + EFI_STATUS Status; + + // + // Adjust current map table depth according to the address to access + // + while (mMapLevel < GUARDED_HEAP_MAP_TABLE_DEPTH + && + RShiftU64 ( + Address, + mLevelShift[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1] + ) !=3D 0) { + + if (mGuardedMemoryMap !=3D 0) { + Size =3D (mLevelMask[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1] += 1) + * GUARDED_HEAP_MAP_ENTRY_BYTES; + Status =3D CoreInternalAllocatePages ( + AllocateAnyPages, + EfiBootServicesData, + EFI_SIZE_TO_PAGES (Size), + &MapMemory, + FALSE + ); + ASSERT_EFI_ERROR (Status); + ASSERT (MapMemory !=3D 0); + + SetMem ((VOID *)(UINTN)MapMemory, Size, 0); + + *(UINT64 *)(UINTN)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 0) { + if (!AllocMapUnit) { + GuardMap =3D NULL; + break; + } + + Size =3D (mLevelMask[Level] + 1) * GUARDED_HEAP_MAP_ENTRY_BYTES; + Status =3D CoreInternalAllocatePages ( + AllocateAnyPages, + EfiBootServicesData, + EFI_SIZE_TO_PAGES (Size), + &MapMemory, + FALSE + ); + ASSERT_EFI_ERROR (Status); + ASSERT (MapMemory !=3D 0); + + SetMem ((VOID *)(UINTN)MapMemory, Size, 0); + *GuardMap =3D MapMemory; + } + + Index =3D (UINTN)RShiftU64 (Address, mLevelShift[Level]); + Index &=3D mLevelMask[Level]; + GuardMap =3D (UINT64 *)(UINTN)((*GuardMap) + Index * sizeof (UINT64)); + + } + + BitsToUnitEnd =3D GUARDED_HEAP_MAP_BITS - GUARDED_HEAP_MAP_BIT_INDEX (Ad= dress); + *BitMap =3D GuardMap; + + return BitsToUnitEnd; +} + +/** + Set corresponding bits in bitmap table to 1 according to given memory ra= nge. + + @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 range. + + @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 memory ra= nge. + + @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; + UINT64 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 or no= t. + + @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 or no= t. + + @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 0b01); +} + +/** + 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] BaseAddress Page address to Guard at + + @return VOID +**/ +VOID +EFIAPI +SetGuardPage ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +{ + // + // Set flag to make sure allocating memory without GUARD for page table + // operation; otherwise infinite loops could be caused. + // + mOnGuarding =3D TRUE; + // + // Note: This might overwrite other attributes needed by other features, + // such as memory protection (NX). Please make sure they are not enabled + // at the same time. + // + gCpu->SetMemoryAttributes (gCpu, BaseAddress, EFI_PAGE_SIZE, EFI_MEMORY_= RP); + mOnGuarding =3D FALSE; +} + +/** + 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] BaseAddress Page address to Guard at. + + @return VOID. +**/ +VOID +EFIAPI +UnsetGuardPage ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +{ + // + // Set flag to make sure allocating memory without GUARD for page table + // operation; otherwise infinite loops could be caused. + // + mOnGuarding =3D TRUE; + // + // Note: This might overwrite other attributes needed by other features, + // such as memory protection (NX). Please make sure they are not enabled + // at the same time. + // + gCpu->SetMemoryAttributes (gCpu, BaseAddress, EFI_PAGE_SIZE, 0); + mOnGuarding =3D FALSE; +} + +/** + 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 allocatio= n. + + + @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; + BOOLEAN InSmm; + + if (gCpu =3D=3D NULL || AllocateType =3D=3D AllocateAddress) { + return FALSE; + } + + InSmm =3D FALSE; + if (gSmmBase2 !=3D NULL) { + gSmmBase2->InSmm (gSmmBase2, &InSmm); + } + + if (InSmm) { + return FALSE; + } + + if ((PcdGet8 (PcdHeapGuardPropertyMask) & PageOrPool) =3D=3D 0) { + return FALSE; + } + + if (PageOrPool =3D=3D GUARD_HEAP_TYPE_POOL) { + ConfigBit =3D PcdGet64 (PcdHeapGuardPoolType); + } else if (PageOrPool =3D=3D GUARD_HEAP_TYPE_PAGE) { + ConfigBit =3D PcdGet64 (PcdHeapGuardPageType); + } else { + ConfigBit =3D (UINT64)-1; + } + + if ((UINT32)MemoryType >=3D MEMORY_TYPE_OS_RESERVED_MIN) { + TestBit =3D BIT63; + } else if ((UINT32) MemoryType >=3D MEMORY_TYPE_OEM_RESERVED_MIN) { + TestBit =3D BIT62; + } else if (MemoryType < EfiMaxMemoryType) { + 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 not. + + @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 not. + + @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_PA= GE); +} + +/** + 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 for. + @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 block, + // 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 any. + // + 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 block, + // free it; otherwise, keep it. + // + UnsetGuardPage (GuardPage); + } + } else if (IsMemoryGuarded (GuardPage)) { + // + // Pages after memory to free are still in Guard. It's a partial free + // 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 Guar= d. + + This function will check if there're existing Guard pages of adjacent + 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 Gua= rd. +**/ +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 share. + return 0; + } + } + + // OK, we have enough pages for memory and its Guards. Return the End of= the + // free space. + return Target + SizeRequested - 1; +} + +/** + Adjust the start address and number of pages to free according to Guard. + + The purpose of this function is to keep the shared Guard page with adjac= ent + memory block if it's still in guard, or free it if no more sharing. Anot= her + 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 || *NumberOfPages = =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 block, + // 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 any. + // + 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 block, + // 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 free + // 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 Guar= d. + + @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 safe to + // adjust the start address and/or number of pages here, to make sure th= at + // 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 adjavent 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); +} + +/** + Allocate or free guarded memory. + + @param[in] Start Start address of memory to allocate or free. + @param[in] NumberOfPages Memory size in pages. + @param[in] NewType Memory type to convert to. + + @return VOID. +**/ +EFI_STATUS +CoreConvertPagesWithGuard ( + IN UINT64 Start, + IN UINTN NumberOfPages, + IN EFI_MEMORY_TYPE NewType + ) +{ + if (NewType =3D=3D EfiConventionalMemory) { + AdjustMemoryF (&Start, &NumberOfPages); + } else { + AdjustMemoryA (&Start, &NumberOfPages); + } + + return CoreConvertPages(Start, NumberOfPages, NewType); +} + +/** + Helper function to convert a UINT64 value in binary to a string. + + @param[in] Value Value of a UINT64 integer. + @param[out] BinString String buffer to contain the conversion result. + + @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. +**/ +VOID +EFIAPI +DumpGuardedMemoryBitmap ( + VOID + ) +{ + UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 TableEntry; + UINT64 Address; + INTN Level; + UINTN RepeatZero; + CHAR8 String[GUARDED_HEAP_MAP_ENTRY_BITS + 1]; + CHAR8 *Ruler1; + CHAR8 *Ruler2; + + if (mGuardedMemoryMap =3D=3D 0) { + return; + } + + Ruler1 =3D " 3 2 1 = 0"; + Ruler2 =3D "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA987654= 3210"; + + DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "=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 ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler1)); + DEBUG ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler2)); + + CopyMem (Entries, mLevelMask, sizeof (Entries)); + CopyMem (Shifts, mLevelShift, sizeof (Shifts)); + + SetMem (Indices, sizeof(Indices), 0); + SetMem (Tables, sizeof(Tables), 0); + SetMem (Addresses, sizeof(Addresses), 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 (( + HEAP_GUARD_DEBUG_LEVEL, + "=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 ((UINT64 *)(UINTN)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 ((HEAP_GUARD_DEBUG_LEVEL, "%016lx: %a\r\n", Address, Str= ing)); + } else if (RepeatZero =3D=3D 1) { + DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "... : ...\r\n")); + } + RepeatZero +=3D 1; + } + + } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) { + + Level +=3D 1; + Tables[Level] =3D TableEntry; + Addresses[Level] =3D Address; + Indices[Level] =3D 0; + RepeatZero =3D 0; + + continue; + + } else { + + RepeatZero =3D 0; + Uint64ToBinString(TableEntry, String); + DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "%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[Level]= ); + + } +} + diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h b/MdeModulePkg/Core/Dxe/= Mem/HeapGuard.h index 71757a83b1..bd7abd7c53 100644 --- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h +++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h @@ -1,394 +1,394 @@ -/** @file - Data type, macros and function prototypes of heap guard feature. - -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 IMPLI= ED. - -**/ - -#ifndef _HEAPGUARD_H_ -#define _HEAPGUARD_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, the -// 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-bit -// system, like below. -// -// 512 * 512 * 512 * 512 * 1K * 64b * 4K -// 111111111 111111111 111111111 111111111 1111111111 111111 1111111111= 11 -// 63 54 45 36 27 17 11 = 0 -// 9b 9b 9b 9b 10b 6b 12b -// L0 -> L1 -> L2 -> L3 -> L4 -> bits -> page -// 1FF 1FF 1FF 1FF 3FF 3F FFF -// -// L4 table has 1K * sizeof(UINT64) =3D 8K (2-page), which can track 256MB -// memory. Each table of L0-L3 will be allocated when its memory address -// range is to be tracked. Only 1-page will be allocated each time. This -// can save memories used to establish this map table. -// -// For a normal configuration of system with 4G memory, two levels of tabl= es -// can track the whole memory, because two levels (L3+L4) of map tables ha= ve -// already coverred 37-bit of memory address. And for a normal UEFI BIOS, -// 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 spans 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_BYTE= S) - -// 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 travers= ing -// {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 BIT0 -#define GUARD_HEAP_TYPE_PAGE BIT1 - -// -// Debug message level -// -#define HEAP_GUARD_DEBUG_LEVEL (DEBUG_POOL|DEBUG_PAGE) - -typedef struct { - UINT32 TailMark; - UINT32 HeadMark; - EFI_PHYSICAL_ADDRESS Address; - LIST_ENTRY Link; -} HEAP_GUARD_NODE; - -/** - Internal function. Converts a memory range to the specified type. - The range must exist in the memory map. - - @param Start The first address of the range Must be pa= ge - aligned. - @param NumberOfPages The number of pages to convert. - @param NewType The new type for the memory range. - - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_NOT_FOUND Could not find a descriptor cover the spe= cified - range or convertion not allowed. - @retval EFI_SUCCESS Successfully converts the memory range to= the - specified type. - -**/ -EFI_STATUS -CoreConvertPages ( - IN UINT64 Start, - IN UINT64 NumberOfPages, - IN EFI_MEMORY_TYPE NewType - ); - -/** - Allocate or free guarded memory. - - @param[in] Start Start address of memory to allocate or free. - @param[in] NumberOfPages Memory size in pages. - @param[in] NewType Memory type to convert to. - - @return VOID. -**/ -EFI_STATUS -CoreConvertPagesWithGuard ( - IN UINT64 Start, - IN UINTN NumberOfPages, - IN EFI_MEMORY_TYPE NewType - ); - -/** - 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 for. - @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 Guar= d. - - @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 Guard. - - The purpose of this function is to keep the shared Guard page with adjac= ent - memory block if it's still in guard, or free it if no more sharing. Anot= her - 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 - ); - -/** - Adjust address of free memory according to existing and/or required Guar= d. - - This function will check if there're existing Guard pages of adjacent - 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 Gua= rd. -**/ -UINT64 -AdjustMemoryS ( - IN UINT64 Start, - IN UINT64 Size, - IN UINT64 SizeRequested - ); - -/** - Check to see if the pool at the given address should be guarded or not. - - @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 not. - - @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. -**/ -VOID -EFIAPI -DumpGuardedMemoryBitmap ( - VOID - ); - -/** - Adjust the pool head position to make sure the Guard page is adjavent 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 - ); - -extern BOOLEAN mOnGuarding; - -#endif +/** @file + Data type, macros and function prototypes of heap guard feature. + +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 IMPLI= ED. + +**/ + +#ifndef _HEAPGUARD_H_ +#define _HEAPGUARD_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, the +// 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-bit +// system, like below. +// +// 512 * 512 * 512 * 512 * 1K * 64b * 4K +// 111111111 111111111 111111111 111111111 1111111111 111111 1111111111= 11 +// 63 54 45 36 27 17 11 = 0 +// 9b 9b 9b 9b 10b 6b 12b +// L0 -> L1 -> L2 -> L3 -> L4 -> bits -> page +// 1FF 1FF 1FF 1FF 3FF 3F FFF +// +// L4 table has 1K * sizeof(UINT64) =3D 8K (2-page), which can track 256MB +// memory. Each table of L0-L3 will be allocated when its memory address +// range is to be tracked. Only 1-page will be allocated each time. This +// can save memories used to establish this map table. +// +// For a normal configuration of system with 4G memory, two levels of tabl= es +// can track the whole memory, because two levels (L3+L4) of map tables ha= ve +// already coverred 37-bit of memory address. And for a normal UEFI BIOS, +// 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 spans 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_BYTE= S) + +// 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 travers= ing +// {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 BIT0 +#define GUARD_HEAP_TYPE_PAGE BIT1 + +// +// Debug message level +// +#define HEAP_GUARD_DEBUG_LEVEL (DEBUG_POOL|DEBUG_PAGE) + +typedef struct { + UINT32 TailMark; + UINT32 HeadMark; + EFI_PHYSICAL_ADDRESS Address; + LIST_ENTRY Link; +} HEAP_GUARD_NODE; + +/** + Internal function. Converts a memory range to the specified type. + The range must exist in the memory map. + + @param Start The first address of the range Must be pa= ge + aligned. + @param NumberOfPages The number of pages to convert. + @param NewType The new type for the memory range. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND Could not find a descriptor cover the spe= cified + range or convertion not allowed. + @retval EFI_SUCCESS Successfully converts the memory range to= the + specified type. + +**/ +EFI_STATUS +CoreConvertPages ( + IN UINT64 Start, + IN UINT64 NumberOfPages, + IN EFI_MEMORY_TYPE NewType + ); + +/** + Allocate or free guarded memory. + + @param[in] Start Start address of memory to allocate or free. + @param[in] NumberOfPages Memory size in pages. + @param[in] NewType Memory type to convert to. + + @return VOID. +**/ +EFI_STATUS +CoreConvertPagesWithGuard ( + IN UINT64 Start, + IN UINTN NumberOfPages, + IN EFI_MEMORY_TYPE NewType + ); + +/** + 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 for. + @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 Guar= d. + + @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 Guard. + + The purpose of this function is to keep the shared Guard page with adjac= ent + memory block if it's still in guard, or free it if no more sharing. Anot= her + 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 + ); + +/** + Adjust address of free memory according to existing and/or required Guar= d. + + This function will check if there're existing Guard pages of adjacent + 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 Gua= rd. +**/ +UINT64 +AdjustMemoryS ( + IN UINT64 Start, + IN UINT64 Size, + IN UINT64 SizeRequested + ); + +/** + Check to see if the pool at the given address should be guarded or not. + + @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 not. + + @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. +**/ +VOID +EFIAPI +DumpGuardedMemoryBitmap ( + VOID + ); + +/** + Adjust the pool head position to make sure the Guard page is adjavent 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 + ); + +extern BOOLEAN mOnGuarding; + +#endif diff --git a/MdeModulePkg/Core/Dxe/Mem/Imem.h b/MdeModulePkg/Core/Dxe/Mem/I= mem.h index 8a6ae50b88..e58a5d62ba 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Imem.h +++ b/MdeModulePkg/Core/Dxe/Mem/Imem.h @@ -1,7 +1,7 @@ /** @file Data structure and functions to allocate and free memory space. =20 -Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 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 @@ -61,7 +61,7 @@ typedef struct { @param PoolType The type of memory for the new pool pages @param NumberOfPages No of pages to allocate @param Alignment Bits to align. - @param NeedGuard Flag to indicate Guard page is needed or = not + @param NeedGuard Flag to indicate Guard page is needed or = not =20 @return The allocated memory, or NULL =20 @@ -70,8 +70,8 @@ VOID * CoreAllocatePoolPages ( IN EFI_MEMORY_TYPE PoolType, IN UINTN NumberOfPages, - IN UINTN Alignment, - IN BOOLEAN NeedGuard + IN UINTN Alignment, + IN BOOLEAN NeedGuard ); =20 =20 @@ -97,7 +97,7 @@ CoreFreePoolPages ( =20 @param PoolType Type of pool to allocate @param Size The amount of pool to allocate - @param NeedGuard Flag to indicate Guard page is needed or = not + @param NeedGuard Flag to indicate Guard page is needed or = not =20 @return The allocate pool, or NULL =20 @@ -105,8 +105,8 @@ CoreFreePoolPages ( VOID * CoreAllocatePoolI ( IN EFI_MEMORY_TYPE PoolType, - IN UINTN Size, - IN BOOLEAN NeedGuard + IN UINTN Size, + IN BOOLEAN NeedGuard ); =20 =20 @@ -149,34 +149,34 @@ CoreReleaseMemoryLock ( VOID ); =20 -/** - Allocates pages from the memory map. - - @param Type The type of allocation to perform - @param MemoryType The type of memory to turn the allocated = pages - into - @param NumberOfPages The number of pages to allocate - @param Memory A pointer to receive the base allocated m= emory - address - @param NeedGuard Flag to indicate Guard page is needed or = not - - @return Status. On success, Memory is filled in with the base address al= located - @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined= in - spec. - @retval EFI_NOT_FOUND Could not allocate pages match the requir= ement. - @retval EFI_OUT_OF_RESOURCES No enough pages to allocate. - @retval EFI_SUCCESS Pages successfully allocated. - -**/ -EFI_STATUS -EFIAPI -CoreInternalAllocatePages ( - IN EFI_ALLOCATE_TYPE Type, - IN EFI_MEMORY_TYPE MemoryType, - IN UINTN NumberOfPages, - IN OUT EFI_PHYSICAL_ADDRESS *Memory, - IN BOOLEAN NeedGuard - ); +/** + Allocates pages from the memory map. + + @param Type The type of allocation to perform + @param MemoryType The type of memory to turn the allocated = pages + into + @param NumberOfPages The number of pages to allocate + @param Memory A pointer to receive the base allocated m= emory + address + @param NeedGuard Flag to indicate Guard page is needed or = not + + @return Status. On success, Memory is filled in with the base address al= located + @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined= in + spec. + @retval EFI_NOT_FOUND Could not allocate pages match the requir= ement. + @retval EFI_OUT_OF_RESOURCES No enough pages to allocate. + @retval EFI_SUCCESS Pages successfully allocated. + +**/ +EFI_STATUS +EFIAPI +CoreInternalAllocatePages ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NumberOfPages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory, + IN BOOLEAN NeedGuard + ); =20 // // Internal Global data diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/P= age.c index f1e4a37f2a..2034b64cd7 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -14,7 +14,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER= EXPRESS OR IMPLIED. =20 #include "DxeMain.h" #include "Imem.h" -#include "HeapGuard.h" +#include "HeapGuard.h" =20 // // Entry for tracking the memory regions for each memory type to coalesce = similar memory types @@ -288,12 +288,12 @@ AllocateMemoryMapEntry ( // // The list is empty, to allocate one page to refuel the list // - FreeDescriptorEntries =3D CoreAllocatePoolPages ( - EfiBootServicesData, + FreeDescriptorEntries =3D CoreAllocatePoolPages ( + EfiBootServicesData, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION_G= RANULARITY), - DEFAULT_PAGE_ALLOCATION_GRANULARITY, - FALSE - ); + DEFAULT_PAGE_ALLOCATION_GRANULARITY, + FALSE + ); if (FreeDescriptorEntries !=3D NULL) { // // Enque the free memmory map entries into the list @@ -901,40 +901,40 @@ CoreConvertPagesEx ( CoreAddRange (MemType, Start, RangeEnd, Attribute); if (ChangingType && (MemType =3D=3D EfiConventionalMemory)) { if (Start =3D=3D 0) { - // - // Avoid calling DEBUG_CLEAR_MEMORY() for an address of 0 because = this - // macro will ASSERT() if address is 0. Instead, CoreAddRange() - // guarantees that the page starting at address 0 is always filled - // with zeros. - // + // + // Avoid calling DEBUG_CLEAR_MEMORY() for an address of 0 because = this + // macro will ASSERT() if address is 0. Instead, CoreAddRange() + // guarantees that the page starting at address 0 is always filled + // with zeros. + // if (RangeEnd > EFI_PAGE_SIZE) { DEBUG_CLEAR_MEMORY ((VOID *)(UINTN) EFI_PAGE_SIZE, (UINTN) (Rang= eEnd - EFI_PAGE_SIZE + 1)); } } else { - // - // If Heap Guard is enabled, the page at the top and/or bottom of - // this memory block to free might be inaccessible. Skipping them - // to avoid page fault exception. - // - UINT64 StartToClear; - UINT64 EndToClear; - - StartToClear =3D Start; - EndToClear =3D RangeEnd; - if (PcdGet8 (PcdHeapGuardPropertyMask) & (BIT1|BIT0)) { - if (IsGuardPage(StartToClear)) { - StartToClear +=3D EFI_PAGE_SIZE; - } - if (IsGuardPage (EndToClear)) { - EndToClear -=3D EFI_PAGE_SIZE; - } - ASSERT (EndToClear > StartToClear); - } - - DEBUG_CLEAR_MEMORY( - (VOID *)(UINTN)StartToClear, - (UINTN)(EndToClear - StartToClear + 1) - ); + // + // If Heap Guard is enabled, the page at the top and/or bottom of + // this memory block to free might be inaccessible. Skipping them + // to avoid page fault exception. + // + UINT64 StartToClear; + UINT64 EndToClear; + + StartToClear =3D Start; + EndToClear =3D RangeEnd; + if (PcdGet8 (PcdHeapGuardPropertyMask) & (BIT1|BIT0)) { + if (IsGuardPage(StartToClear)) { + StartToClear +=3D EFI_PAGE_SIZE; + } + if (IsGuardPage (EndToClear)) { + EndToClear -=3D EFI_PAGE_SIZE; + } + ASSERT (EndToClear > StartToClear); + } + + DEBUG_CLEAR_MEMORY( + (VOID *)(UINTN)StartToClear, + (UINTN)(EndToClear - StartToClear + 1) + ); } } =20 @@ -1021,7 +1021,7 @@ CoreUpdateMemoryAttributes ( @param NewType The type of memory the range is going to = be turned into @param Alignment Bits to align with - @param NeedGuard Flag to indicate Guard page is needed or = not + @param NeedGuard Flag to indicate Guard page is needed or = not =20 @return The base address of the range, or 0 if the range was not found =20 @@ -1032,8 +1032,8 @@ CoreFindFreePagesI ( IN UINT64 MinAddress, IN UINT64 NumberOfPages, IN EFI_MEMORY_TYPE NewType, - IN UINTN Alignment, - IN BOOLEAN NeedGuard + IN UINTN Alignment, + IN BOOLEAN NeedGuard ) { UINT64 NumberOfBytes; @@ -1125,17 +1125,17 @@ CoreFindFreePagesI ( // If this is the best match so far remember it // if (DescEnd > Target) { - if (NeedGuard) { - DescEnd =3D AdjustMemoryS ( - DescEnd + 1 - DescNumberOfBytes, - DescNumberOfBytes, - NumberOfBytes - ); - if (DescEnd =3D=3D 0) { - continue; - } - } - + if (NeedGuard) { + DescEnd =3D AdjustMemoryS ( + DescEnd + 1 - DescNumberOfBytes, + DescNumberOfBytes, + NumberOfBytes + ); + if (DescEnd =3D=3D 0) { + continue; + } + } + Target =3D DescEnd; } } @@ -1166,7 +1166,7 @@ CoreFindFreePagesI ( @param NewType The type of memory the range is going to = be turned into @param Alignment Bits to align with - @param NeedGuard Flag to indicate Guard page is needed or = not + @param NeedGuard Flag to indicate Guard page is needed or = not =20 @return The base address of the range, or 0 if the range was not found. =20 @@ -1176,8 +1176,8 @@ FindFreePages ( IN UINT64 MaxAddress, IN UINT64 NoPages, IN EFI_MEMORY_TYPE NewType, - IN UINTN Alignment, - IN BOOLEAN NeedGuard + IN UINTN Alignment, + IN BOOLEAN NeedGuard ) { UINT64 Start; @@ -1191,8 +1191,8 @@ FindFreePages ( mMemoryTypeStatistics[NewType].BaseAddress,=20 NoPages,=20 NewType,=20 - Alignment, - NeedGuard + Alignment, + NeedGuard ); if (Start !=3D 0) { return Start; @@ -1203,8 +1203,8 @@ FindFreePages ( // Attempt to find free pages in the default allocation bin // if (MaxAddress >=3D mDefaultMaximumAddress) { - Start =3D CoreFindFreePagesI (mDefaultMaximumAddress, 0, NoPages, NewT= ype, - Alignment, NeedGuard); + Start =3D CoreFindFreePagesI (mDefaultMaximumAddress, 0, NoPages, NewT= ype, + Alignment, NeedGuard); if (Start !=3D 0) { if (Start < mDefaultBaseAddress) { mDefaultBaseAddress =3D Start; @@ -1219,8 +1219,8 @@ FindFreePages ( // address range. If this allocation fails, then there are not enough=20 // resources anywhere to satisfy the request. // - Start =3D CoreFindFreePagesI (MaxAddress, 0, NoPages, NewType, Alignment, - NeedGuard); + Start =3D CoreFindFreePagesI (MaxAddress, 0, NoPages, NewType, Alignment, + NeedGuard); if (Start !=3D 0) { return Start; } @@ -1235,7 +1235,7 @@ FindFreePages ( // // If any memory resources were promoted, then re-attempt the allocation // - return FindFreePages (MaxAddress, NoPages, NewType, Alignment, NeedGuard= ); + return FindFreePages (MaxAddress, NoPages, NewType, Alignment, NeedGuard= ); } =20 =20 @@ -1248,7 +1248,7 @@ FindFreePages ( @param NumberOfPages The number of pages to allocate @param Memory A pointer to receive the base allocated m= emory address - @param NeedGuard Flag to indicate Guard page is needed or = not + @param NeedGuard Flag to indicate Guard page is needed or = not =20 @return Status. On success, Memory is filled in with the base address al= located @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined= in @@ -1264,8 +1264,8 @@ CoreInternalAllocatePages ( IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINTN NumberOfPages, - IN OUT EFI_PHYSICAL_ADDRESS *Memory, - IN BOOLEAN NeedGuard + IN OUT EFI_PHYSICAL_ADDRESS *Memory, + IN BOOLEAN NeedGuard ) { EFI_STATUS Status; @@ -1351,8 +1351,8 @@ CoreInternalAllocatePages ( // If not a specific address, then find an address to allocate // if (Type !=3D AllocateAddress) { - Start =3D FindFreePages (MaxAddress, NumberOfPages, MemoryType, Alignm= ent, - NeedGuard); + Start =3D FindFreePages (MaxAddress, NumberOfPages, MemoryType, Alignm= ent, + NeedGuard); if (Start =3D=3D 0) { Status =3D EFI_OUT_OF_RESOURCES; goto Done; @@ -1362,19 +1362,19 @@ CoreInternalAllocatePages ( // // Convert pages from FreeMemory to the requested type // - if (NeedGuard) { - Status =3D CoreConvertPagesWithGuard(Start, NumberOfPages, MemoryType); - } else { - Status =3D CoreConvertPages(Start, NumberOfPages, MemoryType); - } + if (NeedGuard) { + Status =3D CoreConvertPagesWithGuard(Start, NumberOfPages, MemoryType); + } else { + Status =3D CoreConvertPages(Start, NumberOfPages, MemoryType); + } =20 Done: CoreReleaseMemoryLock (); =20 if (!EFI_ERROR (Status)) { - if (NeedGuard) { - SetGuardForMemory (Start, NumberOfPages); - } + if (NeedGuard) { + SetGuardForMemory (Start, NumberOfPages); + } *Memory =3D Start; } =20 @@ -1409,11 +1409,11 @@ CoreAllocatePages ( ) { EFI_STATUS Status; - BOOLEAN NeedGuard; + BOOLEAN NeedGuard; =20 - NeedGuard =3D IsPageTypeToGuard (MemoryType, Type) && !mOnGuarding; - Status =3D CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, M= emory, - NeedGuard); + NeedGuard =3D IsPageTypeToGuard (MemoryType, Type) && !mOnGuarding; + Status =3D CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, M= emory, + NeedGuard); if (!EFI_ERROR (Status)) { CoreUpdateProfile ( (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), @@ -1454,7 +1454,7 @@ CoreInternalFreePages ( LIST_ENTRY *Link; MEMORY_MAP *Entry; UINTN Alignment; - BOOLEAN IsGuarded; + BOOLEAN IsGuarded; =20 // // Free the range @@ -1464,7 +1464,7 @@ CoreInternalFreePages ( // // Find the entry that the covers the range // - IsGuarded =3D FALSE; + IsGuarded =3D FALSE; Entry =3D NULL; for (Link =3D gMemoryMap.ForwardLink; Link !=3D &gMemoryMap; Link =3D Li= nk->ForwardLink) { Entry =3D CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); @@ -1501,20 +1501,20 @@ CoreInternalFreePages ( *MemoryType =3D Entry->Type; } =20 - IsGuarded =3D IsPageTypeToGuard (Entry->Type, AllocateAnyPages) && - IsMemoryGuarded (Memory); - if (IsGuarded) { - Status =3D CoreConvertPagesWithGuard (Memory, NumberOfPages, - EfiConventionalMemory); - } else { - Status =3D CoreConvertPages (Memory, NumberOfPages, EfiConventionalMem= ory); + IsGuarded =3D IsPageTypeToGuard (Entry->Type, AllocateAnyPages) && + IsMemoryGuarded (Memory); + if (IsGuarded) { + Status =3D CoreConvertPagesWithGuard (Memory, NumberOfPages, + EfiConventionalMemory); + } else { + Status =3D CoreConvertPages (Memory, NumberOfPages, EfiConventionalMem= ory); } =20 Done: CoreReleaseMemoryLock (); - if (IsGuarded) { - UnsetGuardForMemory(Memory, NumberOfPages); - } + if (IsGuarded) { + UnsetGuardForMemory(Memory, NumberOfPages); + } return Status; } =20 @@ -1912,12 +1912,12 @@ Done: =20 *MemoryMapSize =3D BufferSize; =20 - DEBUG_CODE ( - if (PcdGet8 (PcdHeapGuardPropertyMask) & (BIT1|BIT0)) { - DumpGuardedMemoryBitmap (); - } - ); - + DEBUG_CODE ( + if (PcdGet8 (PcdHeapGuardPropertyMask) & (BIT1|BIT0)) { + DumpGuardedMemoryBitmap (); + } + ); + return Status; } =20 @@ -1929,7 +1929,7 @@ Done: @param PoolType The type of memory for the new pool pages @param NumberOfPages No of pages to allocate @param Alignment Bits to align. - @param NeedGuard Flag to indicate Guard page is needed or = not + @param NeedGuard Flag to indicate Guard page is needed or = not =20 @return The allocated memory, or NULL =20 @@ -1938,8 +1938,8 @@ VOID * CoreAllocatePoolPages ( IN EFI_MEMORY_TYPE PoolType, IN UINTN NumberOfPages, - IN UINTN Alignment, - IN BOOLEAN NeedGuard + IN UINTN Alignment, + IN BOOLEAN NeedGuard ) { UINT64 Start; @@ -1947,8 +1947,8 @@ CoreAllocatePoolPages ( // // Find the pages to convert // - Start =3D FindFreePages (MAX_ADDRESS, NumberOfPages, PoolType, Alignment, - NeedGuard); + Start =3D FindFreePages (MAX_ADDRESS, NumberOfPages, PoolType, Alignment, + NeedGuard); =20 // // Convert it to boot services data @@ -1956,11 +1956,11 @@ CoreAllocatePoolPages ( if (Start =3D=3D 0) { DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "AllocatePoolPages: failed to alloca= te %d pages\n", (UINT32)NumberOfPages)); } else { - if (NeedGuard) { - CoreConvertPagesWithGuard (Start, NumberOfPages, PoolType); - } else { - CoreConvertPages (Start, NumberOfPages, PoolType); - } + if (NeedGuard) { + CoreConvertPagesWithGuard (Start, NumberOfPages, PoolType); + } else { + CoreConvertPages (Start, NumberOfPages, PoolType); + } } =20 return (VOID *)(UINTN) Start; diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c b/MdeModulePkg/Core/Dxe/Mem/P= ool.c index 77ca5671dc..b82b51595c 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Pool.c +++ b/MdeModulePkg/Core/Dxe/Mem/Pool.c @@ -14,7 +14,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER= EXPRESS OR IMPLIED. =20 #include "DxeMain.h" #include "Imem.h" -#include "HeapGuard.h" +#include "HeapGuard.h" =20 STATIC EFI_LOCK mPoolMemoryLock =3D EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTI= FY); =20 @@ -170,7 +170,7 @@ LookupPoolHead ( } } =20 - Pool =3D CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL), FALSE); + Pool =3D CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL), FALSE); if (Pool =3D=3D NULL) { return NULL; } @@ -215,8 +215,8 @@ CoreInternalAllocatePool ( OUT VOID **Buffer ) { - EFI_STATUS Status; - BOOLEAN NeedGuard; + EFI_STATUS Status; + BOOLEAN NeedGuard; =20 // // If it's not a valid type, fail it @@ -240,8 +240,8 @@ CoreInternalAllocatePool ( return EFI_OUT_OF_RESOURCES; } =20 - NeedGuard =3D IsPoolTypeToGuard (PoolType) && !mOnGuarding; - + NeedGuard =3D IsPoolTypeToGuard (PoolType) && !mOnGuarding; + // // Acquire the memory lock and make the allocation // @@ -250,7 +250,7 @@ CoreInternalAllocatePool ( return EFI_OUT_OF_RESOURCES; } =20 - *Buffer =3D CoreAllocatePoolI (PoolType, Size, NeedGuard); + *Buffer =3D CoreAllocatePoolI (PoolType, Size, NeedGuard); CoreReleaseLock (&mPoolMemoryLock); return (*Buffer !=3D NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES; } @@ -302,7 +302,7 @@ CoreAllocatePool ( @param PoolType The type of memory for the new pool pages @param NoPages No of pages to allocate @param Granularity Bits to align. - @param NeedGuard Flag to indicate Guard page is needed or = not + @param NeedGuard Flag to indicate Guard page is needed or = not =20 @return The allocated memory, or NULL =20 @@ -312,8 +312,8 @@ VOID * CoreAllocatePoolPagesI ( IN EFI_MEMORY_TYPE PoolType, IN UINTN NoPages, - IN UINTN Granularity, - IN BOOLEAN NeedGuard + IN UINTN Granularity, + IN BOOLEAN NeedGuard ) { VOID *Buffer; @@ -324,14 +324,14 @@ CoreAllocatePoolPagesI ( return NULL; } =20 - Buffer =3D CoreAllocatePoolPages (PoolType, NoPages, Granularity, NeedGu= ard); + Buffer =3D CoreAllocatePoolPages (PoolType, NoPages, Granularity, NeedGu= ard); CoreReleaseMemoryLock (); =20 if (Buffer !=3D NULL) { - if (NeedGuard) { - SetGuardForMemory ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, NoPages); - } - ApplyMemoryProtectionPolicy(EfiConventionalMemory, PoolType, + if (NeedGuard) { + SetGuardForMemory ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, NoPages); + } + ApplyMemoryProtectionPolicy(EfiConventionalMemory, PoolType, (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, EFI_PAGES_TO_SIZE (NoPages)); } return Buffer; @@ -343,7 +343,7 @@ CoreAllocatePoolPagesI ( =20 @param PoolType Type of pool to allocate @param Size The amount of pool to allocate - @param NeedGuard Flag to indicate Guard page is needed or = not + @param NeedGuard Flag to indicate Guard page is needed or = not =20 @return The allocate pool, or NULL =20 @@ -351,8 +351,8 @@ CoreAllocatePoolPagesI ( VOID * CoreAllocatePoolI ( IN EFI_MEMORY_TYPE PoolType, - IN UINTN Size, - IN BOOLEAN NeedGuard + IN UINTN Size, + IN BOOLEAN NeedGuard ) { POOL *Pool; @@ -366,7 +366,7 @@ CoreAllocatePoolI ( UINTN Offset, MaxOffset; UINTN NoPages; UINTN Granularity; - BOOLEAN HasPoolTail; + BOOLEAN HasPoolTail; =20 ASSERT_LOCKED (&mPoolMemoryLock); =20 @@ -384,9 +384,9 @@ CoreAllocatePoolI ( // Adjust the size by the pool header & tail overhead // =20 - HasPoolTail =3D !(NeedGuard && - ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) =3D=3D 0)); - + HasPoolTail =3D !(NeedGuard && + ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) =3D=3D 0)); + // // Adjusting the Size to be of proper alignment so that // we don't get an unaligned access fault later when @@ -406,16 +406,16 @@ CoreAllocatePoolI ( // If allocation is over max size, just allocate pages for the request // (slow) // - if (Index >=3D SIZE_TO_LIST (Granularity) || NeedGuard) { - if (!HasPoolTail) { - Size -=3D sizeof (POOL_TAIL); - } - NoPages =3D EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity)= - 1; + if (Index >=3D SIZE_TO_LIST (Granularity) || NeedGuard) { + if (!HasPoolTail) { + Size -=3D sizeof (POOL_TAIL); + } + NoPages =3D EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity)= - 1; NoPages &=3D ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1); - Head =3D CoreAllocatePoolPagesI (PoolType, NoPages, Granularity, NeedG= uard); - if (NeedGuard) { - Head =3D AdjustPoolHeadA ((EFI_PHYSICAL_ADDRESS)(UINTN)Head, NoPages= , Size); - } + Head =3D CoreAllocatePoolPagesI (PoolType, NoPages, Granularity, NeedG= uard); + if (NeedGuard) { + Head =3D AdjustPoolHeadA ((EFI_PHYSICAL_ADDRESS)(UINTN)Head, NoPages= , Size); + } goto Done; } =20 @@ -443,8 +443,8 @@ CoreAllocatePoolI ( // // Get another page // - NewPage =3D CoreAllocatePoolPagesI (PoolType, EFI_SIZE_TO_PAGES (Granu= larity), - Granularity, NeedGuard); + NewPage =3D CoreAllocatePoolPagesI (PoolType, EFI_SIZE_TO_PAGES (Granu= larity), + Granularity, NeedGuard); if (NewPage =3D=3D NULL) { goto Done; } @@ -490,11 +490,11 @@ Done: =20 if (Head !=3D NULL) { =20 - // - // Account the allocation - // - Pool->Used +=3D Size; - + // + // Account the allocation + // + Pool->Used +=3D Size; + // // If we have a pool buffer, fill in the header & tail info // @@ -502,24 +502,24 @@ Done: Head->Size =3D Size; Head->Type =3D (EFI_MEMORY_TYPE) PoolType; Buffer =3D Head->Data; - - if (HasPoolTail) { - Tail =3D HEAD_TO_TAIL (Head); - Tail->Signature =3D POOL_TAIL_SIGNATURE; - Tail->Size =3D Size; - - Size -=3D POOL_OVERHEAD; - } else { - Size -=3D SIZE_OF_POOL_HEAD; - } - - DEBUG_CLEAR_MEMORY (Buffer, Size); + + if (HasPoolTail) { + Tail =3D HEAD_TO_TAIL (Head); + Tail->Signature =3D POOL_TAIL_SIGNATURE; + Tail->Size =3D Size; + + Size -=3D POOL_OVERHEAD; + } else { + Size -=3D SIZE_OF_POOL_HEAD; + } + + DEBUG_CLEAR_MEMORY (Buffer, Size); =20 DEBUG (( DEBUG_POOL, "AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType, Buffer, - (UINT64)Size, + (UINT64)Size, (UINT64) Pool->Used )); =20 @@ -619,34 +619,34 @@ CoreFreePoolPagesI ( (EFI_PHYSICAL_ADDRESS)(UINTN)Memory, EFI_PAGES_TO_SIZE (NoPages)); } =20 -/** - Internal function. Frees guarded pool pages. - - @param PoolType The type of memory for the pool pages - @param Memory The base address to free - @param NoPages The number of pages to free - -**/ -STATIC -VOID -CoreFreePoolPagesWithGuard ( - IN EFI_MEMORY_TYPE PoolType, - IN EFI_PHYSICAL_ADDRESS Memory, - IN UINTN NoPages - ) -{ - EFI_PHYSICAL_ADDRESS MemoryGuarded; - UINTN NoPagesGuarded; - - MemoryGuarded =3D Memory; - NoPagesGuarded =3D NoPages; - - AdjustMemoryF (&Memory, &NoPages); - CoreFreePoolPagesI (PoolType, Memory, NoPages); - - UnsetGuardForMemory (MemoryGuarded, NoPagesGuarded); -} - +/** + Internal function. Frees guarded pool pages. + + @param PoolType The type of memory for the pool pages + @param Memory The base address to free + @param NoPages The number of pages to free + +**/ +STATIC +VOID +CoreFreePoolPagesWithGuard ( + IN EFI_MEMORY_TYPE PoolType, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NoPages + ) +{ + EFI_PHYSICAL_ADDRESS MemoryGuarded; + UINTN NoPagesGuarded; + + MemoryGuarded =3D Memory; + NoPagesGuarded =3D NoPages; + + AdjustMemoryF (&Memory, &NoPages); + CoreFreePoolPagesI (PoolType, Memory, NoPages); + + UnsetGuardForMemory (MemoryGuarded, NoPagesGuarded); +} + /** Internal function to free a pool entry. Caller must have the memory lock held @@ -675,8 +675,8 @@ CoreFreePoolI ( UINTN Offset; BOOLEAN AllFree; UINTN Granularity; - BOOLEAN IsGuarded; - BOOLEAN HasPoolTail; + BOOLEAN IsGuarded; + BOOLEAN HasPoolTail; =20 ASSERT(Buffer !=3D NULL); // @@ -689,32 +689,32 @@ CoreFreePoolI ( return EFI_INVALID_PARAMETER; } =20 - IsGuarded =3D IsPoolTypeToGuard (Head->Type) && - IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)Head); - HasPoolTail =3D !(IsGuarded && - ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) =3D=3D 0)); - - if (HasPoolTail) { - Tail =3D HEAD_TO_TAIL (Head); - ASSERT (Tail !=3D NULL); - - // - // Debug - // - ASSERT (Tail->Signature =3D=3D POOL_TAIL_SIGNATURE); - ASSERT (Head->Size =3D=3D Tail->Size); - - if (Tail->Signature !=3D POOL_TAIL_SIGNATURE) { - return EFI_INVALID_PARAMETER; - } - - if (Head->Size !=3D Tail->Size) { - return EFI_INVALID_PARAMETER; - } + IsGuarded =3D IsPoolTypeToGuard (Head->Type) && + IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)Head); + HasPoolTail =3D !(IsGuarded && + ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) =3D=3D 0)); + + if (HasPoolTail) { + Tail =3D HEAD_TO_TAIL (Head); + ASSERT (Tail !=3D NULL); + + // + // Debug + // + ASSERT (Tail->Signature =3D=3D POOL_TAIL_SIGNATURE); + ASSERT (Head->Size =3D=3D Tail->Size); + + if (Tail->Signature !=3D POOL_TAIL_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + if (Head->Size !=3D Tail->Size) { + return EFI_INVALID_PARAMETER; + } } =20 - ASSERT_LOCKED (&mPoolMemoryLock); - + ASSERT_LOCKED (&mPoolMemoryLock); + // // Determine the pool type and account for it // @@ -749,27 +749,27 @@ CoreFreePoolI ( // // If it's not on the list, it must be pool pages // - if (Index >=3D SIZE_TO_LIST (Granularity) || IsGuarded) { + if (Index >=3D SIZE_TO_LIST (Granularity) || IsGuarded) { =20 // // Return the memory pages back to free memory // - NoPages =3D EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity)= - 1; + NoPages =3D EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity)= - 1; NoPages &=3D ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1); - if (IsGuarded) { - Head =3D AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)Head); - CoreFreePoolPagesWithGuard ( - Pool->MemoryType, - (EFI_PHYSICAL_ADDRESS)(UINTN)Head, - NoPages - ); - } else { - CoreFreePoolPagesI ( - Pool->MemoryType, - (EFI_PHYSICAL_ADDRESS)(UINTN)Head, - NoPages - ); - } + if (IsGuarded) { + Head =3D AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)Head); + CoreFreePoolPagesWithGuard ( + Pool->MemoryType, + (EFI_PHYSICAL_ADDRESS)(UINTN)Head, + NoPages + ); + } else { + CoreFreePoolPagesI ( + Pool->MemoryType, + (EFI_PHYSICAL_ADDRESS)(UINTN)Head, + NoPages + ); + } =20 } else { =20 diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/C= ore/Dxe/Misc/MemoryProtection.c index e1e611ab79..21a52d0af5 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c @@ -1065,15 +1065,15 @@ CoreInitializeMemoryProtection ( // - code regions should have no EFI_MEMORY_XP attribute // - EfiConventionalMemory and EfiBootServicesData should use the // same attribute - // - heap guard should not be enabled for the same type of memory + // - heap guard should not be enabled for the same type of memory // ASSERT ((GetPermissionAttributeForMemoryType (EfiBootServicesCode) & EFI= _MEMORY_XP) =3D=3D 0); ASSERT ((GetPermissionAttributeForMemoryType (EfiRuntimeServicesCode) & = EFI_MEMORY_XP) =3D=3D 0); ASSERT ((GetPermissionAttributeForMemoryType (EfiLoaderCode) & EFI_MEMOR= Y_XP) =3D=3D 0); ASSERT (GetPermissionAttributeForMemoryType (EfiBootServicesData) =3D=3D GetPermissionAttributeForMemoryType (EfiConventionalMemory)); - ASSERT ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & PcdGet64 (PcdHeapGu= ardPoolType)) =3D=3D 0); - ASSERT ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & PcdGet64 (PcdHeapGu= ardPageType)) =3D=3D 0); + ASSERT ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & PcdGet64 (PcdHeapGu= ardPoolType)) =3D=3D 0); + ASSERT ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & PcdGet64 (PcdHeapGu= ardPageType)) =3D=3D 0); =20 if (mImageProtectionPolicy !=3D 0 || PcdGet64 (PcdDxeNxMemoryProtectionP= olicy) !=3D 0) { Status =3D CoreCreateEvent ( diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/Dx= eIplPeim/DxeIpl.inf index e8a05b0333..a1b8748432 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -116,7 +116,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ##= SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ##= CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ##= CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ##= CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ##= CONSUMES =20 [Pcd.IA32,Pcd.X64,Pcd.ARM,Pcd.AARCH64] gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIM= ES_CONSUMES diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg= /Core/DxeIplPeim/Ia32/DxeLoadFunc.c index 33c77374a9..5649265367 100644 --- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c @@ -211,37 +211,37 @@ IsExecuteDisableBitAvailable ( return Available; } =20 -/** - The function will check if page table should be setup or not. - - @retval TRUE Page table should be created. - @retval FALSE Page table should not be created. - -**/ -BOOLEAN -ToBuildPageTable ( - VOID - ) -{ - if (!IsIa32PaeSupport ()) { - return FALSE; - } - - if (IsNullDetectionEnabled ()) { - return TRUE; - } - - if (PcdGet8 (PcdHeapGuardPropertyMask) !=3D 0) { - return TRUE; - } - - if (PcdGetBool (PcdSetNxForStack) && IsExecuteDisableBitAvailable ()) { - return TRUE; - } - - return FALSE; -} - +/** + The function will check if page table should be setup or not. + + @retval TRUE Page table should be created. + @retval FALSE Page table should not be created. + +**/ +BOOLEAN +ToBuildPageTable ( + VOID + ) +{ + if (!IsIa32PaeSupport ()) { + return FALSE; + } + + if (IsNullDetectionEnabled ()) { + return TRUE; + } + + if (PcdGet8 (PcdHeapGuardPropertyMask) !=3D 0) { + return TRUE; + } + + if (PcdGetBool (PcdSetNxForStack) && IsExecuteDisableBitAvailable ()) { + return TRUE; + } + + return FALSE; +} + /** Transfers control to DxeCore. =20 @@ -416,7 +416,7 @@ HandOffToDxeCore ( TopOfStack =3D (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStac= k, CPU_STACK_ALIGNMENT); =20 PageTables =3D 0; - BuildPageTablesIa32Pae =3D ToBuildPageTable (); + BuildPageTablesIa32Pae =3D ToBuildPageTable (); if (BuildPageTablesIa32Pae) { PageTables =3D Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE); if (IsExecuteDisableBitAvailable ()) { diff --git a/MdeModulePkg/Core/PiSmmCore/HeapGuard.c b/MdeModulePkg/Core/Pi= SmmCore/HeapGuard.c index 6fda9ba430..8dd109b619 100644 --- a/MdeModulePkg/Core/PiSmmCore/HeapGuard.c +++ b/MdeModulePkg/Core/PiSmmCore/HeapGuard.c @@ -1,1467 +1,1467 @@ -/** @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 IMPLI= ED. - -**/ - -#include "HeapGuard.h" - -// -// Global to avoid infinite reentrance of memory allocation when updating -// page table attributes, which may need allocating pages for new PDE/PTE. -// -GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mOnGuarding =3D FALSE; - -// -// Pointer to table tracking the Guarded memory with bitmap, in which '1' -// is used to indicate memory guarded. '0' might be free memory or Guard -// page itself, depending on status of memory adjacent to it. -// -GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mGuardedMemoryMap =3D 0; - -// -// Current depth level of map table pointed by mGuardedMemoryMap. -// mMapLevel must be initialized at least by 1. It will be automatically -// updated according to the address of memory just tracked. -// -GLOBAL_REMOVE_IF_UNREFERENCED UINTN mMapLevel =3D 1; - -// -// Shift and mask for each level of map table -// -GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLevelShift[GUARDED_HEAP_MAP_TABLE_DEP= TH] - =3D GUARDED_HEAP_MAP_TABLE_DEPTH_SHIFT= S; -GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLevelMask[GUARDED_HEAP_MAP_TABLE_DEPT= H] - =3D GUARDED_HEAP_MAP_TABLE_DEPTH_MASKS; - -// -// SMM memory attribute protocol -// -EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *mSmmMemoryAttribute =3D NULL; - -/** - 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_BITS; - - 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_BITS; - - 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 Address. - 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_BITS; - - 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), Msbs); - } - - 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, EfiRuntimeService= sData, - 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 tab= le. - @param[out] BitMap Pointer to bitmap which covers the Address. - - @return The bit number from given Address to the end of current map tabl= e. -**/ -UINTN -FindGuardedMemoryMap ( - IN EFI_PHYSICAL_ADDRESS Address, - IN BOOLEAN AllocMapUnit, - OUT UINT64 **BitMap - ) -{ - UINTN Level; - 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, - mLevelShift[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1] - ) !=3D 0) { - - if (mGuardedMemoryMap !=3D 0) { - Size =3D (mLevelMask[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1] += 1) - * GUARDED_HEAP_MAP_ENTRY_BYTES; - MapMemory =3D (UINT64)(UINTN)PageAlloc (EFI_SIZE_TO_PAGES (Size)); - ASSERT (MapMemory !=3D 0); - - SetMem ((VOID *)(UINTN)MapMemory, Size, 0); - - *(UINT64 *)(UINTN)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 0) { - if (!AllocMapUnit) { - GuardMap =3D NULL; - break; - } - - Size =3D (mLevelMask[Level] + 1) * GUARDED_HEAP_MAP_ENTRY_BYTES; - MapMemory =3D (UINT64)(UINTN)PageAlloc (EFI_SIZE_TO_PAGES (Size)); - ASSERT (MapMemory !=3D 0); - - SetMem ((VOID *)(UINTN)MapMemory, Size, 0); - *GuardMap =3D MapMemory; - } - - Index =3D (UINTN)RShiftU64 (Address, mLevelShift[Level]); - Index &=3D mLevelMask[Level]; - GuardMap =3D (UINT64 *)(UINTN)((*GuardMap) + Index * sizeof (UINT64)); - - } - - BitsToUnitEnd =3D GUARDED_HEAP_MAP_BITS - GUARDED_HEAP_MAP_BIT_INDEX (Ad= dress); - *BitMap =3D GuardMap; - - return BitsToUnitEnd; -} - -/** - Set corresponding bits in bitmap table to 1 according to given memory ra= nge. - - @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 range. - - @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 memory ra= nge. - - @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; - UINT64 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 or no= t. - - @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 or no= t. - - @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 0b01); -} - -/** - 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] BaseAddress Page address to Guard at. - - @return VOID. -**/ -VOID -EFIAPI -SetGuardPage ( - IN EFI_PHYSICAL_ADDRESS BaseAddress - ) -{ - if (mSmmMemoryAttribute !=3D NULL) { - mOnGuarding =3D TRUE; - mSmmMemoryAttribute->SetMemoryAttributes ( - mSmmMemoryAttribute, - BaseAddress, - EFI_PAGE_SIZE, - EFI_MEMORY_RP - ); - mOnGuarding =3D FALSE; - } -} - -/** - 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] BaseAddress Page address to Guard at. - - @return VOID. -**/ -VOID -EFIAPI -UnsetGuardPage ( - IN EFI_PHYSICAL_ADDRESS BaseAddress - ) -{ - if (mSmmMemoryAttribute !=3D NULL) { - mOnGuarding =3D TRUE; - mSmmMemoryAttribute->ClearMemoryAttributes ( - mSmmMemoryAttribute, - BaseAddress, - EFI_PAGE_SIZE, - EFI_MEMORY_RP - ); - mOnGuarding =3D FALSE; - } -} - -/** - 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 allocatio= n. - - - @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 - || mOnGuarding - || AllocateType =3D=3D AllocateAddress) { - return FALSE; - } - - ConfigBit =3D 0; - if ((PageOrPool & GUARD_HEAP_TYPE_POOL) !=3D 0) { - ConfigBit |=3D PcdGet64 (PcdHeapGuardPoolType); - } - - if ((PageOrPool & GUARD_HEAP_TYPE_PAGE) !=3D 0) { - 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 not. - - @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 not. - - @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_PA= GE); -} - -/** - Check to see if the heap guard is enabled for page and/or pool allocatio= n. - - @return TRUE/FALSE. -**/ -BOOLEAN -IsHeapGuardEnabled ( - VOID - ) -{ - return IsMemoryTypeToGuard (EfiMaxMemoryType, AllocateAnyPages, - GUARD_HEAP_TYPE_POOL|GUARD_HEAP_TYPE_PAGE); -} - -/** - 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 for. - @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 block, - // 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 any. - // - 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 block, - // free it; otherwise, keep it. - // - UnsetGuardPage (GuardPage); - } - } else if (IsMemoryGuarded (GuardPage)) { - // - // Pages after memory to free are still in Guard. It's a partial free - // 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 Guar= d. - - This function will check if there're existing Guard pages of adjacent - 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 Gua= rd. -**/ -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 share. - return 0; - } - } - - // OK, we have enough pages for memory and its Guards. Return the End of= the - // free space. - return Target + SizeRequested - 1; -} - -/** - Adjust the start address and number of pages to free according to Guard. - - The purpose of this function is to keep the shared Guard page with adjac= ent - memory block if it's still in guard, or free it if no more sharing. Anot= her - 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 || *NumberOfPages = =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 block, - // 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 any. - // - 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 block, - // 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 free - // 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 Guar= d. - - @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 safe to - // adjust the start address and/or number of pages here, to make sure th= at - // 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 adjavent 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 add= ress. - @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 MaxAddre= ss) { - - // - // 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 - PagesToAlloc) - - EFI_PAGE_SIZE; - if (!IsGuardPage (HeadGuard)) { - // - // Add one if no Guard at the page before the address to allocate - // - PagesToAlloc +=3D 1; - HeadGuard =3D 0; - } - - if (Pages->NumberOfPages < PagesToAlloc) { - // Not enough space to allocate memory with Guards? Try next block. - continue; - } - - Address =3D InternalAllocPagesOnOneNode (Pages, PagesToAlloc, MaxAdd= ress); - ConvertSmmMemoryMapEntry(MemoryType, Address, PagesToAlloc, FALSE); - CoreFreeMemoryMapStack(); - if (HeadGuard =3D=3D 0) { - // 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 freed. - @param[in] NumberOfPages The number of pages to free. - @param[in] AddRegion If this memory is new added region. - - @retval EFI_NOT_FOUND Could not find the entry that covers the = range. - @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or N= umberOfPages 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 - ) -{ - UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINT64 TableEntry; - UINT64 Address; - UINT64 GuardPage; - INTN Level; - UINTN Index; - BOOLEAN OnGuarding; - - if (mGuardedMemoryMap =3D=3D 0) { - return; - } - - CopyMem (Entries, mLevelMask, sizeof (Entries)); - CopyMem (Shifts, mLevelShift, sizeof (Shifts)); - - SetMem (Tables, sizeof(Tables), 0); - SetMem (Addresses, sizeof(Addresses), 0); - SetMem (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 ((UINT64 *)(UINTN)(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 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[Level]= ); - - } -} - -/** - Hook function used to set all Guard pages after entering SMM mode. -**/ -VOID -SmmEntryPointMemoryManagementHook ( - VOID - ) -{ - EFI_STATUS Status; - - if (mSmmMemoryAttribute =3D=3D NULL) { - Status =3D SmmLocateProtocol ( - &gEdkiiSmmMemoryAttributeProtocolGuid, - NULL, - (VOID **)&mSmmMemoryAttribute - ); - if (!EFI_ERROR(Status)) { - SetAllGuardPages (); - } - } -} - -/** - Helper function to convert a UINT64 value in binary to a string. - - @param[in] Value Value of a UINT64 integer. - @param[out] BinString String buffer to contain the conversion result. - - @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. -**/ -VOID -EFIAPI -DumpGuardedMemoryBitmap ( - VOID - ) -{ - UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH]; - UINT64 TableEntry; - UINT64 Address; - INTN Level; - UINTN RepeatZero; - CHAR8 String[GUARDED_HEAP_MAP_ENTRY_BITS + 1]; - CHAR8 *Ruler1; - CHAR8 *Ruler2; - - if (mGuardedMemoryMap =3D=3D 0) { - return; - } - - Ruler1 =3D " 3 2 1 = 0"; - Ruler2 =3D "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA987654= 3210"; - - DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "=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 ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler1)); - DEBUG ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler2)); - - CopyMem (Entries, mLevelMask, sizeof (Entries)); - CopyMem (Shifts, mLevelShift, sizeof (Shifts)); - - SetMem (Indices, sizeof(Indices), 0); - SetMem (Tables, sizeof(Tables), 0); - SetMem (Addresses, sizeof(Addresses), 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 (( - HEAP_GUARD_DEBUG_LEVEL, - "=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 ((UINT64 *)(UINTN)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 ((HEAP_GUARD_DEBUG_LEVEL, "%016lx: %a\r\n", Address, Str= ing)); - } else if (RepeatZero =3D=3D 1) { - DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "... : ...\r\n")); - } - RepeatZero +=3D 1; - } - - } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) { - - Level +=3D 1; - Tables[Level] =3D TableEntry; - Addresses[Level] =3D Address; - Indices[Level] =3D 0; - RepeatZero =3D 0; - - continue; - - } else { - - RepeatZero =3D 0; - Uint64ToBinString(TableEntry, String); - DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "%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[Level]= ); - - } -} - -/** - 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 - ) -{ - EFI_STATUS Status; - UINT64 Attribute; - EFI_PHYSICAL_ADDRESS Address; - - if (mSmmMemoryAttribute =3D=3D NULL) { - return TRUE; - } - - Attribute =3D 0; - Address =3D BaseAddress - EFI_PAGE_SIZE; - Status =3D mSmmMemoryAttribute->GetMemoryAttributes ( - mSmmMemoryAttribute, - Address, - EFI_PAGE_SIZE, - &Attribute - ); - if (EFI_ERROR (Status) || (Attribute & EFI_MEMORY_RP) =3D=3D 0) { - DEBUG ((DEBUG_ERROR, "Head Guard is not set at: %016lx (%016lX)!!!\r\n= ", - Address, Attribute)); - DumpGuardedMemoryBitmap (); - return FALSE; - } - - Attribute =3D 0; - Address =3D BaseAddress + EFI_PAGES_TO_SIZE (NumberOfPages); - Status =3D mSmmMemoryAttribute->GetMemoryAttributes ( - mSmmMemoryAttribute, - Address, - EFI_PAGE_SIZE, - &Attribute - ); - if (EFI_ERROR (Status) || (Attribute & EFI_MEMORY_RP) =3D=3D 0) { - DEBUG ((DEBUG_ERROR, "Tail Guard is not set at: %016lx (%016lX)!!!\r\n= ", - Address, Attribute)); - DumpGuardedMemoryBitmap (); - return FALSE; - } - - return TRUE; -} - +/** @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 IMPLI= ED. + +**/ + +#include "HeapGuard.h" + +// +// Global to avoid infinite reentrance of memory allocation when updating +// page table attributes, which may need allocating pages for new PDE/PTE. +// +GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mOnGuarding =3D FALSE; + +// +// Pointer to table tracking the Guarded memory with bitmap, in which '1' +// is used to indicate memory guarded. '0' might be free memory or Guard +// page itself, depending on status of memory adjacent to it. +// +GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mGuardedMemoryMap =3D 0; + +// +// Current depth level of map table pointed by mGuardedMemoryMap. +// mMapLevel must be initialized at least by 1. It will be automatically +// updated according to the address of memory just tracked. +// +GLOBAL_REMOVE_IF_UNREFERENCED UINTN mMapLevel =3D 1; + +// +// Shift and mask for each level of map table +// +GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLevelShift[GUARDED_HEAP_MAP_TABLE_DEP= TH] + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_SHIFT= S; +GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLevelMask[GUARDED_HEAP_MAP_TABLE_DEPT= H] + =3D GUARDED_HEAP_MAP_TABLE_DEPTH_MASKS; + +// +// SMM memory attribute protocol +// +EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *mSmmMemoryAttribute =3D NULL; + +/** + 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_BITS; + + 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_BITS; + + 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 Address. + 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_BITS; + + 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), Msbs); + } + + 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, EfiRuntimeService= sData, + 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 tab= le. + @param[out] BitMap Pointer to bitmap which covers the Address. + + @return The bit number from given Address to the end of current map tabl= e. +**/ +UINTN +FindGuardedMemoryMap ( + IN EFI_PHYSICAL_ADDRESS Address, + IN BOOLEAN AllocMapUnit, + OUT UINT64 **BitMap + ) +{ + UINTN Level; + 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, + mLevelShift[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1] + ) !=3D 0) { + + if (mGuardedMemoryMap !=3D 0) { + Size =3D (mLevelMask[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1] += 1) + * GUARDED_HEAP_MAP_ENTRY_BYTES; + MapMemory =3D (UINT64)(UINTN)PageAlloc (EFI_SIZE_TO_PAGES (Size)); + ASSERT (MapMemory !=3D 0); + + SetMem ((VOID *)(UINTN)MapMemory, Size, 0); + + *(UINT64 *)(UINTN)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 0) { + if (!AllocMapUnit) { + GuardMap =3D NULL; + break; + } + + Size =3D (mLevelMask[Level] + 1) * GUARDED_HEAP_MAP_ENTRY_BYTES; + MapMemory =3D (UINT64)(UINTN)PageAlloc (EFI_SIZE_TO_PAGES (Size)); + ASSERT (MapMemory !=3D 0); + + SetMem ((VOID *)(UINTN)MapMemory, Size, 0); + *GuardMap =3D MapMemory; + } + + Index =3D (UINTN)RShiftU64 (Address, mLevelShift[Level]); + Index &=3D mLevelMask[Level]; + GuardMap =3D (UINT64 *)(UINTN)((*GuardMap) + Index * sizeof (UINT64)); + + } + + BitsToUnitEnd =3D GUARDED_HEAP_MAP_BITS - GUARDED_HEAP_MAP_BIT_INDEX (Ad= dress); + *BitMap =3D GuardMap; + + return BitsToUnitEnd; +} + +/** + Set corresponding bits in bitmap table to 1 according to given memory ra= nge. + + @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 range. + + @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 memory ra= nge. + + @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; + UINT64 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 or no= t. + + @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 or no= t. + + @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 0b01); +} + +/** + 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] BaseAddress Page address to Guard at. + + @return VOID. +**/ +VOID +EFIAPI +SetGuardPage ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +{ + if (mSmmMemoryAttribute !=3D NULL) { + mOnGuarding =3D TRUE; + mSmmMemoryAttribute->SetMemoryAttributes ( + mSmmMemoryAttribute, + BaseAddress, + EFI_PAGE_SIZE, + EFI_MEMORY_RP + ); + mOnGuarding =3D FALSE; + } +} + +/** + 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] BaseAddress Page address to Guard at. + + @return VOID. +**/ +VOID +EFIAPI +UnsetGuardPage ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +{ + if (mSmmMemoryAttribute !=3D NULL) { + mOnGuarding =3D TRUE; + mSmmMemoryAttribute->ClearMemoryAttributes ( + mSmmMemoryAttribute, + BaseAddress, + EFI_PAGE_SIZE, + EFI_MEMORY_RP + ); + mOnGuarding =3D FALSE; + } +} + +/** + 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 allocatio= n. + + + @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 + || mOnGuarding + || AllocateType =3D=3D AllocateAddress) { + return FALSE; + } + + ConfigBit =3D 0; + if ((PageOrPool & GUARD_HEAP_TYPE_POOL) !=3D 0) { + ConfigBit |=3D PcdGet64 (PcdHeapGuardPoolType); + } + + if ((PageOrPool & GUARD_HEAP_TYPE_PAGE) !=3D 0) { + 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 not. + + @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 not. + + @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_PA= GE); +} + +/** + Check to see if the heap guard is enabled for page and/or pool allocatio= n. + + @return TRUE/FALSE. +**/ +BOOLEAN +IsHeapGuardEnabled ( + VOID + ) +{ + return IsMemoryTypeToGuard (EfiMaxMemoryType, AllocateAnyPages, + GUARD_HEAP_TYPE_POOL|GUARD_HEAP_TYPE_PAGE); +} + +/** + 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 for. + @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 block, + // 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 any. + // + 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 block, + // free it; otherwise, keep it. + // + UnsetGuardPage (GuardPage); + } + } else if (IsMemoryGuarded (GuardPage)) { + // + // Pages after memory to free are still in Guard. It's a partial free + // 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 Guar= d. + + This function will check if there're existing Guard pages of adjacent + 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 Gua= rd. +**/ +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 share. + return 0; + } + } + + // OK, we have enough pages for memory and its Guards. Return the End of= the + // free space. + return Target + SizeRequested - 1; +} + +/** + Adjust the start address and number of pages to free according to Guard. + + The purpose of this function is to keep the shared Guard page with adjac= ent + memory block if it's still in guard, or free it if no more sharing. Anot= her + 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 || *NumberOfPages = =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 block, + // 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 any. + // + 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 block, + // 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 free + // 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 Guar= d. + + @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 safe to + // adjust the start address and/or number of pages here, to make sure th= at + // 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 adjavent 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 add= ress. + @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 MaxAddre= ss) { + + // + // 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 - PagesToAlloc) - + EFI_PAGE_SIZE; + if (!IsGuardPage (HeadGuard)) { + // + // Add one if no Guard at the page before the address to allocate + // + PagesToAlloc +=3D 1; + HeadGuard =3D 0; + } + + if (Pages->NumberOfPages < PagesToAlloc) { + // Not enough space to allocate memory with Guards? Try next block. + continue; + } + + Address =3D InternalAllocPagesOnOneNode (Pages, PagesToAlloc, MaxAdd= ress); + ConvertSmmMemoryMapEntry(MemoryType, Address, PagesToAlloc, FALSE); + CoreFreeMemoryMapStack(); + if (HeadGuard =3D=3D 0) { + // 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 freed. + @param[in] NumberOfPages The number of pages to free. + @param[in] AddRegion If this memory is new added region. + + @retval EFI_NOT_FOUND Could not find the entry that covers the = range. + @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or N= umberOfPages 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 + ) +{ + UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 TableEntry; + UINT64 Address; + UINT64 GuardPage; + INTN Level; + UINTN Index; + BOOLEAN OnGuarding; + + if (mGuardedMemoryMap =3D=3D 0) { + return; + } + + CopyMem (Entries, mLevelMask, sizeof (Entries)); + CopyMem (Shifts, mLevelShift, sizeof (Shifts)); + + SetMem (Tables, sizeof(Tables), 0); + SetMem (Addresses, sizeof(Addresses), 0); + SetMem (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 ((UINT64 *)(UINTN)(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 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[Level]= ); + + } +} + +/** + Hook function used to set all Guard pages after entering SMM mode. +**/ +VOID +SmmEntryPointMemoryManagementHook ( + VOID + ) +{ + EFI_STATUS Status; + + if (mSmmMemoryAttribute =3D=3D NULL) { + Status =3D SmmLocateProtocol ( + &gEdkiiSmmMemoryAttributeProtocolGuid, + NULL, + (VOID **)&mSmmMemoryAttribute + ); + if (!EFI_ERROR(Status)) { + SetAllGuardPages (); + } + } +} + +/** + Helper function to convert a UINT64 value in binary to a string. + + @param[in] Value Value of a UINT64 integer. + @param[out] BinString String buffer to contain the conversion result. + + @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. +**/ +VOID +EFIAPI +DumpGuardedMemoryBitmap ( + VOID + ) +{ + UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH]; + UINT64 TableEntry; + UINT64 Address; + INTN Level; + UINTN RepeatZero; + CHAR8 String[GUARDED_HEAP_MAP_ENTRY_BITS + 1]; + CHAR8 *Ruler1; + CHAR8 *Ruler2; + + if (mGuardedMemoryMap =3D=3D 0) { + return; + } + + Ruler1 =3D " 3 2 1 = 0"; + Ruler2 =3D "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA987654= 3210"; + + DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "=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 ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler1)); + DEBUG ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler2)); + + CopyMem (Entries, mLevelMask, sizeof (Entries)); + CopyMem (Shifts, mLevelShift, sizeof (Shifts)); + + SetMem (Indices, sizeof(Indices), 0); + SetMem (Tables, sizeof(Tables), 0); + SetMem (Addresses, sizeof(Addresses), 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 (( + HEAP_GUARD_DEBUG_LEVEL, + "=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 ((UINT64 *)(UINTN)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 ((HEAP_GUARD_DEBUG_LEVEL, "%016lx: %a\r\n", Address, Str= ing)); + } else if (RepeatZero =3D=3D 1) { + DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "... : ...\r\n")); + } + RepeatZero +=3D 1; + } + + } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) { + + Level +=3D 1; + Tables[Level] =3D TableEntry; + Addresses[Level] =3D Address; + Indices[Level] =3D 0; + RepeatZero =3D 0; + + continue; + + } else { + + RepeatZero =3D 0; + Uint64ToBinString(TableEntry, String); + DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "%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[Level]= ); + + } +} + +/** + 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 + ) +{ + EFI_STATUS Status; + UINT64 Attribute; + EFI_PHYSICAL_ADDRESS Address; + + if (mSmmMemoryAttribute =3D=3D NULL) { + return TRUE; + } + + Attribute =3D 0; + Address =3D BaseAddress - EFI_PAGE_SIZE; + Status =3D mSmmMemoryAttribute->GetMemoryAttributes ( + mSmmMemoryAttribute, + Address, + EFI_PAGE_SIZE, + &Attribute + ); + if (EFI_ERROR (Status) || (Attribute & EFI_MEMORY_RP) =3D=3D 0) { + DEBUG ((DEBUG_ERROR, "Head Guard is not set at: %016lx (%016lX)!!!\r\n= ", + Address, Attribute)); + DumpGuardedMemoryBitmap (); + return FALSE; + } + + Attribute =3D 0; + Address =3D BaseAddress + EFI_PAGES_TO_SIZE (NumberOfPages); + Status =3D mSmmMemoryAttribute->GetMemoryAttributes ( + mSmmMemoryAttribute, + Address, + EFI_PAGE_SIZE, + &Attribute + ); + if (EFI_ERROR (Status) || (Attribute & EFI_MEMORY_RP) =3D=3D 0) { + DEBUG ((DEBUG_ERROR, "Tail Guard is not set at: %016lx (%016lX)!!!\r\n= ", + Address, Attribute)); + DumpGuardedMemoryBitmap (); + return FALSE; + } + + return TRUE; +} + diff --git a/MdeModulePkg/Core/PiSmmCore/HeapGuard.h b/MdeModulePkg/Core/Pi= SmmCore/HeapGuard.h index 8698ff9f87..a6f92a2042 100644 --- a/MdeModulePkg/Core/PiSmmCore/HeapGuard.h +++ b/MdeModulePkg/Core/PiSmmCore/HeapGuard.h @@ -1,398 +1,398 @@ -/** @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 IMPLI= ED. - -**/ - -#ifndef _HEAPGUARD_H_ -#define _HEAPGUARD_H_ - -#include "PiSmmCore.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, the -// 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-bit -// system, like below. -// -// 512 * 512 * 512 * 512 * 1K * 64b * 4K -// 111111111 111111111 111111111 111111111 1111111111 111111 1111111111= 11 -// 63 54 45 36 27 17 11 = 0 -// 9b 9b 9b 9b 10b 6b 12b -// L0 -> L1 -> L2 -> L3 -> L4 -> bits -> page -// 1FF 1FF 1FF 1FF 3FF 3F FFF -// -// L4 table has 1K * sizeof(UINT64) =3D 8K (2-page), which can track 256MB -// memory. Each table of L0-L3 will be allocated when its memory address -// range is to be tracked. Only 1-page will be allocated each time. This -// can save memories used to establish this map table. -// -// For a normal configuration of system with 4G memory, two levels of tabl= es -// can track the whole memory, because two levels (L3+L4) of map tables ha= ve -// already coverred 37-bit of memory address. And for a normal UEFI BIOS, -// 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 spans 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_BYTE= S) - -// 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 travers= ing -// {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 - -// -// Debug message level -// -#define HEAP_GUARD_DEBUG_LEVEL (DEBUG_POOL|DEBUG_PAGE) - -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 for. - @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 Guar= d. - - @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 Guard. - - The purpose of this function is to keep the shared Guard page with adjac= ent - memory block if it's still in guard, or free it if no more sharing. Anot= her - 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 not. - - @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 not. - - @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. -**/ -VOID -EFIAPI -DumpGuardedMemoryBitmap ( - VOID - ); - -/** - Adjust the pool head position to make sure the Guard page is adjavent 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 add= ress. - @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 freed. - @param[in] NumberOfPages The number of pages to free. - @param[in] AddRegion If this memory is new added region. - - @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 allocatio= n. - - @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 +/** @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 IMPLI= ED. + +**/ + +#ifndef _HEAPGUARD_H_ +#define _HEAPGUARD_H_ + +#include "PiSmmCore.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, the +// 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-bit +// system, like below. +// +// 512 * 512 * 512 * 512 * 1K * 64b * 4K +// 111111111 111111111 111111111 111111111 1111111111 111111 1111111111= 11 +// 63 54 45 36 27 17 11 = 0 +// 9b 9b 9b 9b 10b 6b 12b +// L0 -> L1 -> L2 -> L3 -> L4 -> bits -> page +// 1FF 1FF 1FF 1FF 3FF 3F FFF +// +// L4 table has 1K * sizeof(UINT64) =3D 8K (2-page), which can track 256MB +// memory. Each table of L0-L3 will be allocated when its memory address +// range is to be tracked. Only 1-page will be allocated each time. This +// can save memories used to establish this map table. +// +// For a normal configuration of system with 4G memory, two levels of tabl= es +// can track the whole memory, because two levels (L3+L4) of map tables ha= ve +// already coverred 37-bit of memory address. And for a normal UEFI BIOS, +// 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 spans 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_BYTE= S) + +// 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 travers= ing +// {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 + +// +// Debug message level +// +#define HEAP_GUARD_DEBUG_LEVEL (DEBUG_POOL|DEBUG_PAGE) + +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 for. + @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 Guar= d. + + @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 Guard. + + The purpose of this function is to keep the shared Guard page with adjac= ent + memory block if it's still in guard, or free it if no more sharing. Anot= her + 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 not. + + @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 not. + + @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. +**/ +VOID +EFIAPI +DumpGuardedMemoryBitmap ( + VOID + ); + +/** + Adjust the pool head position to make sure the Guard page is adjavent 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 add= ress. + @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 freed. + @param[in] NumberOfPages The number of pages to free. + @param[in] AddRegion If this memory is new added region. + + @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 allocatio= n. + + @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/Page.c b/MdeModulePkg/Core/PiSmmCo= re/Page.c index 5f5b4bbe1c..8909d46a00 100644 --- a/MdeModulePkg/Core/PiSmmCore/Page.c +++ b/MdeModulePkg/Core/PiSmmCore/Page.c @@ -64,8 +64,8 @@ LIST_ENTRY mFreeMemoryMapEntryList =3D INITIALIZE_LIST_= HEAD_VARIABLE (mFreeMemor @param[out] Memory A pointer to receive the base alloca= ted memory address. @param[in] AddRegion If this memory is new added region. - @param[in] NeedGuard Flag to indicate Guard page is needed - or not + @param[in] NeedGuard Flag to indicate Guard page is needed + or not =20 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined= in spec. @retval EFI_NOT_FOUND Could not allocate pages match the requir= ement. @@ -79,8 +79,8 @@ SmmInternalAllocatePagesEx ( IN EFI_MEMORY_TYPE MemoryType, IN UINTN NumberOfPages, OUT EFI_PHYSICAL_ADDRESS *Memory, - IN BOOLEAN AddRegion, - IN BOOLEAN NeedGuard + IN BOOLEAN AddRegion, + IN BOOLEAN NeedGuard ); =20 /** @@ -115,8 +115,8 @@ AllocateMemoryMapEntry ( EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (RUNTIME_PAGE_ALLOCATION_GRANULARITY), &Mem, - TRUE, - FALSE + TRUE, + FALSE ); ASSERT_EFI_ERROR (Status); if(!EFI_ERROR (Status)) { @@ -692,8 +692,8 @@ InternalAllocAddress ( @param[out] Memory A pointer to receive the base alloca= ted memory address. @param[in] AddRegion If this memory is new added region. - @param[in] NeedGuard Flag to indicate Guard page is needed - or not + @param[in] NeedGuard Flag to indicate Guard page is needed + or not =20 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined= in spec. @retval EFI_NOT_FOUND Could not allocate pages match the requir= ement. @@ -707,8 +707,8 @@ SmmInternalAllocatePagesEx ( IN EFI_MEMORY_TYPE MemoryType, IN UINTN NumberOfPages, OUT EFI_PHYSICAL_ADDRESS *Memory, - IN BOOLEAN AddRegion, - IN BOOLEAN NeedGuard + IN BOOLEAN AddRegion, + IN BOOLEAN NeedGuard ) { UINTN RequestedAddress; @@ -730,21 +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 TRUE); - return EFI_SUCCESS; - } - } - + 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 TRUE); + return EFI_SUCCESS; + } + } + *Memory =3D InternalAllocMaxAddress ( &mSmmMemoryMap, NumberOfPages, @@ -788,8 +788,8 @@ SmmInternalAllocatePagesEx ( @param[in] NumberOfPages The number of pages to allocate. @param[out] Memory A pointer to receive the base alloca= ted memory address. - @param[in] NeedGuard Flag to indicate Guard page is needed - or not + @param[in] NeedGuard Flag to indicate Guard page is needed + or not =20 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined= in spec. @retval EFI_NOT_FOUND Could not allocate pages match the requir= ement. @@ -803,12 +803,12 @@ SmmInternalAllocatePages ( IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINTN NumberOfPages, - OUT EFI_PHYSICAL_ADDRESS *Memory, - IN BOOLEAN NeedGuard + OUT EFI_PHYSICAL_ADDRESS *Memory, + IN BOOLEAN NeedGuard ) { - return SmmInternalAllocatePagesEx (Type, MemoryType, NumberOfPages, Memo= ry, - FALSE, NeedGuard); + return SmmInternalAllocatePagesEx (Type, MemoryType, NumberOfPages, Memo= ry, + FALSE, NeedGuard); } =20 /** @@ -837,11 +837,11 @@ SmmAllocatePages ( ) { EFI_STATUS Status; - BOOLEAN NeedGuard; + BOOLEAN NeedGuard; =20 - NeedGuard =3D IsPageTypeToGuard (MemoryType, Type); - Status =3D SmmInternalAllocatePages (Type, MemoryType, NumberOfPages, Me= mory, - NeedGuard); + NeedGuard =3D IsPageTypeToGuard (MemoryType, Type); + Status =3D SmmInternalAllocatePages (Type, MemoryType, NumberOfPages, Me= mory, + NeedGuard); if (!EFI_ERROR (Status)) { SmmCoreUpdateProfile ( (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), @@ -960,7 +960,7 @@ SmmInternalFreePagesEx ( =20 @param[in] Memory Base address of memory being freed. @param[in] NumberOfPages The number of pages to free. - @param[in] IsGuarded Is the memory to free guarded or not. + @param[in] IsGuarded Is the memory to free guarded or not. =20 @retval EFI_NOT_FOUND Could not find the entry that covers the = range. @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or N= umberOfPages is zero. @@ -971,13 +971,13 @@ EFI_STATUS EFIAPI SmmInternalFreePages ( IN EFI_PHYSICAL_ADDRESS Memory, - IN UINTN NumberOfPages, - IN BOOLEAN IsGuarded + IN UINTN NumberOfPages, + IN BOOLEAN IsGuarded ) { - if (IsGuarded) { - return SmmInternalFreePagesExWithGuard (Memory, NumberOfPages, FALSE); - } + if (IsGuarded) { + return SmmInternalFreePagesExWithGuard (Memory, NumberOfPages, FALSE); + } return SmmInternalFreePagesEx (Memory, NumberOfPages, FALSE); } =20 @@ -1000,10 +1000,10 @@ SmmFreePages ( ) { EFI_STATUS Status; - BOOLEAN IsGuarded; + BOOLEAN IsGuarded; =20 - IsGuarded =3D IsHeapGuardEnabled () && IsMemoryGuarded (Memory); - Status =3D SmmInternalFreePages (Memory, NumberOfPages, IsGuarded); + 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/Pi= SmmCore/PiSmmCore.c index a0b295b31a..a7467aca20 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c @@ -506,11 +506,11 @@ SmmEntryPoint ( // PlatformHookBeforeSmmDispatch (); =20 - // - // Call memory management hook function - // - SmmEntryPointMemoryManagementHook (); - + // + // Call memory management hook function + // + SmmEntryPointMemoryManagementHook (); + // // If a legacy boot has occured, then make sure gSmmCorePrivate is not a= ccessed // @@ -704,7 +704,7 @@ SmmMain ( // gSmmCorePrivate->Smst =3D &gSmmCoreSmst; gSmmCorePrivate->SmmEntryPoint =3D SmmEntryPoint; - + // // No need to initialize memory service. // It is done in constructor of PiSmmCoreMemoryAllocationLib(), diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h b/MdeModulePkg/Core/Pi= SmmCore/PiSmmCore.h index fbbecfae52..cdc491c324 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h @@ -33,7 +33,7 @@ #include #include #include -#include +#include =20 #include #include @@ -61,7 +61,7 @@ #include =20 #include "PiSmmCorePrivateData.h" -#include "HeapGuard.h" +#include "HeapGuard.h" =20 // // Used to build a table of SMI Handlers that the SMM Core registers @@ -320,7 +320,7 @@ SmmAllocatePages ( @param NumberOfPages The number of pages to allocate @param Memory A pointer to receive the base allocated m= emory address - @param NeedGuard Flag to indicate Guard page is needed or = not + @param NeedGuard Flag to indicate Guard page is needed or = not =20 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined= in spec. @retval EFI_NOT_FOUND Could not allocate pages match the requir= ement. @@ -334,8 +334,8 @@ SmmInternalAllocatePages ( IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINTN NumberOfPages, - OUT EFI_PHYSICAL_ADDRESS *Memory, - IN BOOLEAN NeedGuard + OUT EFI_PHYSICAL_ADDRESS *Memory, + IN BOOLEAN NeedGuard ); =20 /** @@ -361,8 +361,8 @@ SmmFreePages ( =20 @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 guarded - or not + @param IsGuarded Flag to indicate if the memory is guarded + or not =20 @retval EFI_NOT_FOUND Could not find the entry that covers the = range @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or N= umberOfPages is zero. @@ -373,8 +373,8 @@ EFI_STATUS EFIAPI SmmInternalFreePages ( IN EFI_PHYSICAL_ADDRESS Memory, - IN UINTN NumberOfPages, - IN BOOLEAN IsGuarded + IN UINTN NumberOfPages, + IN BOOLEAN IsGuarded ); =20 /** @@ -1262,74 +1262,74 @@ typedef enum { =20 extern LIST_ENTRY mSmmPoolLists[SmmPoolTypeMax][MAX_POOL_INDEX]; =20 -/** - 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 add= ress. - - @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 region. -**/ -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 freed. - @param[in] NumberOfPages The number of pages to free. - @param[in] AddRegion If this memory is new added region. - - @retval EFI_NOT_FOUND Could not find the entry that covers the = range. - @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or N= umberOfPages 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 - ); - +/** + 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 add= ress. + + @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 region. +**/ +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 freed. + @param[in] NumberOfPages The number of pages to free. + @param[in] AddRegion If this memory is new added region. + + @retval EFI_NOT_FOUND Could not find the entry that covers the = range. + @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or N= umberOfPages 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 ead821b78f..1583641887 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf @@ -40,7 +40,7 @@ SmramProfileRecord.c MemoryAttributesTable.c SmiHandlerProfile.c - HeapGuard.c + HeapGuard.c =20 [Packages] MdePkg/MdePkg.dec @@ -90,8 +90,8 @@ gEfiSmmGpiDispatch2ProtocolGuid ## SOMETIMES_CONSUMES gEfiSmmIoTrapDispatch2ProtocolGuid ## SOMETIMES_CONSUMES gEfiSmmUsbDispatch2ProtocolGuid ## SOMETIMES_CONSUMES - gEfiSmmCpuProtocolGuid ## SOMETIMES_CONSUMES - gEdkiiSmmMemoryAttributeProtocolGuid ## CONSUMES + gEfiSmmCpuProtocolGuid ## SOMETIMES_CONSUMES + gEdkiiSmmMemoryAttributeProtocolGuid ## CONSUMES =20 [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber ##= SOMETIMES_CONSUMES @@ -100,9 +100,9 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask ##= CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileDriverPath ##= CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdSmiHandlerProfilePropertyMask ##= CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPageType ##= CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType ##= CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ##= CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPageType ##= CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType ##= CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ##= CONSUMES =20 [Guids] gAprioriGuid ## SOMETIMES_CONSUMES ##= File diff --git a/MdeModulePkg/Core/PiSmmCore/Pool.c b/MdeModulePkg/Core/PiSmmCo= re/Pool.c index e77caa8853..798d66994b 100644 --- a/MdeModulePkg/Core/PiSmmCore/Pool.c +++ b/MdeModulePkg/Core/PiSmmCore/Pool.c @@ -144,9 +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, FALSE); + Status =3D SmmInternalAllocatePages (AllocateAnyPages, PoolType, + EFI_SIZE_TO_PAGES (MAX_POOL_SIZE <<= 1), + &Address, FALSE); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } @@ -245,9 +245,9 @@ SmmInternalAllocatePool ( EFI_STATUS Status; EFI_PHYSICAL_ADDRESS Address; UINTN PoolIndex; - BOOLEAN HasPoolTail; - BOOLEAN NeedGuard; - UINTN NoPages; + BOOLEAN HasPoolTail; + BOOLEAN NeedGuard; + UINTN NoPages; =20 Address =3D 0; =20 @@ -256,47 +256,47 @@ SmmInternalAllocatePool ( return EFI_INVALID_PARAMETER; } =20 - NeedGuard =3D IsPoolTypeToGuard (PoolType); - HasPoolTail =3D !(NeedGuard && - ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) =3D=3D 0)); - + 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 || NeedGuard) { - if (!HasPoolTail) { - Size -=3D sizeof (POOL_TAIL); - } - - NoPages =3D EFI_SIZE_TO_PAGES (Size); - Status =3D SmmInternalAllocatePages (AllocateAnyPages, PoolType, NoPag= es, - &Address, NeedGuard); + 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, NoPag= es, + &Address, NeedGuard); if (EFI_ERROR (Status)) { return Status; } =20 - if (NeedGuard) { - ASSERT (VerifyMemoryGuard (Address, NoPages) =3D=3D TRUE); - Address =3D (EFI_PHYSICAL_ADDRESS)(UINTN)AdjustPoolHeadA ( - Address, - NoPages, - Size - ); - } - + if (NeedGuard) { + ASSERT (VerifyMemoryGuard (Address, NoPages) =3D=3D TRUE); + Address =3D (EFI_PHYSICAL_ADDRESS)(UINTN)AdjustPoolHeadA ( + Address, + NoPages, + Size + ); + } + PoolHdr =3D (POOL_HEADER*)(UINTN)Address; PoolHdr->Signature =3D POOL_HEAD_SIGNATURE; - PoolHdr->Size =3D Size; + PoolHdr->Size =3D Size; PoolHdr->Available =3D FALSE; PoolHdr->Type =3D PoolType; - - if (HasPoolTail) { - 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; } @@ -368,18 +368,18 @@ SmmInternalFreePool ( { FREE_POOL_HEADER *FreePoolHdr; POOL_TAIL *PoolTail; - BOOLEAN HasPoolTail; - BOOLEAN MemoryGuarded; + BOOLEAN HasPoolTail; + BOOLEAN MemoryGuarded; =20 if (Buffer =3D=3D NULL) { return EFI_INVALID_PARAMETER; } =20 - MemoryGuarded =3D IsHeapGuardEnabled () && - IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer); - HasPoolTail =3D !(MemoryGuarded && - ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) =3D=3D 0)= ); - + 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); @@ -387,28 +387,28 @@ SmmInternalFreePool ( return EFI_INVALID_PARAMETER; } =20 - 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; - } - } else { - PoolTail =3D NULL; + 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; + } + } else { + PoolTail =3D NULL; } =20 - 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 (MemoryGuarded) { + Buffer =3D AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr); + return SmmInternalFreePages ( + (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, + EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size), + TRUE + ); } =20 if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) { @@ -416,8 +416,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), - FALSE + EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size), + FALSE ); } return InternalFreePoolByIndex (FreePoolHdr, PoolTail); diff --git a/MdeModulePkg/Include/Protocol/SmmMemoryAttribute.h b/MdeModule= Pkg/Include/Protocol/SmmMemoryAttribute.h index 86788bf194..0700eb51d6 100644 --- a/MdeModulePkg/Include/Protocol/SmmMemoryAttribute.h +++ b/MdeModulePkg/Include/Protocol/SmmMemoryAttribute.h @@ -1,136 +1,136 @@ -/** @file - SMM Memory Attribute Protocol provides retrieval and update service - for memory attributes in EFI SMM environment. - - 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 BS= D License - which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. - -**/ - -#ifndef __SMM_MEMORYATTRIBUTE_H__ -#define __SMM_MEMORYATTRIBUTE_H__ - -//{69B792EA-39CE-402D-A2A6-F721DE351DFE} -#define EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL_GUID \ - { \ - 0x69b792ea, 0x39ce, 0x402d, { 0xa2, 0xa6, 0xf7, 0x21, 0xde, 0x35, 0x1d= , 0xfe } \ - } - -typedef struct _EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL EDKII_SMM_MEMORY_ATTRI= BUTE_PROTOCOL; - -/** - This function set given attributes of the memory region specified by - BaseAddress and Length. - - @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. - @param BaseAddress The physical address that is the start address= of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes The bit mask of attributes to set for the memo= ry - region. - - @retval EFI_SUCCESS The attributes were set for the memory reg= ion. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes specified an illegal combinatio= n of - attributes that cannot be set together. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specifi= ed - by BaseAddress and Length. - The bit mask of attributes is not support = for - the memory resource range specified by - BaseAddress and Length. - -**/ -typedef -EFI_STATUS -(EFIAPI *EDKII_SMM_SET_MEMORY_ATTRIBUTES)( - IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes - ); - -/** - This function clears given attributes of the memory region specified by - BaseAddress and Length. - - @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. - @param BaseAddress The physical address that is the start address= of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes The bit mask of attributes to set for the memo= ry - region. - - @retval EFI_SUCCESS The attributes were set for the memory reg= ion. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes specified an illegal combinatio= n of - attributes that cannot be set together. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specifi= ed - by BaseAddress and Length. - The bit mask of attributes is not support = for - the memory resource range specified by - BaseAddress and Length. - -**/ -typedef -EFI_STATUS -(EFIAPI *EDKII_SMM_CLEAR_MEMORY_ATTRIBUTES)( - IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes - ); - -/** - This function retrieve the attributes of the memory region specified by - BaseAddress and Length. If different attributes are got from different p= art - of the memory region, EFI_NO_MAPPING will be returned. - - @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. - @param BaseAddress The physical address that is the start address= of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes Pointer to attributes returned. - - @retval EFI_SUCCESS The attributes got for the memory region. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes is NULL. - @retval EFI_NO_MAPPING Attributes are not consistent cross the me= mory - region. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specifi= ed - by BaseAddress and Length. - The bit mask of attributes is not support = for - the memory resource range specified by - BaseAddress and Length. - -**/ -typedef -EFI_STATUS -(EFIAPI *EDKII_SMM_GET_MEMORY_ATTRIBUTES)( - IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - OUT UINT64 *Attributes - ); - -/// -/// SMM Memory Attribute Protocol provides services to retrieve or update -/// attribute of memory in the EFI SMM environment. -/// -struct _EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL { - EDKII_SMM_GET_MEMORY_ATTRIBUTES GetMemoryAttributes; - EDKII_SMM_SET_MEMORY_ATTRIBUTES SetMemoryAttributes; - EDKII_SMM_CLEAR_MEMORY_ATTRIBUTES ClearMemoryAttributes; -}; - -extern EFI_GUID gEdkiiSmmMemoryAttributeProtocolGuid; - -#endif +/** @file + SMM Memory Attribute Protocol provides retrieval and update service + for memory attributes in EFI SMM environment. + + 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 BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef __SMM_MEMORYATTRIBUTE_H__ +#define __SMM_MEMORYATTRIBUTE_H__ + +//{69B792EA-39CE-402D-A2A6-F721DE351DFE} +#define EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL_GUID \ + { \ + 0x69b792ea, 0x39ce, 0x402d, { 0xa2, 0xa6, 0xf7, 0x21, 0xde, 0x35, 0x1d= , 0xfe } \ + } + +typedef struct _EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL EDKII_SMM_MEMORY_ATTRI= BUTE_PROTOCOL; + +/** + This function set given attributes of the memory region specified by + BaseAddress and Length. + + @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. + @param BaseAddress The physical address that is the start address= of + a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memo= ry + region. + + @retval EFI_SUCCESS The attributes were set for the memory reg= ion. + @retval EFI_INVALID_PARAMETER Length is zero. + Attributes specified an illegal combinatio= n of + attributes that cannot be set together. + @retval EFI_UNSUPPORTED The processor does not support one or more + bytes of the memory resource range specifi= ed + by BaseAddress and Length. + The bit mask of attributes is not support = for + the memory resource range specified by + BaseAddress and Length. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_SMM_SET_MEMORY_ATTRIBUTES)( + IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + +/** + This function clears given attributes of the memory region specified by + BaseAddress and Length. + + @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. + @param BaseAddress The physical address that is the start address= of + a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memo= ry + region. + + @retval EFI_SUCCESS The attributes were set for the memory reg= ion. + @retval EFI_INVALID_PARAMETER Length is zero. + Attributes specified an illegal combinatio= n of + attributes that cannot be set together. + @retval EFI_UNSUPPORTED The processor does not support one or more + bytes of the memory resource range specifi= ed + by BaseAddress and Length. + The bit mask of attributes is not support = for + the memory resource range specified by + BaseAddress and Length. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_SMM_CLEAR_MEMORY_ATTRIBUTES)( + IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + +/** + This function retrieve the attributes of the memory region specified by + BaseAddress and Length. If different attributes are got from different p= art + of the memory region, EFI_NO_MAPPING will be returned. + + @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. + @param BaseAddress The physical address that is the start address= of + a memory region. + @param Length The size in bytes of the memory region. + @param Attributes Pointer to attributes returned. + + @retval EFI_SUCCESS The attributes got for the memory region. + @retval EFI_INVALID_PARAMETER Length is zero. + Attributes is NULL. + @retval EFI_NO_MAPPING Attributes are not consistent cross the me= mory + region. + @retval EFI_UNSUPPORTED The processor does not support one or more + bytes of the memory resource range specifi= ed + by BaseAddress and Length. + The bit mask of attributes is not support = for + the memory resource range specified by + BaseAddress and Length. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_SMM_GET_MEMORY_ATTRIBUTES)( + IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + OUT UINT64 *Attributes + ); + +/// +/// SMM Memory Attribute Protocol provides services to retrieve or update +/// attribute of memory in the EFI SMM environment. +/// +struct _EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL { + EDKII_SMM_GET_MEMORY_ATTRIBUTES GetMemoryAttributes; + EDKII_SMM_SET_MEMORY_ATTRIBUTES SetMemoryAttributes; + EDKII_SMM_CLEAR_MEMORY_ATTRIBUTES ClearMemoryAttributes; +}; + +extern EFI_GUID gEdkiiSmmMemoryAttributeProtocolGuid; + +#endif diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 40d5cd5fb6..856d67aceb 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -559,9 +559,9 @@ ## Include/Protocol/SmmEndofS3Resume.h gEdkiiSmmEndOfS3ResumeProtocolGuid =3D { 0x96f5296d, 0x05f7, 0x4f3c, {0x= 84, 0x67, 0xe4, 0x56, 0x89, 0x0e, 0x0c, 0xb5 } } =20 - ## Include/Protocol/SmmMemoryAttribute.h - gEdkiiSmmMemoryAttributeProtocolGuid =3D { 0x69b792ea, 0x39ce, 0x402d, {= 0xa2, 0xa6, 0xf7, 0x21, 0xde, 0x35, 0x1d, 0xfe } } - + ## Include/Protocol/SmmMemoryAttribute.h + gEdkiiSmmMemoryAttributeProtocolGuid =3D { 0x69b792ea, 0x39ce, 0x402d, {= 0xa2, 0xa6, 0xf7, 0x21, 0xde, 0x35, 0x1d, 0xfe } } + # # [Error.gEfiMdeModulePkgTokenSpaceGuid] # 0x80000001 | Invalid value provided. @@ -892,63 +892,63 @@ # @Prompt Init Value in Temp Stack gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack|0x5AA55AA5|UINT32= |0x30001051 =20 - ## Indicates which type allocation need guard page. - # Below is bit mask for this PCD: (Order is same as UEFI spec)
- # EfiReservedMemoryType 0x0000000000000001
- # EfiLoaderCode 0x0000000000000002
- # EfiLoaderData 0x0000000000000004
- # EfiBootServicesCode 0x0000000000000008
- # EfiBootServicesData 0x0000000000000010
- # EfiRuntimeServicesCode 0x0000000000000020
- # EfiRuntimeServicesData 0x0000000000000040
- # EfiConventionalMemory 0x0000000000000080
- # EfiUnusableMemory 0x0000000000000100
- # EfiACPIReclaimMemory 0x0000000000000200
- # EfiACPIMemoryNVS 0x0000000000000400
- # EfiMemoryMappedIO 0x0000000000000800
- # EfiMemoryMappedIOPortSpace 0x0000000000001000
- # EfiPalCode 0x0000000000002000
- # EfiPersistentMemory 0x0000000000004000
- # OEM Reserved 0x4000000000000000
- # OS Reserved 0x8000000000000000
- # e.g. LoaderCode+LoaderData+BootServicesCode+BootServicesData are neede= d, 0x1E should be used.
- # @Prompt The memory type mask for Page Guard. - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPageType|0x0|UINT64|0x30001052 - - ## Indicates which type allocation need guard page. - # Below is bit mask for this PCD: (Order is same as UEFI spec)
- # EfiReservedMemoryType 0x0000000000000001
- # EfiLoaderCode 0x0000000000000002
- # EfiLoaderData 0x0000000000000004
- # EfiBootServicesCode 0x0000000000000008
- # EfiBootServicesData 0x0000000000000010
- # EfiRuntimeServicesCode 0x0000000000000020
- # EfiRuntimeServicesData 0x0000000000000040
- # EfiConventionalMemory 0x0000000000000080
- # EfiUnusableMemory 0x0000000000000100
- # EfiACPIReclaimMemory 0x0000000000000200
- # EfiACPIMemoryNVS 0x0000000000000400
- # EfiMemoryMappedIO 0x0000000000000800
- # EfiMemoryMappedIOPortSpace 0x0000000000001000
- # EfiPalCode 0x0000000000002000
- # EfiPersistentMemory 0x0000000000004000
- # OEM Reserved 0x4000000000000000
- # OS Reserved 0x8000000000000000
- # e.g. LoaderCode+LoaderData+BootServicesCode+BootServicesData are neede= d, 0x1E should be used.
- # @Prompt The memory type mask for Pool Guard. - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType|0x0|UINT64|0x30001053 - - ## This mask is to control Heap Guard behavior. - # BIT0 - Enable UEFI page guard.
- # BIT1 - Enable UEFI pool guard.
- # BIT2 - Enable SMM page guard.
- # BIT3 - Enable SMM pool guard.
- # BIT7 - The direction of Guard Page for Pool Guard. - # 0 - The returned pool is adjacent to the bottom guard page. - # 1 - The returned pool is adjacent to the top guard page.
- # @Prompt The Heap Guard feature mask - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask|0x0|UINT8|0x3000= 1054 - + ## Indicates which type allocation need guard page. + # Below is bit mask for this PCD: (Order is same as UEFI spec)
+ # EfiReservedMemoryType 0x0000000000000001
+ # EfiLoaderCode 0x0000000000000002
+ # EfiLoaderData 0x0000000000000004
+ # EfiBootServicesCode 0x0000000000000008
+ # EfiBootServicesData 0x0000000000000010
+ # EfiRuntimeServicesCode 0x0000000000000020
+ # EfiRuntimeServicesData 0x0000000000000040
+ # EfiConventionalMemory 0x0000000000000080
+ # EfiUnusableMemory 0x0000000000000100
+ # EfiACPIReclaimMemory 0x0000000000000200
+ # EfiACPIMemoryNVS 0x0000000000000400
+ # EfiMemoryMappedIO 0x0000000000000800
+ # EfiMemoryMappedIOPortSpace 0x0000000000001000
+ # EfiPalCode 0x0000000000002000
+ # EfiPersistentMemory 0x0000000000004000
+ # OEM Reserved 0x4000000000000000
+ # OS Reserved 0x8000000000000000
+ # e.g. LoaderCode+LoaderData+BootServicesCode+BootServicesData are neede= d, 0x1E should be used.
+ # @Prompt The memory type mask for Page Guard. + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPageType|0x0|UINT64|0x30001052 + + ## Indicates which type allocation need guard page. + # Below is bit mask for this PCD: (Order is same as UEFI spec)
+ # EfiReservedMemoryType 0x0000000000000001
+ # EfiLoaderCode 0x0000000000000002
+ # EfiLoaderData 0x0000000000000004
+ # EfiBootServicesCode 0x0000000000000008
+ # EfiBootServicesData 0x0000000000000010
+ # EfiRuntimeServicesCode 0x0000000000000020
+ # EfiRuntimeServicesData 0x0000000000000040
+ # EfiConventionalMemory 0x0000000000000080
+ # EfiUnusableMemory 0x0000000000000100
+ # EfiACPIReclaimMemory 0x0000000000000200
+ # EfiACPIMemoryNVS 0x0000000000000400
+ # EfiMemoryMappedIO 0x0000000000000800
+ # EfiMemoryMappedIOPortSpace 0x0000000000001000
+ # EfiPalCode 0x0000000000002000
+ # EfiPersistentMemory 0x0000000000004000
+ # OEM Reserved 0x4000000000000000
+ # OS Reserved 0x8000000000000000
+ # e.g. LoaderCode+LoaderData+BootServicesCode+BootServicesData are neede= d, 0x1E should be used.
+ # @Prompt The memory type mask for Pool Guard. + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType|0x0|UINT64|0x30001053 + + ## This mask is to control Heap Guard behavior. + # BIT0 - Enable UEFI page guard.
+ # BIT1 - Enable UEFI pool guard.
+ # BIT2 - Enable SMM page guard.
+ # BIT3 - Enable SMM pool guard.
+ # BIT7 - The direction of Guard Page for Pool Guard. + # 0 - The returned pool is adjacent to the bottom guard page. + # 1 - The returned pool is adjacent to the top guard page.
+ # @Prompt The Heap Guard feature mask + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask|0x0|UINT8|0x3000= 1054 + [PcdsFixedAtBuild, PcdsPatchableInModule] ## Dynamic type PCD can be registered callback function for Pcd setting = action. # PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of= callback function diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni index 827fbbccf9..588905a9a1 100644 --- a/MdeModulePkg/MdeModulePkg.uni +++ b/MdeModulePkg/MdeModulePkg.uni @@ -1146,61 +1146,61 @@ = "SEC fills the full temp stack with this values. When swit= ch stack, PeiCore can check\n" = "this value in the temp stack to know how many stack has b= een used.\n" =20 -#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPageType_PROMPT #l= anguage en-US "The memory type mask for Page Guard" - -#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPageType_HELP #l= anguage en-US "Indicates which type allocation need guard page.\n" - = " Below is bit mask for this PCD: (Order is same as UEFI spec= )
\n" - = " EfiReservedMemoryType 0x0000000000000001\n" - = " EfiLoaderCode 0x0000000000000002\n" - = " EfiLoaderData 0x0000000000000004\n" - = " EfiBootServicesCode 0x0000000000000008\n" - = " EfiBootServicesData 0x0000000000000010\n" - = " EfiRuntimeServicesCode 0x0000000000000020\n" - = " EfiRuntimeServicesData 0x0000000000000040\n" - = " EfiConventionalMemory 0x0000000000000080\n" - = " EfiUnusableMemory 0x0000000000000100\n" - = " EfiACPIReclaimMemory 0x0000000000000200\n" - = " EfiACPIMemoryNVS 0x0000000000000400\n" - = " EfiMemoryMappedIO 0x0000000000000800\n" - = " EfiMemoryMappedIOPortSpace 0x0000000000001000\n" - = " EfiPalCode 0x0000000000002000\n" - = " EfiPersistentMemory 0x0000000000004000\n" - = " OEM Reserved 0x4000000000000000\n" - = " OS Reserved 0x8000000000000000\n" - = " e.g. LoaderCode+LoaderData+BootServicesCode+BootServicesDat= a are needed, 0x1E should be used.
" - -#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPoolType_PROMPT #l= anguage en-US "The memory type mask for Pool Guard" - -#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPoolType_HELP #l= anguage en-US "Indicates which type allocation need guard page.\n" - = " Below is bit mask for this PCD: (Order is same as UEFI spec= )
\n" - = " EfiReservedMemoryType 0x0000000000000001\n" - = " EfiLoaderCode 0x0000000000000002\n" - = " EfiLoaderData 0x0000000000000004\n" - = " EfiBootServicesCode 0x0000000000000008\n" - = " EfiBootServicesData 0x0000000000000010\n" - = " EfiRuntimeServicesCode 0x0000000000000020\n" - = " EfiRuntimeServicesData 0x0000000000000040\n" - = " EfiConventionalMemory 0x0000000000000080\n" - = " EfiUnusableMemory 0x0000000000000100\n" - = " EfiACPIReclaimMemory 0x0000000000000200\n" - = " EfiACPIMemoryNVS 0x0000000000000400\n" - = " EfiMemoryMappedIO 0x0000000000000800\n" - = " EfiMemoryMappedIOPortSpace 0x0000000000001000\n" - = " EfiPalCode 0x0000000000002000\n" - = " EfiPersistentMemory 0x0000000000004000\n" - = " OEM Reserved 0x4000000000000000\n" - = " OS Reserved 0x8000000000000000\n" - = " e.g. LoaderCode+LoaderData+BootServicesCode+BootServicesDat= a are needed, 0x1E should be used.
" - - -#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPropertyMask_PROMPT= #language en-US "The Heap Guard feature mask" - -#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPropertyMask_HELP = #language en-US "This mask is to control Heap Guard behavior.\n" - = " BIT0 - Enable UEFI page guard.
\n" - = " BIT1 - Enable UEFI pool guard.
\n" - = " BIT2 - Enable SMM page guard.
\n" - = " BIT3 - Enable SMM pool guard.
\n" - = " BIT7 - The direction of Guard Page for Pool Guard.\n" - = " 0 - The returned pool is adjacent to the botto= m guard page.
\n" - = " 1 - The returned pool is adjacent to the top g= uard page.
" - +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPageType_PROMPT #l= anguage en-US "The memory type mask for Page Guard" + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPageType_HELP #l= anguage en-US "Indicates which type allocation need guard page.\n" + = " Below is bit mask for this PCD: (Order is same as UEFI spec= )
\n" + = " EfiReservedMemoryType 0x0000000000000001\n" + = " EfiLoaderCode 0x0000000000000002\n" + = " EfiLoaderData 0x0000000000000004\n" + = " EfiBootServicesCode 0x0000000000000008\n" + = " EfiBootServicesData 0x0000000000000010\n" + = " EfiRuntimeServicesCode 0x0000000000000020\n" + = " EfiRuntimeServicesData 0x0000000000000040\n" + = " EfiConventionalMemory 0x0000000000000080\n" + = " EfiUnusableMemory 0x0000000000000100\n" + = " EfiACPIReclaimMemory 0x0000000000000200\n" + = " EfiACPIMemoryNVS 0x0000000000000400\n" + = " EfiMemoryMappedIO 0x0000000000000800\n" + = " EfiMemoryMappedIOPortSpace 0x0000000000001000\n" + = " EfiPalCode 0x0000000000002000\n" + = " EfiPersistentMemory 0x0000000000004000\n" + = " OEM Reserved 0x4000000000000000\n" + = " OS Reserved 0x8000000000000000\n" + = " e.g. LoaderCode+LoaderData+BootServicesCode+BootServicesDat= a are needed, 0x1E should be used.
" + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPoolType_PROMPT #l= anguage en-US "The memory type mask for Pool Guard" + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPoolType_HELP #l= anguage en-US "Indicates which type allocation need guard page.\n" + = " Below is bit mask for this PCD: (Order is same as UEFI spec= )
\n" + = " EfiReservedMemoryType 0x0000000000000001\n" + = " EfiLoaderCode 0x0000000000000002\n" + = " EfiLoaderData 0x0000000000000004\n" + = " EfiBootServicesCode 0x0000000000000008\n" + = " EfiBootServicesData 0x0000000000000010\n" + = " EfiRuntimeServicesCode 0x0000000000000020\n" + = " EfiRuntimeServicesData 0x0000000000000040\n" + = " EfiConventionalMemory 0x0000000000000080\n" + = " EfiUnusableMemory 0x0000000000000100\n" + = " EfiACPIReclaimMemory 0x0000000000000200\n" + = " EfiACPIMemoryNVS 0x0000000000000400\n" + = " EfiMemoryMappedIO 0x0000000000000800\n" + = " EfiMemoryMappedIOPortSpace 0x0000000000001000\n" + = " EfiPalCode 0x0000000000002000\n" + = " EfiPersistentMemory 0x0000000000004000\n" + = " OEM Reserved 0x4000000000000000\n" + = " OS Reserved 0x8000000000000000\n" + = " e.g. LoaderCode+LoaderData+BootServicesCode+BootServicesDat= a are needed, 0x1E should be used.
" + + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPropertyMask_PROMPT= #language en-US "The Heap Guard feature mask" + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdHeapGuardPropertyMask_HELP = #language en-US "This mask is to control Heap Guard behavior.\n" + = " BIT0 - Enable UEFI page guard.
\n" + = " BIT1 - Enable UEFI pool guard.
\n" + = " BIT2 - Enable SMM page guard.
\n" + = " BIT3 - Enable SMM pool guard.
\n" + = " BIT7 - The direction of Guard Page for Pool Guard.\n" + = " 0 - The returned pool is adjacent to the botto= m guard page.
\n" + = " 1 - The returned pool is adjacent to the top g= uard page.
" + diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.c b/UefiCpuPkg/CpuDxe/CpuPageTa= ble.c index 309f448a83..76f44f9bd1 100644 --- a/UefiCpuPkg/CpuDxe/CpuPageTable.c +++ b/UefiCpuPkg/CpuDxe/CpuPageTable.c @@ -442,8 +442,8 @@ ConvertPageEntryAttribute ( *PageEntry =3D NewPageEntry; if (CurrentPageEntry !=3D NewPageEntry) { *IsModified =3D TRUE; - DEBUG ((DEBUG_VERBOSE, "ConvertPageEntryAttribute 0x%lx", CurrentPageE= ntry)); - DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry)); + DEBUG ((DEBUG_VERBOSE, "ConvertPageEntryAttribute 0x%lx", CurrentPageE= ntry)); + DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry)); } else { *IsModified =3D FALSE; } diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpu= DxeSmm/Ia32/PageTbl.c index 9447a31ef5..0396f2daaa 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c @@ -196,16 +196,16 @@ SetPageTableAttributes ( BOOLEAN IsSplitted; BOOLEAN PageTableSplitted; =20 - // - // Don't mark page table as read-only if heap guard is enabled. - // - // BIT2: SMM page guard enabled - // BIT3: SMM pool guard enabled - // - if ((PcdGet8 (PcdHeapGuardPropertyMask) & (BIT3 | BIT2)) !=3D 0) { - return ; - } - + // + // Don't mark page table as read-only if heap guard is enabled. + // + // BIT2: SMM page guard enabled + // BIT3: SMM pool guard enabled + // + if ((PcdGet8 (PcdHeapGuardPropertyMask) & (BIT3 | BIT2)) !=3D 0) { + return ; + } + DEBUG ((DEBUG_INFO, "SetPageTableAttributes\n")); =20 // diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmC= puDxeSmm/PiSmmCpuDxeSmm.c index 6c6d742c95..4b66a0dfd9 100755 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c @@ -76,15 +76,15 @@ EFI_SMM_CPU_PROTOCOL mSmmCpu =3D { SmmWriteSaveState }; =20 -/// -/// SMM Memory Attribute Protocol instance -/// -EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL mSmmMemoryAttribute =3D { - EdkiiSmmGetMemoryAttributes, - EdkiiSmmSetMemoryAttributes, - EdkiiSmmClearMemoryAttributes -}; - +/// +/// SMM Memory Attribute Protocol instance +/// +EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL mSmmMemoryAttribute =3D { + EdkiiSmmGetMemoryAttributes, + EdkiiSmmSetMemoryAttributes, + EdkiiSmmClearMemoryAttributes +}; + EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[EXCEPTION_VECTOR_NUMBER]; =20 // @@ -902,17 +902,17 @@ PiCpuSmmEntry ( ); ASSERT_EFI_ERROR (Status); =20 - // - // Install the SMM Memory Attribute Protocol into SMM protocol database - // - Status =3D gSmst->SmmInstallProtocolInterface ( - &mSmmCpuHandle, - &gEdkiiSmmMemoryAttributeProtocolGuid, - EFI_NATIVE_INTERFACE, - &mSmmMemoryAttribute - ); - ASSERT_EFI_ERROR (Status); - + // + // Install the SMM Memory Attribute Protocol into SMM protocol database + // + Status =3D gSmst->SmmInstallProtocolInterface ( + &mSmmCpuHandle, + &gEdkiiSmmMemoryAttributeProtocolGuid, + EFI_NATIVE_INTERFACE, + &mSmmMemoryAttribute + ); + ASSERT_EFI_ERROR (Status); + // // Expose address of CPU Hot Plug Data structure if CPU hot plug is supp= orted. // diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h b/UefiCpuPkg/PiSmmC= puDxeSmm/PiSmmCpuDxeSmm.h index a2d5f55045..ef32f17676 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h @@ -25,7 +25,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER= EXPRESS OR IMPLIED. #include #include #include -#include +#include =20 #include #include @@ -1069,101 +1069,101 @@ TransferApToSafeState ( IN UINTN NumberToFinishAddress ); =20 -/** - This function set given attributes of the memory region specified by - BaseAddress and Length. - - @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. - @param BaseAddress The physical address that is the start address= of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes The bit mask of attributes to set for the memo= ry - region. - - @retval EFI_SUCCESS The attributes were set for the memory reg= ion. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes specified an illegal combinatio= n of - attributes that cannot be set together. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specifi= ed - by BaseAddress and Length. - The bit mask of attributes is not support = for - the memory resource range specified by - BaseAddress and Length. - -**/ -EFI_STATUS -EFIAPI -EdkiiSmmSetMemoryAttributes ( - IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes - ); - -/** - This function clears given attributes of the memory region specified by - BaseAddress and Length. - - @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. - @param BaseAddress The physical address that is the start address= of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes The bit mask of attributes to set for the memo= ry - region. - - @retval EFI_SUCCESS The attributes were set for the memory reg= ion. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes specified an illegal combinatio= n of - attributes that cannot be set together. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specifi= ed - by BaseAddress and Length. - The bit mask of attributes is not support = for - the memory resource range specified by - BaseAddress and Length. - -**/ -EFI_STATUS -EFIAPI -EdkiiSmmClearMemoryAttributes ( - IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes - ); - -/** - This function retrieve the attributes of the memory region specified by - BaseAddress and Length. If different attributes are got from different p= art - of the memory region, EFI_NO_MAPPING will be returned. - - @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. - @param BaseAddress The physical address that is the start address= of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes Pointer to attributes returned. - - @retval EFI_SUCCESS The attributes got for the memory region. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes is NULL. - @retval EFI_NO_MAPPING Attributes are not consistent cross the me= mory - region. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specifi= ed - by BaseAddress and Length. - The bit mask of attributes is not support = for - the memory resource range specified by - BaseAddress and Length. - -**/ -EFI_STATUS -EFIAPI -EdkiiSmmGetMemoryAttributes ( - IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 *Attributes - ); - +/** + This function set given attributes of the memory region specified by + BaseAddress and Length. + + @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. + @param BaseAddress The physical address that is the start address= of + a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memo= ry + region. + + @retval EFI_SUCCESS The attributes were set for the memory reg= ion. + @retval EFI_INVALID_PARAMETER Length is zero. + Attributes specified an illegal combinatio= n of + attributes that cannot be set together. + @retval EFI_UNSUPPORTED The processor does not support one or more + bytes of the memory resource range specifi= ed + by BaseAddress and Length. + The bit mask of attributes is not support = for + the memory resource range specified by + BaseAddress and Length. + +**/ +EFI_STATUS +EFIAPI +EdkiiSmmSetMemoryAttributes ( + IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + +/** + This function clears given attributes of the memory region specified by + BaseAddress and Length. + + @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. + @param BaseAddress The physical address that is the start address= of + a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memo= ry + region. + + @retval EFI_SUCCESS The attributes were set for the memory reg= ion. + @retval EFI_INVALID_PARAMETER Length is zero. + Attributes specified an illegal combinatio= n of + attributes that cannot be set together. + @retval EFI_UNSUPPORTED The processor does not support one or more + bytes of the memory resource range specifi= ed + by BaseAddress and Length. + The bit mask of attributes is not support = for + the memory resource range specified by + BaseAddress and Length. + +**/ +EFI_STATUS +EFIAPI +EdkiiSmmClearMemoryAttributes ( + IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + +/** + This function retrieve the attributes of the memory region specified by + BaseAddress and Length. If different attributes are got from different p= art + of the memory region, EFI_NO_MAPPING will be returned. + + @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. + @param BaseAddress The physical address that is the start address= of + a memory region. + @param Length The size in bytes of the memory region. + @param Attributes Pointer to attributes returned. + + @retval EFI_SUCCESS The attributes got for the memory region. + @retval EFI_INVALID_PARAMETER Length is zero. + Attributes is NULL. + @retval EFI_NO_MAPPING Attributes are not consistent cross the me= mory + region. + @retval EFI_UNSUPPORTED The processor does not support one or more + bytes of the memory resource range specifi= ed + by BaseAddress and Length. + The bit mask of attributes is not support = for + the memory resource range specified by + BaseAddress and Length. + +**/ +EFI_STATUS +EFIAPI +EdkiiSmmGetMemoryAttributes ( + IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 *Attributes + ); + #endif diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSm= mCpuDxeSmm/PiSmmCpuDxeSmm.inf index 9edd162feb..e37ac5f84e 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf @@ -129,7 +129,7 @@ gEfiSmmCpuProtocolGuid ## PRODUCES gEfiSmmReadyToLockProtocolGuid ## NOTIFY gEfiSmmCpuServiceProtocolGuid ## PRODUCES - gEdkiiSmmMemoryAttributeProtocolGuid ## PRODUCES + gEdkiiSmmMemoryAttributeProtocolGuid ## PRODUCES =20 [Guids] gEfiAcpiVariableGuid ## SOMETIMES_CONSUMES ## HOB # = it is used for S3 boot. @@ -161,7 +161,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable ## CONS= UMES gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ##= CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ##= CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ##= CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ##= CONSUMES =20 [Depex] gEfiMpServiceProtocolGuid diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/UefiCpuPk= g/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c index 55c04c7aa7..2d7dba59bf 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c @@ -1120,166 +1120,166 @@ IsSmmCommBufferForbiddenAddress ( } return FALSE; } - -/** - This function set given attributes of the memory region specified by - BaseAddress and Length. - - @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. - @param BaseAddress The physical address that is the start address= of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes The bit mask of attributes to set for the memo= ry - region. - - @retval EFI_SUCCESS The attributes were set for the memory reg= ion. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes specified an illegal combinatio= n of - attributes that cannot be set together. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specifi= ed - by BaseAddress and Length. - The bit mask of attributes is not support = for - the memory resource range specified by - BaseAddress and Length. - -**/ -EFI_STATUS -EFIAPI -EdkiiSmmSetMemoryAttributes ( - IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes - ) -{ - return SmmSetMemoryAttributes (BaseAddress, Length, Attributes); -} - -/** - This function clears given attributes of the memory region specified by - BaseAddress and Length. - - @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. - @param BaseAddress The physical address that is the start address= of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes The bit mask of attributes to set for the memo= ry - region. - - @retval EFI_SUCCESS The attributes were set for the memory reg= ion. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes specified an illegal combinatio= n of - attributes that cannot be set together. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specifi= ed - by BaseAddress and Length. - The bit mask of attributes is not support = for - the memory resource range specified by - BaseAddress and Length. - -**/ -EFI_STATUS -EFIAPI -EdkiiSmmClearMemoryAttributes ( - IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes - ) -{ - return SmmClearMemoryAttributes (BaseAddress, Length, Attributes); -} - -/** - This function retrieve the attributes of the memory region specified by - BaseAddress and Length. If different attributes are got from different p= art - of the memory region, EFI_NO_MAPPING will be returned. - - @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. - @param BaseAddress The physical address that is the start address= of - a memory region. - @param Length The size in bytes of the memory region. - @param Attributes Pointer to attributes returned. - - @retval EFI_SUCCESS The attributes got for the memory region. - @retval EFI_INVALID_PARAMETER Length is zero. - Attributes is NULL. - @retval EFI_NO_MAPPING Attributes are not consistent cross the me= mory - region. - @retval EFI_UNSUPPORTED The processor does not support one or more - bytes of the memory resource range specifi= ed - by BaseAddress and Length. - The bit mask of attributes is not support = for - the memory resource range specified by - BaseAddress and Length. - -**/ -EFI_STATUS -EFIAPI -EdkiiSmmGetMemoryAttributes ( - IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - OUT UINT64 *Attributes - ) -{ - EFI_PHYSICAL_ADDRESS Address; - UINT64 *PageEntry; - UINT64 MemAttr; - PAGE_ATTRIBUTE PageAttr; - INT64 Size; - - if (Length < SIZE_4KB || Attributes =3D=3D NULL) { - return EFI_INVALID_PARAMETER; - } - - Size =3D (INT64)Length; - MemAttr =3D (UINT64)-1; - - do { - - PageEntry =3D GetPageTableEntry (BaseAddress, &PageAttr); - if (PageEntry =3D=3D NULL || PageAttr =3D=3D PageNone) { - return EFI_UNSUPPORTED; - } - - // - // If the memory range is cross page table boundary, make sure they - // share the same attribute. Return EFI_NO_MAPPING if not. - // - *Attributes =3D GetAttributesFromPageEntry (PageEntry); - if (MemAttr !=3D (UINT64)-1 && *Attributes !=3D MemAttr) { - return EFI_NO_MAPPING; - } - - switch (PageAttr) { - case Page4K: - Address =3D *PageEntry & ~mAddressEncMask & PAGING_4K_ADDRESS_MA= SK_64; - Size -=3D (SIZE_4KB - (BaseAddress - Address)); - BaseAddress +=3D (SIZE_4KB - (BaseAddress - Address)); - break; - - case Page2M: - Address =3D *PageEntry & ~mAddressEncMask & PAGING_2M_ADDRESS_MA= SK_64; - Size -=3D SIZE_2MB - (BaseAddress - Address); - BaseAddress +=3D SIZE_2MB - (BaseAddress - Address); - break; - - case Page1G: - Address =3D *PageEntry & ~mAddressEncMask & PAGING_1G_ADDRESS_MA= SK_64; - Size -=3D SIZE_1GB - (BaseAddress - Address); - BaseAddress +=3D SIZE_1GB - (BaseAddress - Address); - break; - - default: - return EFI_UNSUPPORTED; - } - - MemAttr =3D *Attributes; - - } while (Size > 0); - - return EFI_SUCCESS; -} - + +/** + This function set given attributes of the memory region specified by + BaseAddress and Length. + + @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. + @param BaseAddress The physical address that is the start address= of + a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memo= ry + region. + + @retval EFI_SUCCESS The attributes were set for the memory reg= ion. + @retval EFI_INVALID_PARAMETER Length is zero. + Attributes specified an illegal combinatio= n of + attributes that cannot be set together. + @retval EFI_UNSUPPORTED The processor does not support one or more + bytes of the memory resource range specifi= ed + by BaseAddress and Length. + The bit mask of attributes is not support = for + the memory resource range specified by + BaseAddress and Length. + +**/ +EFI_STATUS +EFIAPI +EdkiiSmmSetMemoryAttributes ( + IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +{ + return SmmSetMemoryAttributes (BaseAddress, Length, Attributes); +} + +/** + This function clears given attributes of the memory region specified by + BaseAddress and Length. + + @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. + @param BaseAddress The physical address that is the start address= of + a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memo= ry + region. + + @retval EFI_SUCCESS The attributes were set for the memory reg= ion. + @retval EFI_INVALID_PARAMETER Length is zero. + Attributes specified an illegal combinatio= n of + attributes that cannot be set together. + @retval EFI_UNSUPPORTED The processor does not support one or more + bytes of the memory resource range specifi= ed + by BaseAddress and Length. + The bit mask of attributes is not support = for + the memory resource range specified by + BaseAddress and Length. + +**/ +EFI_STATUS +EFIAPI +EdkiiSmmClearMemoryAttributes ( + IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +{ + return SmmClearMemoryAttributes (BaseAddress, Length, Attributes); +} + +/** + This function retrieve the attributes of the memory region specified by + BaseAddress and Length. If different attributes are got from different p= art + of the memory region, EFI_NO_MAPPING will be returned. + + @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instan= ce. + @param BaseAddress The physical address that is the start address= of + a memory region. + @param Length The size in bytes of the memory region. + @param Attributes Pointer to attributes returned. + + @retval EFI_SUCCESS The attributes got for the memory region. + @retval EFI_INVALID_PARAMETER Length is zero. + Attributes is NULL. + @retval EFI_NO_MAPPING Attributes are not consistent cross the me= mory + region. + @retval EFI_UNSUPPORTED The processor does not support one or more + bytes of the memory resource range specifi= ed + by BaseAddress and Length. + The bit mask of attributes is not support = for + the memory resource range specified by + BaseAddress and Length. + +**/ +EFI_STATUS +EFIAPI +EdkiiSmmGetMemoryAttributes ( + IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + OUT UINT64 *Attributes + ) +{ + EFI_PHYSICAL_ADDRESS Address; + UINT64 *PageEntry; + UINT64 MemAttr; + PAGE_ATTRIBUTE PageAttr; + INT64 Size; + + if (Length < SIZE_4KB || Attributes =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Size =3D (INT64)Length; + MemAttr =3D (UINT64)-1; + + do { + + PageEntry =3D GetPageTableEntry (BaseAddress, &PageAttr); + if (PageEntry =3D=3D NULL || PageAttr =3D=3D PageNone) { + return EFI_UNSUPPORTED; + } + + // + // If the memory range is cross page table boundary, make sure they + // share the same attribute. Return EFI_NO_MAPPING if not. + // + *Attributes =3D GetAttributesFromPageEntry (PageEntry); + if (MemAttr !=3D (UINT64)-1 && *Attributes !=3D MemAttr) { + return EFI_NO_MAPPING; + } + + switch (PageAttr) { + case Page4K: + Address =3D *PageEntry & ~mAddressEncMask & PAGING_4K_ADDRESS_MA= SK_64; + Size -=3D (SIZE_4KB - (BaseAddress - Address)); + BaseAddress +=3D (SIZE_4KB - (BaseAddress - Address)); + break; + + case Page2M: + Address =3D *PageEntry & ~mAddressEncMask & PAGING_2M_ADDRESS_MA= SK_64; + Size -=3D SIZE_2MB - (BaseAddress - Address); + BaseAddress +=3D SIZE_2MB - (BaseAddress - Address); + break; + + case Page1G: + Address =3D *PageEntry & ~mAddressEncMask & PAGING_1G_ADDRESS_MA= SK_64; + Size -=3D SIZE_1GB - (BaseAddress - Address); + BaseAddress +=3D SIZE_1GB - (BaseAddress - Address); + break; + + default: + return EFI_UNSUPPORTED; + } + + MemAttr =3D *Attributes; + + } while (Size > 0); + + return EFI_SUCCESS; +} + diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c b/UefiCpuPkg/PiSmmCpuD= xeSmm/X64/PageTbl.c index 1da4b5506c..79a26d7ec6 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c @@ -914,20 +914,20 @@ SetPageTableAttributes ( BOOLEAN IsSplitted; BOOLEAN PageTableSplitted; =20 - // - // Don't do this if - // - no static page table; or - // - SMM heap guard feature enabled - // BIT2: SMM page guard enabled - // BIT3: SMM pool guard enabled - // - if (!mCpuSmmStaticPageTable || - (PcdGet8 (PcdHeapGuardPropertyMask) & (BIT3 | BIT2)) !=3D 0) { - // - // Static paging and heap guard should not be enabled at the same time. - // - ASSERT (!(mCpuSmmStaticPageTable && - (PcdGet8 (PcdHeapGuardPropertyMask) & (BIT3 | BIT2)) !=3D 0)= ); + // + // Don't do this if + // - no static page table; or + // - SMM heap guard feature enabled + // BIT2: SMM page guard enabled + // BIT3: SMM pool guard enabled + // + if (!mCpuSmmStaticPageTable || + (PcdGet8 (PcdHeapGuardPropertyMask) & (BIT3 | BIT2)) !=3D 0) { + // + // Static paging and heap guard should not be enabled at the same time. + // + ASSERT (!(mCpuSmmStaticPageTable && + (PcdGet8 (PcdHeapGuardPropertyMask) & (BIT3 | BIT2)) !=3D 0)= ); return ; } =20 --=20 2.14.1.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel