summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Core/Dxe/Misc
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2024-06-04 06:43:08 +0300
committerkx <kx@radix.pro>2024-06-04 06:43:08 +0300
commit7e2ccccace24636f29ddc210b94606abd4c7e42b (patch)
tree545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Core/Dxe/Misc
parent27b044605cd5f6b33a3d231576003850b3fe305b (diff)
downloadedk2-trunk.tar.xz
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Core/Dxe/Misc')
-rw-r--r--MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c564
-rwxr-xr-xMdeModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c358
-rw-r--r--MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c1374
-rw-r--r--MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c2220
-rw-r--r--MdeModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c132
-rw-r--r--MdeModulePkg/Core/Dxe/Misc/Stall.c218
6 files changed, 2433 insertions, 2433 deletions
diff --git a/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c b/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
index eeb18f6e47..7b96806686 100644
--- a/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
+++ b/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
@@ -1,282 +1,282 @@
-/** @file
- Support functions for managing debug image info table when loading and unloading
- images.
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "DxeMain.h"
-
-EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugInfoTableHeader = {
- 0, // volatile UINT32 UpdateStatus;
- 0, // UINT32 TableSize;
- NULL // EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable;
-};
-
-UINTN mMaxTableEntries = 0;
-
-EFI_SYSTEM_TABLE_POINTER *mDebugTable = NULL;
-
-#define EFI_DEBUG_TABLE_ENTRY_SIZE (sizeof (VOID *))
-
-/**
- Creates and initializes the DebugImageInfo Table. Also creates the configuration
- table and registers it into the system table.
-
-**/
-VOID
-CoreInitializeDebugImageInfoTable (
- VOID
- )
-{
- EFI_STATUS Status;
- UINTN Pages;
- EFI_PHYSICAL_ADDRESS Memory;
- UINTN AlignedMemory;
- UINTN AlignmentMask;
- UINTN UnalignedPages;
- UINTN RealPages;
-
- //
- // Allocate 4M aligned page for the structure and fill in the data.
- // Ideally we would update the CRC now as well, but the service may not yet be available.
- // See comments in the CoreUpdateDebugTableCrc32() function below for details.
- //
- Pages = EFI_SIZE_TO_PAGES (sizeof (EFI_SYSTEM_TABLE_POINTER));
- AlignmentMask = SIZE_4MB - 1;
- RealPages = Pages + EFI_SIZE_TO_PAGES (SIZE_4MB);
-
- //
- // Attempt to allocate memory below PcdMaxEfiSystemTablePointerAddress
- // If PcdMaxEfiSystemTablePointerAddress is 0, then allocate memory below
- // MAX_ADDRESS
- //
- Memory = PcdGet64 (PcdMaxEfiSystemTablePointerAddress);
- if (Memory == 0) {
- Memory = MAX_ADDRESS;
- }
-
- Status = CoreAllocatePages (
- AllocateMaxAddress,
- EfiBootServicesData,
- RealPages,
- &Memory
- );
- if (EFI_ERROR (Status)) {
- if (PcdGet64 (PcdMaxEfiSystemTablePointerAddress) != 0) {
- DEBUG ((DEBUG_INFO, "Allocate memory for EFI_SYSTEM_TABLE_POINTER below PcdMaxEfiSystemTablePointerAddress failed. \
- Retry to allocate memroy as close to the top of memory as feasible.\n"));
- }
-
- //
- // If the initial memory allocation fails, then reattempt allocation
- // as close to the top of memory as feasible.
- //
- Status = CoreAllocatePages (
- AllocateAnyPages,
- EfiBootServicesData,
- RealPages,
- &Memory
- );
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR (Status)) {
- return;
- }
- }
-
- //
- // Free overallocated pages
- //
- AlignedMemory = ((UINTN)Memory + AlignmentMask) & ~AlignmentMask;
- UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN)Memory);
- if (UnalignedPages > 0) {
- //
- // Free first unaligned page(s).
- //
- Status = CoreFreePages (Memory, UnalignedPages);
- ASSERT_EFI_ERROR (Status);
- }
-
- Memory = AlignedMemory + EFI_PAGES_TO_SIZE (Pages);
- UnalignedPages = RealPages - Pages - UnalignedPages;
- if (UnalignedPages > 0) {
- //
- // Free last unaligned page(s).
- //
- Status = CoreFreePages (Memory, UnalignedPages);
- ASSERT_EFI_ERROR (Status);
- }
-
- //
- // Set mDebugTable to the 4MB aligned allocated pages
- //
- mDebugTable = (EFI_SYSTEM_TABLE_POINTER *)(AlignedMemory);
- ASSERT (mDebugTable != NULL);
-
- //
- // Initialize EFI_SYSTEM_TABLE_POINTER structure
- //
- mDebugTable->Signature = EFI_SYSTEM_TABLE_SIGNATURE;
- mDebugTable->EfiSystemTableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)gDxeCoreST;
- mDebugTable->Crc32 = 0;
-
- //
- // Install the EFI_SYSTEM_TABLE_POINTER structure in the EFI System
- // Configuration Table
- //
- Status = CoreInstallConfigurationTable (&gEfiDebugImageInfoTableGuid, &mDebugInfoTableHeader);
- ASSERT_EFI_ERROR (Status);
-}
-
-/**
- Update the CRC32 in the Debug Table.
- Since the CRC32 service is made available by the Runtime driver, we have to
- wait for the Runtime Driver to be installed before the CRC32 can be computed.
- This function is called elsewhere by the core when the runtime architectural
- protocol is produced.
-
-**/
-VOID
-CoreUpdateDebugTableCrc32 (
- VOID
- )
-{
- ASSERT (mDebugTable != NULL);
- mDebugTable->Crc32 = 0;
- gBS->CalculateCrc32 ((VOID *)mDebugTable, sizeof (EFI_SYSTEM_TABLE_POINTER), &mDebugTable->Crc32);
-}
-
-/**
- Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates
- the table if it's not large enough to accomidate another entry.
-
- @param ImageInfoType type of debug image information
- @param LoadedImage pointer to the loaded image protocol for the image being
- loaded
- @param ImageHandle image handle for the image being loaded
-
-**/
-VOID
-CoreNewDebugImageInfoEntry (
- IN UINT32 ImageInfoType,
- IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
- IN EFI_HANDLE ImageHandle
- )
-{
- EFI_DEBUG_IMAGE_INFO *Table;
- EFI_DEBUG_IMAGE_INFO *NewTable;
- UINTN Index;
- UINTN TableSize;
-
- //
- // Set the flag indicating that we're in the process of updating the table.
- //
- mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
-
- Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
-
- if (mDebugInfoTableHeader.TableSize < mMaxTableEntries) {
- //
- // We still have empty entires in the Table, find the first empty entry.
- //
- Index = 0;
- while (Table[Index].NormalImage != NULL) {
- Index++;
- }
-
- //
- // There must be an empty entry in the in the table.
- //
- ASSERT (Index < mMaxTableEntries);
- } else {
- //
- // Table is full, so re-allocate another page for a larger table...
- //
- TableSize = mMaxTableEntries * EFI_DEBUG_TABLE_ENTRY_SIZE;
- NewTable = AllocateZeroPool (TableSize + EFI_PAGE_SIZE);
- if (NewTable == NULL) {
- mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
- return;
- }
-
- //
- // Copy the old table into the new one
- //
- CopyMem (NewTable, Table, TableSize);
- //
- // Free the old table
- //
- CoreFreePool (Table);
- //
- // Update the table header
- //
- Table = NewTable;
- mDebugInfoTableHeader.EfiDebugImageInfoTable = NewTable;
- //
- // Enlarge the max table entries and set the first empty entry index to
- // be the original max table entries.
- //
- Index = mMaxTableEntries;
- mMaxTableEntries += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE;
- }
-
- //
- // Allocate data for new entry
- //
- Table[Index].NormalImage = AllocateZeroPool (sizeof (EFI_DEBUG_IMAGE_INFO_NORMAL));
- if (Table[Index].NormalImage != NULL) {
- //
- // Update the entry
- //
- Table[Index].NormalImage->ImageInfoType = (UINT32)ImageInfoType;
- Table[Index].NormalImage->LoadedImageProtocolInstance = LoadedImage;
- Table[Index].NormalImage->ImageHandle = ImageHandle;
- //
- // Increase the number of EFI_DEBUG_IMAGE_INFO elements and set the mDebugInfoTable in modified status.
- //
- mDebugInfoTableHeader.TableSize++;
- mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
- }
-
- mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
-}
-
-/**
- Removes and frees an entry from the DebugImageInfo Table.
-
- @param ImageHandle image handle for the image being unloaded
-
-**/
-VOID
-CoreRemoveDebugImageInfoEntry (
- EFI_HANDLE ImageHandle
- )
-{
- EFI_DEBUG_IMAGE_INFO *Table;
- UINTN Index;
-
- mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
-
- Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
-
- for (Index = 0; Index < mMaxTableEntries; Index++) {
- if ((Table[Index].NormalImage != NULL) && (Table[Index].NormalImage->ImageHandle == ImageHandle)) {
- //
- // Found a match. Free up the record, then NULL the pointer to indicate the slot
- // is free.
- //
- CoreFreePool (Table[Index].NormalImage);
- Table[Index].NormalImage = NULL;
- //
- // Decrease the number of EFI_DEBUG_IMAGE_INFO elements and set the mDebugInfoTable in modified status.
- //
- mDebugInfoTableHeader.TableSize--;
- mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
- break;
- }
- }
-
- mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
-}
+/** @file
+ Support functions for managing debug image info table when loading and unloading
+ images.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "DxeMain.h"
+
+EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugInfoTableHeader = {
+ 0, // volatile UINT32 UpdateStatus;
+ 0, // UINT32 TableSize;
+ NULL // EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable;
+};
+
+UINTN mMaxTableEntries = 0;
+
+EFI_SYSTEM_TABLE_POINTER *mDebugTable = NULL;
+
+#define EFI_DEBUG_TABLE_ENTRY_SIZE (sizeof (VOID *))
+
+/**
+ Creates and initializes the DebugImageInfo Table. Also creates the configuration
+ table and registers it into the system table.
+
+**/
+VOID
+CoreInitializeDebugImageInfoTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Memory;
+ UINTN AlignedMemory;
+ UINTN AlignmentMask;
+ UINTN UnalignedPages;
+ UINTN RealPages;
+
+ //
+ // Allocate 4M aligned page for the structure and fill in the data.
+ // Ideally we would update the CRC now as well, but the service may not yet be available.
+ // See comments in the CoreUpdateDebugTableCrc32() function below for details.
+ //
+ Pages = EFI_SIZE_TO_PAGES (sizeof (EFI_SYSTEM_TABLE_POINTER));
+ AlignmentMask = SIZE_4MB - 1;
+ RealPages = Pages + EFI_SIZE_TO_PAGES (SIZE_4MB);
+
+ //
+ // Attempt to allocate memory below PcdMaxEfiSystemTablePointerAddress
+ // If PcdMaxEfiSystemTablePointerAddress is 0, then allocate memory below
+ // MAX_ADDRESS
+ //
+ Memory = PcdGet64 (PcdMaxEfiSystemTablePointerAddress);
+ if (Memory == 0) {
+ Memory = MAX_ADDRESS;
+ }
+
+ Status = CoreAllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ RealPages,
+ &Memory
+ );
+ if (EFI_ERROR (Status)) {
+ if (PcdGet64 (PcdMaxEfiSystemTablePointerAddress) != 0) {
+ DEBUG ((DEBUG_INFO, "Allocate memory for EFI_SYSTEM_TABLE_POINTER below PcdMaxEfiSystemTablePointerAddress failed. \
+ Retry to allocate memroy as close to the top of memory as feasible.\n"));
+ }
+
+ //
+ // If the initial memory allocation fails, then reattempt allocation
+ // as close to the top of memory as feasible.
+ //
+ Status = CoreAllocatePages (
+ AllocateAnyPages,
+ EfiBootServicesData,
+ RealPages,
+ &Memory
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ }
+
+ //
+ // Free overallocated pages
+ //
+ AlignedMemory = ((UINTN)Memory + AlignmentMask) & ~AlignmentMask;
+ UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN)Memory);
+ if (UnalignedPages > 0) {
+ //
+ // Free first unaligned page(s).
+ //
+ Status = CoreFreePages (Memory, UnalignedPages);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Memory = AlignedMemory + EFI_PAGES_TO_SIZE (Pages);
+ UnalignedPages = RealPages - Pages - UnalignedPages;
+ if (UnalignedPages > 0) {
+ //
+ // Free last unaligned page(s).
+ //
+ Status = CoreFreePages (Memory, UnalignedPages);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Set mDebugTable to the 4MB aligned allocated pages
+ //
+ mDebugTable = (EFI_SYSTEM_TABLE_POINTER *)(AlignedMemory);
+ ASSERT (mDebugTable != NULL);
+
+ //
+ // Initialize EFI_SYSTEM_TABLE_POINTER structure
+ //
+ mDebugTable->Signature = EFI_SYSTEM_TABLE_SIGNATURE;
+ mDebugTable->EfiSystemTableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)gDxeCoreST;
+ mDebugTable->Crc32 = 0;
+
+ //
+ // Install the EFI_SYSTEM_TABLE_POINTER structure in the EFI System
+ // Configuration Table
+ //
+ Status = CoreInstallConfigurationTable (&gEfiDebugImageInfoTableGuid, &mDebugInfoTableHeader);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Update the CRC32 in the Debug Table.
+ Since the CRC32 service is made available by the Runtime driver, we have to
+ wait for the Runtime Driver to be installed before the CRC32 can be computed.
+ This function is called elsewhere by the core when the runtime architectural
+ protocol is produced.
+
+**/
+VOID
+CoreUpdateDebugTableCrc32 (
+ VOID
+ )
+{
+ ASSERT (mDebugTable != NULL);
+ mDebugTable->Crc32 = 0;
+ gBS->CalculateCrc32 ((VOID *)mDebugTable, sizeof (EFI_SYSTEM_TABLE_POINTER), &mDebugTable->Crc32);
+}
+
+/**
+ Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates
+ the table if it's not large enough to accomidate another entry.
+
+ @param ImageInfoType type of debug image information
+ @param LoadedImage pointer to the loaded image protocol for the image being
+ loaded
+ @param ImageHandle image handle for the image being loaded
+
+**/
+VOID
+CoreNewDebugImageInfoEntry (
+ IN UINT32 ImageInfoType,
+ IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_DEBUG_IMAGE_INFO *Table;
+ EFI_DEBUG_IMAGE_INFO *NewTable;
+ UINTN Index;
+ UINTN TableSize;
+
+ //
+ // Set the flag indicating that we're in the process of updating the table.
+ //
+ mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+
+ Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
+
+ if (mDebugInfoTableHeader.TableSize < mMaxTableEntries) {
+ //
+ // We still have empty entires in the Table, find the first empty entry.
+ //
+ Index = 0;
+ while (Table[Index].NormalImage != NULL) {
+ Index++;
+ }
+
+ //
+ // There must be an empty entry in the in the table.
+ //
+ ASSERT (Index < mMaxTableEntries);
+ } else {
+ //
+ // Table is full, so re-allocate another page for a larger table...
+ //
+ TableSize = mMaxTableEntries * EFI_DEBUG_TABLE_ENTRY_SIZE;
+ NewTable = AllocateZeroPool (TableSize + EFI_PAGE_SIZE);
+ if (NewTable == NULL) {
+ mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+ return;
+ }
+
+ //
+ // Copy the old table into the new one
+ //
+ CopyMem (NewTable, Table, TableSize);
+ //
+ // Free the old table
+ //
+ CoreFreePool (Table);
+ //
+ // Update the table header
+ //
+ Table = NewTable;
+ mDebugInfoTableHeader.EfiDebugImageInfoTable = NewTable;
+ //
+ // Enlarge the max table entries and set the first empty entry index to
+ // be the original max table entries.
+ //
+ Index = mMaxTableEntries;
+ mMaxTableEntries += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE;
+ }
+
+ //
+ // Allocate data for new entry
+ //
+ Table[Index].NormalImage = AllocateZeroPool (sizeof (EFI_DEBUG_IMAGE_INFO_NORMAL));
+ if (Table[Index].NormalImage != NULL) {
+ //
+ // Update the entry
+ //
+ Table[Index].NormalImage->ImageInfoType = (UINT32)ImageInfoType;
+ Table[Index].NormalImage->LoadedImageProtocolInstance = LoadedImage;
+ Table[Index].NormalImage->ImageHandle = ImageHandle;
+ //
+ // Increase the number of EFI_DEBUG_IMAGE_INFO elements and set the mDebugInfoTable in modified status.
+ //
+ mDebugInfoTableHeader.TableSize++;
+ mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
+ }
+
+ mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+}
+
+/**
+ Removes and frees an entry from the DebugImageInfo Table.
+
+ @param ImageHandle image handle for the image being unloaded
+
+**/
+VOID
+CoreRemoveDebugImageInfoEntry (
+ EFI_HANDLE ImageHandle
+ )
+{
+ EFI_DEBUG_IMAGE_INFO *Table;
+ UINTN Index;
+
+ mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+
+ Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
+
+ for (Index = 0; Index < mMaxTableEntries; Index++) {
+ if ((Table[Index].NormalImage != NULL) && (Table[Index].NormalImage->ImageHandle == ImageHandle)) {
+ //
+ // Found a match. Free up the record, then NULL the pointer to indicate the slot
+ // is free.
+ //
+ CoreFreePool (Table[Index].NormalImage);
+ Table[Index].NormalImage = NULL;
+ //
+ // Decrease the number of EFI_DEBUG_IMAGE_INFO elements and set the mDebugInfoTable in modified status.
+ //
+ mDebugInfoTableHeader.TableSize--;
+ mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
+ break;
+ }
+ }
+
+ mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
+}
diff --git a/MdeModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c b/MdeModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c
index f47f3bd804..70fb4dd337 100755
--- a/MdeModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c
+++ b/MdeModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c
@@ -1,179 +1,179 @@
-/** @file
- UEFI Miscellaneous boot Services InstallConfigurationTable service
-
-Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "DxeMain.h"
-
-#define CONFIG_TABLE_SIZE_INCREASED 0x10
-
-UINTN mSystemTableAllocateSize = 0;
-
-/**
- Boot Service called to add, modify, or remove a system configuration table from
- the EFI System Table.
-
- @param Guid Pointer to the GUID for the entry to add, update, or
- remove
- @param Table Pointer to the configuration table for the entry to add,
- update, or remove, may be NULL.
-
- @return EFI_SUCCESS Guid, Table pair added, updated, or removed.
- @return EFI_INVALID_PARAMETER Input GUID is NULL.
- @return EFI_NOT_FOUND Attempted to delete non-existant entry
- @return EFI_OUT_OF_RESOURCES Not enough memory available
-
-**/
-EFI_STATUS
-EFIAPI
-CoreInstallConfigurationTable (
- IN EFI_GUID *Guid,
- IN VOID *Table
- )
-{
- UINTN Index;
- EFI_CONFIGURATION_TABLE *EfiConfigurationTable;
- EFI_CONFIGURATION_TABLE *OldTable;
-
- //
- // If Guid is NULL, then this operation cannot be performed
- //
- if (Guid == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- EfiConfigurationTable = gDxeCoreST->ConfigurationTable;
-
- //
- // Search all the table for an entry that matches Guid
- //
- for (Index = 0; Index < gDxeCoreST->NumberOfTableEntries; Index++) {
- if (CompareGuid (Guid, &(gDxeCoreST->ConfigurationTable[Index].VendorGuid))) {
- break;
- }
- }
-
- if (Index < gDxeCoreST->NumberOfTableEntries) {
- //
- // A match was found, so this is either a modify or a delete operation
- //
- if (Table != NULL) {
- //
- // If Table is not NULL, then this is a modify operation.
- // Modify the table entry and return.
- //
- gDxeCoreST->ConfigurationTable[Index].VendorTable = Table;
-
- //
- // Signal Configuration Table change
- //
- CoreNotifySignalList (Guid);
-
- return EFI_SUCCESS;
- }
-
- //
- // A match was found and Table is NULL, so this is a delete operation.
- //
- gDxeCoreST->NumberOfTableEntries--;
-
- //
- // Copy over deleted entry
- //
- CopyMem (
- &(EfiConfigurationTable[Index]),
- &(gDxeCoreST->ConfigurationTable[Index + 1]),
- (gDxeCoreST->NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE)
- );
- } else {
- //
- // No matching GUIDs were found, so this is an add operation.
- //
-
- if (Table == NULL) {
- //
- // If Table is NULL on an add operation, then return an error.
- //
- return EFI_NOT_FOUND;
- }
-
- //
- // Assume that Index == gDxeCoreST->NumberOfTableEntries
- //
- if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSystemTableAllocateSize) {
- //
- // Allocate a table with one additional entry.
- //
- mSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE));
- EfiConfigurationTable = AllocateRuntimePool (mSystemTableAllocateSize);
- if (EfiConfigurationTable == NULL) {
- //
- // If a new table could not be allocated, then return an error.
- //
- return EFI_OUT_OF_RESOURCES;
- }
-
- if (gDxeCoreST->ConfigurationTable != NULL) {
- //
- // Copy the old table to the new table.
- //
- CopyMem (
- EfiConfigurationTable,
- gDxeCoreST->ConfigurationTable,
- Index * sizeof (EFI_CONFIGURATION_TABLE)
- );
-
- //
- // Record the old table pointer.
- //
- OldTable = gDxeCoreST->ConfigurationTable;
-
- //
- // As the CoreInstallConfigurationTable() may be re-entered by CoreFreePool()
- // in its calling stack, updating System table to the new table pointer must
- // be done before calling CoreFreePool() to free the old table.
- // It can make sure the gDxeCoreST->ConfigurationTable point to the new table
- // and avoid the errors of use-after-free to the old table by the reenter of
- // CoreInstallConfigurationTable() in CoreFreePool()'s calling stack.
- //
- gDxeCoreST->ConfigurationTable = EfiConfigurationTable;
-
- //
- // Free the old table after updating System Table to the new table pointer.
- //
- CoreFreePool (OldTable);
- } else {
- //
- // Update System Table
- //
- gDxeCoreST->ConfigurationTable = EfiConfigurationTable;
- }
- }
-
- //
- // Fill in the new entry
- //
- CopyGuid ((VOID *)&EfiConfigurationTable[Index].VendorGuid, Guid);
- EfiConfigurationTable[Index].VendorTable = Table;
-
- //
- // This is an add operation, so increment the number of table entries
- //
- gDxeCoreST->NumberOfTableEntries++;
- }
-
- //
- // Fix up the CRC-32 in the EFI System Table
- //
- CalculateEfiHdrCrc (&gDxeCoreST->Hdr);
-
- //
- // Signal Configuration Table change
- //
- CoreNotifySignalList (Guid);
-
- return EFI_SUCCESS;
-}
+/** @file
+ UEFI Miscellaneous boot Services InstallConfigurationTable service
+
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "DxeMain.h"
+
+#define CONFIG_TABLE_SIZE_INCREASED 0x10
+
+UINTN mSystemTableAllocateSize = 0;
+
+/**
+ Boot Service called to add, modify, or remove a system configuration table from
+ the EFI System Table.
+
+ @param Guid Pointer to the GUID for the entry to add, update, or
+ remove
+ @param Table Pointer to the configuration table for the entry to add,
+ update, or remove, may be NULL.
+
+ @return EFI_SUCCESS Guid, Table pair added, updated, or removed.
+ @return EFI_INVALID_PARAMETER Input GUID is NULL.
+ @return EFI_NOT_FOUND Attempted to delete non-existant entry
+ @return EFI_OUT_OF_RESOURCES Not enough memory available
+
+**/
+EFI_STATUS
+EFIAPI
+CoreInstallConfigurationTable (
+ IN EFI_GUID *Guid,
+ IN VOID *Table
+ )
+{
+ UINTN Index;
+ EFI_CONFIGURATION_TABLE *EfiConfigurationTable;
+ EFI_CONFIGURATION_TABLE *OldTable;
+
+ //
+ // If Guid is NULL, then this operation cannot be performed
+ //
+ if (Guid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EfiConfigurationTable = gDxeCoreST->ConfigurationTable;
+
+ //
+ // Search all the table for an entry that matches Guid
+ //
+ for (Index = 0; Index < gDxeCoreST->NumberOfTableEntries; Index++) {
+ if (CompareGuid (Guid, &(gDxeCoreST->ConfigurationTable[Index].VendorGuid))) {
+ break;
+ }
+ }
+
+ if (Index < gDxeCoreST->NumberOfTableEntries) {
+ //
+ // A match was found, so this is either a modify or a delete operation
+ //
+ if (Table != NULL) {
+ //
+ // If Table is not NULL, then this is a modify operation.
+ // Modify the table entry and return.
+ //
+ gDxeCoreST->ConfigurationTable[Index].VendorTable = Table;
+
+ //
+ // Signal Configuration Table change
+ //
+ CoreNotifySignalList (Guid);
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // A match was found and Table is NULL, so this is a delete operation.
+ //
+ gDxeCoreST->NumberOfTableEntries--;
+
+ //
+ // Copy over deleted entry
+ //
+ CopyMem (
+ &(EfiConfigurationTable[Index]),
+ &(gDxeCoreST->ConfigurationTable[Index + 1]),
+ (gDxeCoreST->NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE)
+ );
+ } else {
+ //
+ // No matching GUIDs were found, so this is an add operation.
+ //
+
+ if (Table == NULL) {
+ //
+ // If Table is NULL on an add operation, then return an error.
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Assume that Index == gDxeCoreST->NumberOfTableEntries
+ //
+ if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSystemTableAllocateSize) {
+ //
+ // Allocate a table with one additional entry.
+ //
+ mSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE));
+ EfiConfigurationTable = AllocateRuntimePool (mSystemTableAllocateSize);
+ if (EfiConfigurationTable == NULL) {
+ //
+ // If a new table could not be allocated, then return an error.
+ //
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (gDxeCoreST->ConfigurationTable != NULL) {
+ //
+ // Copy the old table to the new table.
+ //
+ CopyMem (
+ EfiConfigurationTable,
+ gDxeCoreST->ConfigurationTable,
+ Index * sizeof (EFI_CONFIGURATION_TABLE)
+ );
+
+ //
+ // Record the old table pointer.
+ //
+ OldTable = gDxeCoreST->ConfigurationTable;
+
+ //
+ // As the CoreInstallConfigurationTable() may be re-entered by CoreFreePool()
+ // in its calling stack, updating System table to the new table pointer must
+ // be done before calling CoreFreePool() to free the old table.
+ // It can make sure the gDxeCoreST->ConfigurationTable point to the new table
+ // and avoid the errors of use-after-free to the old table by the reenter of
+ // CoreInstallConfigurationTable() in CoreFreePool()'s calling stack.
+ //
+ gDxeCoreST->ConfigurationTable = EfiConfigurationTable;
+
+ //
+ // Free the old table after updating System Table to the new table pointer.
+ //
+ CoreFreePool (OldTable);
+ } else {
+ //
+ // Update System Table
+ //
+ gDxeCoreST->ConfigurationTable = EfiConfigurationTable;
+ }
+ }
+
+ //
+ // Fill in the new entry
+ //
+ CopyGuid ((VOID *)&EfiConfigurationTable[Index].VendorGuid, Guid);
+ EfiConfigurationTable[Index].VendorTable = Table;
+
+ //
+ // This is an add operation, so increment the number of table entries
+ //
+ gDxeCoreST->NumberOfTableEntries++;
+ }
+
+ //
+ // Fix up the CRC-32 in the EFI System Table
+ //
+ CalculateEfiHdrCrc (&gDxeCoreST->Hdr);
+
+ //
+ // Signal Configuration Table change
+ //
+ CoreNotifySignalList (Guid);
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
index e9343a2c4e..9abd79b9e4 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
@@ -1,687 +1,687 @@
-/** @file
- UEFI MemoryAttributesTable support
-
-Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PiDxe.h>
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/DxeServicesTableLib.h>
-#include <Library/DebugLib.h>
-#include <Library/UefiLib.h>
-#include <Library/ImagePropertiesRecordLib.h>
-
-#include <Guid/EventGroup.h>
-
-#include <Guid/MemoryAttributesTable.h>
-
-#include "DxeMain.h"
-#include "HeapGuard.h"
-
-/**
- This function for GetMemoryMap() with properties table capability.
-
- It calls original GetMemoryMap() to get the original memory map information. Then
- plus the additional memory map entries for PE Code/Data seperation.
-
- @param MemoryMapSize A pointer to the size, in bytes, of the
- MemoryMap buffer. On input, this is the size of
- the buffer allocated by the caller. On output,
- it is the size of the buffer returned by the
- firmware if the buffer was large enough, or the
- size of the buffer needed to contain the map if
- the buffer was too small.
- @param MemoryMap A pointer to the buffer in which firmware places
- the current memory map.
- @param MapKey A pointer to the location in which firmware
- returns the key for the current memory map.
- @param DescriptorSize A pointer to the location in which firmware
- returns the size, in bytes, of an individual
- EFI_MEMORY_DESCRIPTOR.
- @param DescriptorVersion A pointer to the location in which firmware
- returns the version number associated with the
- EFI_MEMORY_DESCRIPTOR.
-
- @retval EFI_SUCCESS The memory map was returned in the MemoryMap
- buffer.
- @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
- buffer size needed to hold the memory map is
- returned in MemoryMapSize.
- @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreGetMemoryMapWithSeparatedImageSection (
- IN OUT UINTN *MemoryMapSize,
- IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
- OUT UINTN *MapKey,
- OUT UINTN *DescriptorSize,
- OUT UINT32 *DescriptorVersion
- );
-
-#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
- ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
-
-#define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
-
-typedef struct {
- UINT32 Signature;
- UINTN ImageRecordCount;
- UINTN CodeSegmentCountMax;
- LIST_ENTRY ImageRecordList;
-} IMAGE_PROPERTIES_PRIVATE_DATA;
-
-STATIC IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData = {
- IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE,
- 0,
- 0,
- INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData.ImageRecordList)
-};
-
-STATIC EFI_LOCK mMemoryAttributesTableLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
-
-BOOLEAN mMemoryAttributesTableEnable = TRUE;
-BOOLEAN mMemoryAttributesTableEndOfDxe = FALSE;
-EFI_MEMORY_ATTRIBUTES_TABLE *mMemoryAttributesTable = NULL;
-BOOLEAN mMemoryAttributesTableReadyToBoot = FALSE;
-BOOLEAN gMemoryAttributesTableForwardCfi = TRUE;
-
-/**
- Install MemoryAttributesTable.
-
-**/
-VOID
-InstallMemoryAttributesTable (
- VOID
- )
-{
- UINTN MemoryMapSize;
- EFI_MEMORY_DESCRIPTOR *MemoryMap;
- EFI_MEMORY_DESCRIPTOR *MemoryMapStart;
- UINTN MapKey;
- UINTN DescriptorSize;
- UINT32 DescriptorVersion;
- UINTN Index;
- EFI_STATUS Status;
- UINT32 RuntimeEntryCount;
- EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;
- EFI_MEMORY_DESCRIPTOR *MemoryAttributesEntry;
-
- if (gMemoryMapTerminated) {
- //
- // Directly return after MemoryMap terminated.
- //
- return;
- }
-
- if (!mMemoryAttributesTableEnable) {
- DEBUG ((DEBUG_VERBOSE, "Cannot install Memory Attributes Table "));
- DEBUG ((DEBUG_VERBOSE, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));
- return;
- }
-
- if (mMemoryAttributesTable == NULL) {
- //
- // InstallConfigurationTable here to occupy one entry for MemoryAttributesTable
- // before GetMemoryMap below, as InstallConfigurationTable may allocate runtime
- // memory for the new entry.
- //
- Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID *)(UINTN)MAX_ADDRESS);
- ASSERT_EFI_ERROR (Status);
- }
-
- MemoryMapSize = 0;
- MemoryMap = NULL;
- Status = CoreGetMemoryMapWithSeparatedImageSection (
- &MemoryMapSize,
- MemoryMap,
- &MapKey,
- &DescriptorSize,
- &DescriptorVersion
- );
- ASSERT (Status == EFI_BUFFER_TOO_SMALL);
-
- do {
- MemoryMap = AllocatePool (MemoryMapSize);
- ASSERT (MemoryMap != NULL);
-
- Status = CoreGetMemoryMapWithSeparatedImageSection (
- &MemoryMapSize,
- MemoryMap,
- &MapKey,
- &DescriptorSize,
- &DescriptorVersion
- );
- if (EFI_ERROR (Status)) {
- FreePool (MemoryMap);
- }
- } while (Status == EFI_BUFFER_TOO_SMALL);
-
- MemoryMapStart = MemoryMap;
- RuntimeEntryCount = 0;
- for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {
- switch (MemoryMap->Type) {
- case EfiRuntimeServicesCode:
- case EfiRuntimeServicesData:
- RuntimeEntryCount++;
- break;
- }
-
- MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
- }
-
- //
- // Allocate MemoryAttributesTable
- //
- MemoryAttributesTable = AllocatePool (sizeof (EFI_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount);
- ASSERT (MemoryAttributesTable != NULL);
- MemoryAttributesTable->Version = EFI_MEMORY_ATTRIBUTES_TABLE_VERSION;
- MemoryAttributesTable->NumberOfEntries = RuntimeEntryCount;
- MemoryAttributesTable->DescriptorSize = (UINT32)DescriptorSize;
- if (gMemoryAttributesTableForwardCfi) {
- MemoryAttributesTable->Flags = EFI_MEMORY_ATTRIBUTES_FLAGS_RT_FORWARD_CONTROL_FLOW_GUARD;
- } else {
- MemoryAttributesTable->Flags = 0;
- }
-
- DEBUG ((DEBUG_VERBOSE, "MemoryAttributesTable:\n"));
- DEBUG ((DEBUG_VERBOSE, " Version - 0x%08x\n", MemoryAttributesTable->Version));
- DEBUG ((DEBUG_VERBOSE, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable->NumberOfEntries));
- DEBUG ((DEBUG_VERBOSE, " DescriptorSize - 0x%08x\n", MemoryAttributesTable->DescriptorSize));
- MemoryAttributesEntry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);
- MemoryMap = MemoryMapStart;
- for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {
- switch (MemoryMap->Type) {
- case EfiRuntimeServicesCode:
- case EfiRuntimeServicesData:
- CopyMem (MemoryAttributesEntry, MemoryMap, DescriptorSize);
- MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME);
- DEBUG ((DEBUG_VERBOSE, "Entry (0x%x)\n", MemoryAttributesEntry));
- DEBUG ((DEBUG_VERBOSE, " Type - 0x%x\n", MemoryAttributesEntry->Type));
- DEBUG ((DEBUG_VERBOSE, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry->PhysicalStart));
- DEBUG ((DEBUG_VERBOSE, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry->VirtualStart));
- DEBUG ((DEBUG_VERBOSE, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry->NumberOfPages));
- DEBUG ((DEBUG_VERBOSE, " Attribute - 0x%016lx\n", MemoryAttributesEntry->Attribute));
- MemoryAttributesEntry = NEXT_MEMORY_DESCRIPTOR (MemoryAttributesEntry, DescriptorSize);
- break;
- }
-
- MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
- }
-
- MemoryMap = MemoryMapStart;
- FreePool (MemoryMap);
-
- //
- // Update configuratoin table for MemoryAttributesTable.
- //
- Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, MemoryAttributesTable);
- ASSERT_EFI_ERROR (Status);
-
- if (mMemoryAttributesTable != NULL) {
- FreePool (mMemoryAttributesTable);
- }
-
- mMemoryAttributesTable = MemoryAttributesTable;
-}
-
-/**
- Install MemoryAttributesTable on memory allocation.
-
- @param[in] MemoryType EFI memory type.
-**/
-VOID
-InstallMemoryAttributesTableOnMemoryAllocation (
- IN EFI_MEMORY_TYPE MemoryType
- )
-{
- //
- // Install MemoryAttributesTable after ReadyToBoot on runtime memory allocation.
- //
- if (mMemoryAttributesTableReadyToBoot &&
- ((MemoryType == EfiRuntimeServicesCode) || (MemoryType == EfiRuntimeServicesData)))
- {
- InstallMemoryAttributesTable ();
- }
-}
-
-/**
- Install MemoryAttributesTable on ReadyToBoot.
-
- @param[in] Event The Event this notify function registered to.
- @param[in] Context Pointer to the context data registered to the Event.
-**/
-VOID
-EFIAPI
-InstallMemoryAttributesTableOnReadyToBoot (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- InstallMemoryAttributesTable ();
- mMemoryAttributesTableReadyToBoot = TRUE;
-}
-
-/**
- Install initial MemoryAttributesTable on EndOfDxe.
- Then SMM can consume this information.
-
- @param[in] Event The Event this notify function registered to.
- @param[in] Context Pointer to the context data registered to the Event.
-**/
-VOID
-EFIAPI
-InstallMemoryAttributesTableOnEndOfDxe (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- mMemoryAttributesTableEndOfDxe = TRUE;
- InstallMemoryAttributesTable ();
-
- DEBUG_CODE_BEGIN ();
- if ( mImagePropertiesPrivateData.ImageRecordCount > 0) {
- DEBUG ((DEBUG_INFO, "DXE - Total Runtime Image Count: 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
- DEBUG ((DEBUG_INFO, "DXE - Dump Runtime Image Records:\n"));
- DumpImageRecords (&mImagePropertiesPrivateData.ImageRecordList);
- }
-
- DEBUG_CODE_END ();
-}
-
-/**
- Initialize MemoryAttrubutesTable support.
-**/
-VOID
-EFIAPI
-CoreInitializeMemoryAttributesTable (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_EVENT ReadyToBootEvent;
- EFI_EVENT EndOfDxeEvent;
-
- //
- // Construct the table at ReadyToBoot.
- //
- Status = CoreCreateEventInternal (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- InstallMemoryAttributesTableOnReadyToBoot,
- NULL,
- &gEfiEventReadyToBootGuid,
- &ReadyToBootEvent
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Construct the initial table at EndOfDxe,
- // then SMM can consume this information.
- // Use TPL_NOTIFY here, as such SMM code (TPL_CALLBACK)
- // can run after it.
- //
- Status = CoreCreateEventInternal (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- InstallMemoryAttributesTableOnEndOfDxe,
- NULL,
- &gEfiEndOfDxeEventGroupGuid,
- &EndOfDxeEvent
- );
- ASSERT_EFI_ERROR (Status);
- return;
-}
-
-//
-// Below functions are for MemoryMap
-//
-
-/**
- Acquire memory lock on mMemoryAttributesTableLock.
-**/
-STATIC
-VOID
-CoreAcquiremMemoryAttributesTableLock (
- VOID
- )
-{
- CoreAcquireLock (&mMemoryAttributesTableLock);
-}
-
-/**
- Release memory lock on mMemoryAttributesTableLock.
-**/
-STATIC
-VOID
-CoreReleasemMemoryAttributesTableLock (
- VOID
- )
-{
- CoreReleaseLock (&mMemoryAttributesTableLock);
-}
-
-/**
- Merge continous memory map entries whose have same attributes.
-
- @param MemoryMap A pointer to the buffer in which firmware places
- the current memory map.
- @param MemoryMapSize A pointer to the size, in bytes, of the
- MemoryMap buffer. On input, this is the size of
- the current memory map. On output,
- it is the size of new memory map after merge.
- @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-**/
-VOID
-MergeMemoryMap (
- IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
- IN OUT UINTN *MemoryMapSize,
- IN UINTN DescriptorSize
- )
-{
- EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
- EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
- UINT64 MemoryBlockLength;
- EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry;
- EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
-
- MemoryMapEntry = MemoryMap;
- NewMemoryMapEntry = MemoryMap;
- MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + *MemoryMapSize);
- while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
- CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
- NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
-
- do {
- MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart);
- MemoryBlockLength = LShiftU64 (NewMemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT);
- if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
- (NewMemoryMapEntry->Type == NextMemoryMapEntry->Type) &&
- (NewMemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&
- ((NewMemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart))
- {
- NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
- NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
- continue;
- } else {
- MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
- break;
- }
- } while (TRUE);
-
- MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
- NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);
- }
-
- *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;
-
- return;
-}
-
-/**
- Enforce memory map attributes.
- This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
-
- @param MemoryMap A pointer to the buffer in which firmware places
- the current memory map.
- @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
- @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-**/
-STATIC
-VOID
-EnforceMemoryMapAttribute (
- IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
- IN UINTN MemoryMapSize,
- IN UINTN DescriptorSize
- )
-{
- EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
- EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
-
- MemoryMapEntry = MemoryMap;
- MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
- while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
- switch (MemoryMapEntry->Type) {
- case EfiRuntimeServicesCode:
- // do nothing
- break;
- case EfiRuntimeServicesData:
- case EfiMemoryMappedIO:
- case EfiMemoryMappedIOPortSpace:
- MemoryMapEntry->Attribute |= EFI_MEMORY_XP;
- break;
- case EfiReservedMemoryType:
- case EfiACPIMemoryNVS:
- break;
- }
-
- MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
- }
-
- return;
-}
-
-/**
- This function for GetMemoryMap() with properties table capability.
-
- It calls original GetMemoryMap() to get the original memory map information. Then
- plus the additional memory map entries for PE Code/Data seperation.
-
- @param MemoryMapSize A pointer to the size, in bytes, of the
- MemoryMap buffer. On input, this is the size of
- the buffer allocated by the caller. On output,
- it is the size of the buffer returned by the
- firmware if the buffer was large enough, or the
- size of the buffer needed to contain the map if
- the buffer was too small.
- @param MemoryMap A pointer to the buffer in which firmware places
- the current memory map.
- @param MapKey A pointer to the location in which firmware
- returns the key for the current memory map.
- @param DescriptorSize A pointer to the location in which firmware
- returns the size, in bytes, of an individual
- EFI_MEMORY_DESCRIPTOR.
- @param DescriptorVersion A pointer to the location in which firmware
- returns the version number associated with the
- EFI_MEMORY_DESCRIPTOR.
-
- @retval EFI_SUCCESS The memory map was returned in the MemoryMap
- buffer.
- @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
- buffer size needed to hold the memory map is
- returned in MemoryMapSize.
- @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreGetMemoryMapWithSeparatedImageSection (
- IN OUT UINTN *MemoryMapSize,
- IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
- OUT UINTN *MapKey,
- OUT UINTN *DescriptorSize,
- OUT UINT32 *DescriptorVersion
- )
-{
- EFI_STATUS Status;
- UINTN OldMemoryMapSize;
- UINTN AdditionalRecordCount;
-
- //
- // If PE code/data is not aligned, just return.
- //
- if (!mMemoryAttributesTableEnable) {
- return CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
- }
-
- if (MemoryMapSize == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- CoreAcquiremMemoryAttributesTableLock ();
-
- AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 3) * mImagePropertiesPrivateData.ImageRecordCount;
-
- OldMemoryMapSize = *MemoryMapSize;
- Status = CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
- if (Status == EFI_BUFFER_TOO_SMALL) {
- *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;
- } else if (Status == EFI_SUCCESS) {
- ASSERT (MemoryMap != NULL);
- if (OldMemoryMapSize - *MemoryMapSize < (*DescriptorSize) * AdditionalRecordCount) {
- *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;
- //
- // Need update status to buffer too small
- //
- Status = EFI_BUFFER_TOO_SMALL;
- } else {
- //
- // Split PE code/data
- //
- SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize, &mImagePropertiesPrivateData.ImageRecordList, AdditionalRecordCount);
-
- //
- // Set RuntimeData to XP
- //
- EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, *DescriptorSize);
-
- //
- // Merge same type to save entry size
- //
- MergeMemoryMap (MemoryMap, MemoryMapSize, *DescriptorSize);
- }
- }
-
- CoreReleasemMemoryAttributesTableLock ();
- return Status;
-}
-
-//
-// Below functions are for ImageRecord
-//
-
-/**
- Insert image record.
-
- @param RuntimeImage Runtime image information
-**/
-VOID
-InsertImageRecord (
- IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage
- )
-{
- EFI_STATUS Status;
- IMAGE_PROPERTIES_RECORD *ImageRecord;
- CHAR8 *PdbPointer;
- UINT32 RequiredAlignment;
-
- DEBUG ((DEBUG_VERBOSE, "InsertImageRecord - 0x%x\n", RuntimeImage));
-
- if (mMemoryAttributesTableEndOfDxe) {
- DEBUG ((DEBUG_INFO, "Do not insert runtime image record after EndOfDxe\n"));
- return;
- }
-
- ImageRecord = AllocatePool (sizeof (*ImageRecord));
- if (ImageRecord == NULL) {
- return;
- }
-
- InitializeListHead (&ImageRecord->Link);
- InitializeListHead (&ImageRecord->CodeSegmentList);
-
- PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)RuntimeImage->ImageBase);
- if (PdbPointer != NULL) {
- DEBUG ((DEBUG_VERBOSE, " Image - %a\n", PdbPointer));
- }
-
- RequiredAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
- Status = CreateImagePropertiesRecord (
- RuntimeImage->ImageBase,
- RuntimeImage->ImageSize,
- &RequiredAlignment,
- ImageRecord
- );
-
- if (EFI_ERROR (Status)) {
- if (Status == EFI_ABORTED) {
- mMemoryAttributesTableEnable = FALSE;
- }
-
- Status = EFI_ABORTED;
- goto Finish;
- }
-
- if (ImageRecord->CodeSegmentCount == 0) {
- mMemoryAttributesTableEnable = FALSE;
- DEBUG ((DEBUG_ERROR, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
- if (PdbPointer != NULL) {
- DEBUG ((DEBUG_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));
- }
-
- Status = EFI_ABORTED;
- goto Finish;
- }
-
- //
- // Check overlap all section in ImageBase/Size
- //
- if (!IsImageRecordCodeSectionValid (ImageRecord)) {
- DEBUG ((DEBUG_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));
- Status = EFI_ABORTED;
- goto Finish;
- }
-
- InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);
- mImagePropertiesPrivateData.ImageRecordCount++;
-
- if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {
- mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;
- }
-
- SortImageRecord (&mImagePropertiesPrivateData.ImageRecordList);
-
-Finish:
- if (EFI_ERROR (Status) && (ImageRecord != NULL)) {
- DeleteImagePropertiesRecord (ImageRecord);
- }
-
- return;
-}
-
-/**
- Remove Image record.
-
- @param RuntimeImage Runtime image information
-**/
-VOID
-RemoveImageRecord (
- IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage
- )
-{
- IMAGE_PROPERTIES_RECORD *ImageRecord;
-
- DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%x\n", RuntimeImage));
- DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));
-
- if (mMemoryAttributesTableEndOfDxe) {
- DEBUG ((DEBUG_INFO, "Do not remove runtime image record after EndOfDxe\n"));
- return;
- }
-
- ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize, &mImagePropertiesPrivateData.ImageRecordList);
- if (ImageRecord == NULL) {
- DEBUG ((DEBUG_ERROR, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
- return;
- }
-
- DeleteImagePropertiesRecord (ImageRecord);
-
- mImagePropertiesPrivateData.ImageRecordCount--;
-}
+/** @file
+ UEFI MemoryAttributesTable support
+
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/ImagePropertiesRecordLib.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Guid/MemoryAttributesTable.h>
+
+#include "DxeMain.h"
+#include "HeapGuard.h"
+
+/**
+ This function for GetMemoryMap() with properties table capability.
+
+ It calls original GetMemoryMap() to get the original memory map information. Then
+ plus the additional memory map entries for PE Code/Data seperation.
+
+ @param MemoryMapSize A pointer to the size, in bytes, of the
+ MemoryMap buffer. On input, this is the size of
+ the buffer allocated by the caller. On output,
+ it is the size of the buffer returned by the
+ firmware if the buffer was large enough, or the
+ size of the buffer needed to contain the map if
+ the buffer was too small.
+ @param MemoryMap A pointer to the buffer in which firmware places
+ the current memory map.
+ @param MapKey A pointer to the location in which firmware
+ returns the key for the current memory map.
+ @param DescriptorSize A pointer to the location in which firmware
+ returns the size, in bytes, of an individual
+ EFI_MEMORY_DESCRIPTOR.
+ @param DescriptorVersion A pointer to the location in which firmware
+ returns the version number associated with the
+ EFI_MEMORY_DESCRIPTOR.
+
+ @retval EFI_SUCCESS The memory map was returned in the MemoryMap
+ buffer.
+ @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
+ buffer size needed to hold the memory map is
+ returned in MemoryMapSize.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreGetMemoryMapWithSeparatedImageSection (
+ IN OUT UINTN *MemoryMapSize,
+ IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ OUT UINTN *MapKey,
+ OUT UINTN *DescriptorSize,
+ OUT UINT32 *DescriptorVersion
+ );
+
+#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
+ ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
+
+#define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
+
+typedef struct {
+ UINT32 Signature;
+ UINTN ImageRecordCount;
+ UINTN CodeSegmentCountMax;
+ LIST_ENTRY ImageRecordList;
+} IMAGE_PROPERTIES_PRIVATE_DATA;
+
+STATIC IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData = {
+ IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE,
+ 0,
+ 0,
+ INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData.ImageRecordList)
+};
+
+STATIC EFI_LOCK mMemoryAttributesTableLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
+
+BOOLEAN mMemoryAttributesTableEnable = TRUE;
+BOOLEAN mMemoryAttributesTableEndOfDxe = FALSE;
+EFI_MEMORY_ATTRIBUTES_TABLE *mMemoryAttributesTable = NULL;
+BOOLEAN mMemoryAttributesTableReadyToBoot = FALSE;
+BOOLEAN gMemoryAttributesTableForwardCfi = TRUE;
+
+/**
+ Install MemoryAttributesTable.
+
+**/
+VOID
+InstallMemoryAttributesTable (
+ VOID
+ )
+{
+ UINTN MemoryMapSize;
+ EFI_MEMORY_DESCRIPTOR *MemoryMap;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapStart;
+ UINTN MapKey;
+ UINTN DescriptorSize;
+ UINT32 DescriptorVersion;
+ UINTN Index;
+ EFI_STATUS Status;
+ UINT32 RuntimeEntryCount;
+ EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;
+ EFI_MEMORY_DESCRIPTOR *MemoryAttributesEntry;
+
+ if (gMemoryMapTerminated) {
+ //
+ // Directly return after MemoryMap terminated.
+ //
+ return;
+ }
+
+ if (!mMemoryAttributesTableEnable) {
+ DEBUG ((DEBUG_VERBOSE, "Cannot install Memory Attributes Table "));
+ DEBUG ((DEBUG_VERBOSE, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));
+ return;
+ }
+
+ if (mMemoryAttributesTable == NULL) {
+ //
+ // InstallConfigurationTable here to occupy one entry for MemoryAttributesTable
+ // before GetMemoryMap below, as InstallConfigurationTable may allocate runtime
+ // memory for the new entry.
+ //
+ Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID *)(UINTN)MAX_ADDRESS);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ MemoryMapSize = 0;
+ MemoryMap = NULL;
+ Status = CoreGetMemoryMapWithSeparatedImageSection (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+
+ do {
+ MemoryMap = AllocatePool (MemoryMapSize);
+ ASSERT (MemoryMap != NULL);
+
+ Status = CoreGetMemoryMapWithSeparatedImageSection (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (MemoryMap);
+ }
+ } while (Status == EFI_BUFFER_TOO_SMALL);
+
+ MemoryMapStart = MemoryMap;
+ RuntimeEntryCount = 0;
+ for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {
+ switch (MemoryMap->Type) {
+ case EfiRuntimeServicesCode:
+ case EfiRuntimeServicesData:
+ RuntimeEntryCount++;
+ break;
+ }
+
+ MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
+ }
+
+ //
+ // Allocate MemoryAttributesTable
+ //
+ MemoryAttributesTable = AllocatePool (sizeof (EFI_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount);
+ ASSERT (MemoryAttributesTable != NULL);
+ MemoryAttributesTable->Version = EFI_MEMORY_ATTRIBUTES_TABLE_VERSION;
+ MemoryAttributesTable->NumberOfEntries = RuntimeEntryCount;
+ MemoryAttributesTable->DescriptorSize = (UINT32)DescriptorSize;
+ if (gMemoryAttributesTableForwardCfi) {
+ MemoryAttributesTable->Flags = EFI_MEMORY_ATTRIBUTES_FLAGS_RT_FORWARD_CONTROL_FLOW_GUARD;
+ } else {
+ MemoryAttributesTable->Flags = 0;
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "MemoryAttributesTable:\n"));
+ DEBUG ((DEBUG_VERBOSE, " Version - 0x%08x\n", MemoryAttributesTable->Version));
+ DEBUG ((DEBUG_VERBOSE, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable->NumberOfEntries));
+ DEBUG ((DEBUG_VERBOSE, " DescriptorSize - 0x%08x\n", MemoryAttributesTable->DescriptorSize));
+ MemoryAttributesEntry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);
+ MemoryMap = MemoryMapStart;
+ for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {
+ switch (MemoryMap->Type) {
+ case EfiRuntimeServicesCode:
+ case EfiRuntimeServicesData:
+ CopyMem (MemoryAttributesEntry, MemoryMap, DescriptorSize);
+ MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME);
+ DEBUG ((DEBUG_VERBOSE, "Entry (0x%x)\n", MemoryAttributesEntry));
+ DEBUG ((DEBUG_VERBOSE, " Type - 0x%x\n", MemoryAttributesEntry->Type));
+ DEBUG ((DEBUG_VERBOSE, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry->PhysicalStart));
+ DEBUG ((DEBUG_VERBOSE, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry->VirtualStart));
+ DEBUG ((DEBUG_VERBOSE, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry->NumberOfPages));
+ DEBUG ((DEBUG_VERBOSE, " Attribute - 0x%016lx\n", MemoryAttributesEntry->Attribute));
+ MemoryAttributesEntry = NEXT_MEMORY_DESCRIPTOR (MemoryAttributesEntry, DescriptorSize);
+ break;
+ }
+
+ MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
+ }
+
+ MemoryMap = MemoryMapStart;
+ FreePool (MemoryMap);
+
+ //
+ // Update configuratoin table for MemoryAttributesTable.
+ //
+ Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, MemoryAttributesTable);
+ ASSERT_EFI_ERROR (Status);
+
+ if (mMemoryAttributesTable != NULL) {
+ FreePool (mMemoryAttributesTable);
+ }
+
+ mMemoryAttributesTable = MemoryAttributesTable;
+}
+
+/**
+ Install MemoryAttributesTable on memory allocation.
+
+ @param[in] MemoryType EFI memory type.
+**/
+VOID
+InstallMemoryAttributesTableOnMemoryAllocation (
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ //
+ // Install MemoryAttributesTable after ReadyToBoot on runtime memory allocation.
+ //
+ if (mMemoryAttributesTableReadyToBoot &&
+ ((MemoryType == EfiRuntimeServicesCode) || (MemoryType == EfiRuntimeServicesData)))
+ {
+ InstallMemoryAttributesTable ();
+ }
+}
+
+/**
+ Install MemoryAttributesTable on ReadyToBoot.
+
+ @param[in] Event The Event this notify function registered to.
+ @param[in] Context Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+InstallMemoryAttributesTableOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ InstallMemoryAttributesTable ();
+ mMemoryAttributesTableReadyToBoot = TRUE;
+}
+
+/**
+ Install initial MemoryAttributesTable on EndOfDxe.
+ Then SMM can consume this information.
+
+ @param[in] Event The Event this notify function registered to.
+ @param[in] Context Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+InstallMemoryAttributesTableOnEndOfDxe (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ mMemoryAttributesTableEndOfDxe = TRUE;
+ InstallMemoryAttributesTable ();
+
+ DEBUG_CODE_BEGIN ();
+ if ( mImagePropertiesPrivateData.ImageRecordCount > 0) {
+ DEBUG ((DEBUG_INFO, "DXE - Total Runtime Image Count: 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
+ DEBUG ((DEBUG_INFO, "DXE - Dump Runtime Image Records:\n"));
+ DumpImageRecords (&mImagePropertiesPrivateData.ImageRecordList);
+ }
+
+ DEBUG_CODE_END ();
+}
+
+/**
+ Initialize MemoryAttrubutesTable support.
+**/
+VOID
+EFIAPI
+CoreInitializeMemoryAttributesTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT ReadyToBootEvent;
+ EFI_EVENT EndOfDxeEvent;
+
+ //
+ // Construct the table at ReadyToBoot.
+ //
+ Status = CoreCreateEventInternal (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ InstallMemoryAttributesTableOnReadyToBoot,
+ NULL,
+ &gEfiEventReadyToBootGuid,
+ &ReadyToBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Construct the initial table at EndOfDxe,
+ // then SMM can consume this information.
+ // Use TPL_NOTIFY here, as such SMM code (TPL_CALLBACK)
+ // can run after it.
+ //
+ Status = CoreCreateEventInternal (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ InstallMemoryAttributesTableOnEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ return;
+}
+
+//
+// Below functions are for MemoryMap
+//
+
+/**
+ Acquire memory lock on mMemoryAttributesTableLock.
+**/
+STATIC
+VOID
+CoreAcquiremMemoryAttributesTableLock (
+ VOID
+ )
+{
+ CoreAcquireLock (&mMemoryAttributesTableLock);
+}
+
+/**
+ Release memory lock on mMemoryAttributesTableLock.
+**/
+STATIC
+VOID
+CoreReleasemMemoryAttributesTableLock (
+ VOID
+ )
+{
+ CoreReleaseLock (&mMemoryAttributesTableLock);
+}
+
+/**
+ Merge continous memory map entries whose have same attributes.
+
+ @param MemoryMap A pointer to the buffer in which firmware places
+ the current memory map.
+ @param MemoryMapSize A pointer to the size, in bytes, of the
+ MemoryMap buffer. On input, this is the size of
+ the current memory map. On output,
+ it is the size of new memory map after merge.
+ @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+**/
+VOID
+MergeMemoryMap (
+ IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ IN OUT UINTN *MemoryMapSize,
+ IN UINTN DescriptorSize
+ )
+{
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
+ UINT64 MemoryBlockLength;
+ EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry;
+ EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
+
+ MemoryMapEntry = MemoryMap;
+ NewMemoryMapEntry = MemoryMap;
+ MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + *MemoryMapSize);
+ while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
+ CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
+ NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+
+ do {
+ MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart);
+ MemoryBlockLength = LShiftU64 (NewMemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT);
+ if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
+ (NewMemoryMapEntry->Type == NextMemoryMapEntry->Type) &&
+ (NewMemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&
+ ((NewMemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart))
+ {
+ NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
+ NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
+ continue;
+ } else {
+ MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
+ break;
+ }
+ } while (TRUE);
+
+ MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+ NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);
+ }
+
+ *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;
+
+ return;
+}
+
+/**
+ Enforce memory map attributes.
+ This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
+
+ @param MemoryMap A pointer to the buffer in which firmware places
+ the current memory map.
+ @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
+ @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+**/
+STATIC
+VOID
+EnforceMemoryMapAttribute (
+ IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ IN UINTN MemoryMapSize,
+ IN UINTN DescriptorSize
+ )
+{
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
+
+ MemoryMapEntry = MemoryMap;
+ MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
+ while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
+ switch (MemoryMapEntry->Type) {
+ case EfiRuntimeServicesCode:
+ // do nothing
+ break;
+ case EfiRuntimeServicesData:
+ case EfiMemoryMappedIO:
+ case EfiMemoryMappedIOPortSpace:
+ MemoryMapEntry->Attribute |= EFI_MEMORY_XP;
+ break;
+ case EfiReservedMemoryType:
+ case EfiACPIMemoryNVS:
+ break;
+ }
+
+ MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+ }
+
+ return;
+}
+
+/**
+ This function for GetMemoryMap() with properties table capability.
+
+ It calls original GetMemoryMap() to get the original memory map information. Then
+ plus the additional memory map entries for PE Code/Data seperation.
+
+ @param MemoryMapSize A pointer to the size, in bytes, of the
+ MemoryMap buffer. On input, this is the size of
+ the buffer allocated by the caller. On output,
+ it is the size of the buffer returned by the
+ firmware if the buffer was large enough, or the
+ size of the buffer needed to contain the map if
+ the buffer was too small.
+ @param MemoryMap A pointer to the buffer in which firmware places
+ the current memory map.
+ @param MapKey A pointer to the location in which firmware
+ returns the key for the current memory map.
+ @param DescriptorSize A pointer to the location in which firmware
+ returns the size, in bytes, of an individual
+ EFI_MEMORY_DESCRIPTOR.
+ @param DescriptorVersion A pointer to the location in which firmware
+ returns the version number associated with the
+ EFI_MEMORY_DESCRIPTOR.
+
+ @retval EFI_SUCCESS The memory map was returned in the MemoryMap
+ buffer.
+ @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
+ buffer size needed to hold the memory map is
+ returned in MemoryMapSize.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreGetMemoryMapWithSeparatedImageSection (
+ IN OUT UINTN *MemoryMapSize,
+ IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ OUT UINTN *MapKey,
+ OUT UINTN *DescriptorSize,
+ OUT UINT32 *DescriptorVersion
+ )
+{
+ EFI_STATUS Status;
+ UINTN OldMemoryMapSize;
+ UINTN AdditionalRecordCount;
+
+ //
+ // If PE code/data is not aligned, just return.
+ //
+ if (!mMemoryAttributesTableEnable) {
+ return CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
+ }
+
+ if (MemoryMapSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CoreAcquiremMemoryAttributesTableLock ();
+
+ AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 3) * mImagePropertiesPrivateData.ImageRecordCount;
+
+ OldMemoryMapSize = *MemoryMapSize;
+ Status = CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;
+ } else if (Status == EFI_SUCCESS) {
+ ASSERT (MemoryMap != NULL);
+ if (OldMemoryMapSize - *MemoryMapSize < (*DescriptorSize) * AdditionalRecordCount) {
+ *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;
+ //
+ // Need update status to buffer too small
+ //
+ Status = EFI_BUFFER_TOO_SMALL;
+ } else {
+ //
+ // Split PE code/data
+ //
+ SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize, &mImagePropertiesPrivateData.ImageRecordList, AdditionalRecordCount);
+
+ //
+ // Set RuntimeData to XP
+ //
+ EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, *DescriptorSize);
+
+ //
+ // Merge same type to save entry size
+ //
+ MergeMemoryMap (MemoryMap, MemoryMapSize, *DescriptorSize);
+ }
+ }
+
+ CoreReleasemMemoryAttributesTableLock ();
+ return Status;
+}
+
+//
+// Below functions are for ImageRecord
+//
+
+/**
+ Insert image record.
+
+ @param RuntimeImage Runtime image information
+**/
+VOID
+InsertImageRecord (
+ IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage
+ )
+{
+ EFI_STATUS Status;
+ IMAGE_PROPERTIES_RECORD *ImageRecord;
+ CHAR8 *PdbPointer;
+ UINT32 RequiredAlignment;
+
+ DEBUG ((DEBUG_VERBOSE, "InsertImageRecord - 0x%x\n", RuntimeImage));
+
+ if (mMemoryAttributesTableEndOfDxe) {
+ DEBUG ((DEBUG_INFO, "Do not insert runtime image record after EndOfDxe\n"));
+ return;
+ }
+
+ ImageRecord = AllocatePool (sizeof (*ImageRecord));
+ if (ImageRecord == NULL) {
+ return;
+ }
+
+ InitializeListHead (&ImageRecord->Link);
+ InitializeListHead (&ImageRecord->CodeSegmentList);
+
+ PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)RuntimeImage->ImageBase);
+ if (PdbPointer != NULL) {
+ DEBUG ((DEBUG_VERBOSE, " Image - %a\n", PdbPointer));
+ }
+
+ RequiredAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+ Status = CreateImagePropertiesRecord (
+ RuntimeImage->ImageBase,
+ RuntimeImage->ImageSize,
+ &RequiredAlignment,
+ ImageRecord
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ mMemoryAttributesTableEnable = FALSE;
+ }
+
+ Status = EFI_ABORTED;
+ goto Finish;
+ }
+
+ if (ImageRecord->CodeSegmentCount == 0) {
+ mMemoryAttributesTableEnable = FALSE;
+ DEBUG ((DEBUG_ERROR, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
+ if (PdbPointer != NULL) {
+ DEBUG ((DEBUG_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));
+ }
+
+ Status = EFI_ABORTED;
+ goto Finish;
+ }
+
+ //
+ // Check overlap all section in ImageBase/Size
+ //
+ if (!IsImageRecordCodeSectionValid (ImageRecord)) {
+ DEBUG ((DEBUG_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));
+ Status = EFI_ABORTED;
+ goto Finish;
+ }
+
+ InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);
+ mImagePropertiesPrivateData.ImageRecordCount++;
+
+ if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {
+ mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;
+ }
+
+ SortImageRecord (&mImagePropertiesPrivateData.ImageRecordList);
+
+Finish:
+ if (EFI_ERROR (Status) && (ImageRecord != NULL)) {
+ DeleteImagePropertiesRecord (ImageRecord);
+ }
+
+ return;
+}
+
+/**
+ Remove Image record.
+
+ @param RuntimeImage Runtime image information
+**/
+VOID
+RemoveImageRecord (
+ IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage
+ )
+{
+ IMAGE_PROPERTIES_RECORD *ImageRecord;
+
+ DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%x\n", RuntimeImage));
+ DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));
+
+ if (mMemoryAttributesTableEndOfDxe) {
+ DEBUG ((DEBUG_INFO, "Do not remove runtime image record after EndOfDxe\n"));
+ return;
+ }
+
+ ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize, &mImagePropertiesPrivateData.ImageRecordList);
+ if (ImageRecord == NULL) {
+ DEBUG ((DEBUG_ERROR, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
+ return;
+ }
+
+ DeleteImagePropertiesRecord (ImageRecord);
+
+ mImagePropertiesPrivateData.ImageRecordCount--;
+}
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
index 2c069cc12c..9cfd107730 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
@@ -1,1110 +1,1110 @@
-/** @file
- UEFI Memory Protection support.
-
- If the UEFI image is page aligned, the image code section is set to read only
- and the image data section is set to non-executable.
-
- 1) This policy is applied for all UEFI image including boot service driver,
- runtime driver or application.
- 2) This policy is applied only if the UEFI image meets the page alignment
- requirement.
- 3) This policy is applied only if the Source UEFI image matches the
- PcdImageProtectionPolicy definition.
- 4) This policy is not applied to the non-PE image region.
-
- The DxeCore calls CpuArchProtocol->SetMemoryAttributes() to protect
- the image. If the CpuArch protocol is not installed yet, the DxeCore
- enqueues the protection request. Once the CpuArch is installed, the
- DxeCore dequeues the protection request and applies policy.
-
- Once the image is unloaded, the protection is removed automatically.
-
-Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PiDxe.h>
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/DxeServicesTableLib.h>
-#include <Library/DebugLib.h>
-#include <Library/UefiLib.h>
-#include <Library/ImagePropertiesRecordLib.h>
-
-#include <Guid/EventGroup.h>
-#include <Guid/MemoryAttributesTable.h>
-
-#include <Protocol/FirmwareVolume2.h>
-#include <Protocol/SimpleFileSystem.h>
-
-#include "DxeMain.h"
-#include "Mem/HeapGuard.h"
-
-//
-// Image type definitions
-//
-#define IMAGE_UNKNOWN 0x00000001
-#define IMAGE_FROM_FV 0x00000002
-
-//
-// Protection policy bit definition
-//
-#define DO_NOT_PROTECT 0x00000000
-#define PROTECT_IF_ALIGNED_ELSE_ALLOW 0x00000001
-
-#define MEMORY_TYPE_OS_RESERVED_MIN 0x80000000
-#define MEMORY_TYPE_OEM_RESERVED_MIN 0x70000000
-
-#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
- ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
-
-UINT32 mImageProtectionPolicy;
-
-extern LIST_ENTRY mGcdMemorySpaceMap;
-
-STATIC LIST_ENTRY mProtectedImageRecordList;
-
-/**
- Get the image type.
-
- @param[in] File This is a pointer to the device path of the file that is
- being dispatched.
-
- @return UINT32 Image Type
-**/
-UINT32
-GetImageType (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *File
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE DeviceHandle;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
-
- if (File == NULL) {
- return IMAGE_UNKNOWN;
- }
-
- //
- // First check to see if File is from a Firmware Volume
- //
- DeviceHandle = NULL;
- TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
- Status = gBS->LocateDevicePath (
- &gEfiFirmwareVolume2ProtocolGuid,
- &TempDevicePath,
- &DeviceHandle
- );
- if (!EFI_ERROR (Status)) {
- Status = gBS->OpenProtocol (
- DeviceHandle,
- &gEfiFirmwareVolume2ProtocolGuid,
- NULL,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- return IMAGE_FROM_FV;
- }
- }
-
- return IMAGE_UNKNOWN;
-}
-
-/**
- Get UEFI image protection policy based upon image type.
-
- @param[in] ImageType The UEFI image type
-
- @return UEFI image protection policy
-**/
-UINT32
-GetProtectionPolicyFromImageType (
- IN UINT32 ImageType
- )
-{
- if ((ImageType & mImageProtectionPolicy) == 0) {
- return DO_NOT_PROTECT;
- } else {
- return PROTECT_IF_ALIGNED_ELSE_ALLOW;
- }
-}
-
-/**
- Get UEFI image protection policy based upon loaded image device path.
-
- @param[in] LoadedImage The loaded image protocol
- @param[in] LoadedImageDevicePath The loaded image device path protocol
-
- @return UEFI image protection policy
-**/
-UINT32
-GetUefiImageProtectionPolicy (
- IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
- IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath
- )
-{
- BOOLEAN InSmm;
- UINT32 ImageType;
- UINT32 ProtectionPolicy;
-
- //
- // Check SMM
- //
- InSmm = FALSE;
- if (gSmmBase2 != NULL) {
- gSmmBase2->InSmm (gSmmBase2, &InSmm);
- }
-
- if (InSmm) {
- return FALSE;
- }
-
- //
- // Check DevicePath
- //
- if (LoadedImage == gDxeCoreLoadedImage) {
- ImageType = IMAGE_FROM_FV;
- } else {
- ImageType = GetImageType (LoadedImageDevicePath);
- }
-
- ProtectionPolicy = GetProtectionPolicyFromImageType (ImageType);
- return ProtectionPolicy;
-}
-
-/**
- Set UEFI image memory attributes.
-
- @param[in] BaseAddress Specified start address
- @param[in] Length Specified length
- @param[in] Attributes Specified attributes
-**/
-VOID
-SetUefiImageMemoryAttributes (
- IN UINT64 BaseAddress,
- IN UINT64 Length,
- IN UINT64 Attributes
- )
-{
- EFI_STATUS Status;
- EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
- UINT64 FinalAttributes;
-
- Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);
- ASSERT_EFI_ERROR (Status);
-
- FinalAttributes = (Descriptor.Attributes & EFI_CACHE_ATTRIBUTE_MASK) | (Attributes & EFI_MEMORY_ATTRIBUTE_MASK);
-
- DEBUG ((DEBUG_INFO, "SetUefiImageMemoryAttributes - 0x%016lx - 0x%016lx (0x%016lx)\n", BaseAddress, Length, FinalAttributes));
-
- ASSERT (gCpu != NULL);
- gCpu->SetMemoryAttributes (gCpu, BaseAddress, Length, FinalAttributes);
-}
-
-/**
- Set UEFI image protection attributes.
-
- @param[in] ImageRecord A UEFI image record
-**/
-VOID
-SetUefiImageProtectionAttributes (
- IN IMAGE_PROPERTIES_RECORD *ImageRecord
- )
-{
- IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
- LIST_ENTRY *ImageRecordCodeSectionLink;
- LIST_ENTRY *ImageRecordCodeSectionEndLink;
- LIST_ENTRY *ImageRecordCodeSectionList;
- UINT64 CurrentBase;
- UINT64 ImageEnd;
-
- ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
-
- CurrentBase = ImageRecord->ImageBase;
- ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
-
- ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
- ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
- while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
- ImageRecordCodeSection = CR (
- ImageRecordCodeSectionLink,
- IMAGE_PROPERTIES_RECORD_CODE_SECTION,
- Link,
- IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
- );
- ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
-
- ASSERT (CurrentBase <= ImageRecordCodeSection->CodeSegmentBase);
- if (CurrentBase < ImageRecordCodeSection->CodeSegmentBase) {
- //
- // DATA
- //
- SetUefiImageMemoryAttributes (
- CurrentBase,
- ImageRecordCodeSection->CodeSegmentBase - CurrentBase,
- EFI_MEMORY_XP
- );
- }
-
- //
- // CODE
- //
- SetUefiImageMemoryAttributes (
- ImageRecordCodeSection->CodeSegmentBase,
- ImageRecordCodeSection->CodeSegmentSize,
- EFI_MEMORY_RO
- );
- CurrentBase = ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize;
- }
-
- //
- // Last DATA
- //
- ASSERT (CurrentBase <= ImageEnd);
- if (CurrentBase < ImageEnd) {
- //
- // DATA
- //
- SetUefiImageMemoryAttributes (
- CurrentBase,
- ImageEnd - CurrentBase,
- EFI_MEMORY_XP
- );
- }
-
- return;
-}
-
-/**
- Return the section alignment requirement for the PE image section type.
-
- @param[in] MemoryType PE/COFF image memory type
-
- @retval The required section alignment for this memory type
-
-**/
-STATIC
-UINT32
-GetMemoryProtectionSectionAlignment (
- IN EFI_MEMORY_TYPE MemoryType
- )
-{
- UINT32 SectionAlignment;
-
- switch (MemoryType) {
- case EfiRuntimeServicesCode:
- case EfiACPIMemoryNVS:
- case EfiReservedMemoryType:
- SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
- break;
- case EfiRuntimeServicesData:
- ASSERT (FALSE);
- SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
- break;
- case EfiBootServicesCode:
- case EfiLoaderCode:
- SectionAlignment = EFI_PAGE_SIZE;
- break;
- case EfiACPIReclaimMemory:
- default:
- ASSERT (FALSE);
- SectionAlignment = EFI_PAGE_SIZE;
- break;
- }
-
- return SectionAlignment;
-}
-
-/**
- Protect UEFI PE/COFF image.
-
- @param[in] LoadedImage The loaded image protocol
- @param[in] LoadedImageDevicePath The loaded image device path protocol
-**/
-VOID
-ProtectUefiImage (
- IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
- IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath
- )
-{
- IMAGE_PROPERTIES_RECORD *ImageRecord;
- UINT32 ProtectionPolicy;
- EFI_STATUS Status;
- UINT32 RequiredAlignment;
-
- DEBUG ((DEBUG_INFO, "ProtectUefiImageCommon - 0x%x\n", LoadedImage));
- DEBUG ((DEBUG_INFO, " - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase, LoadedImage->ImageSize));
-
- if (gCpu == NULL) {
- return;
- }
-
- ProtectionPolicy = GetUefiImageProtectionPolicy (LoadedImage, LoadedImageDevicePath);
- switch (ProtectionPolicy) {
- case DO_NOT_PROTECT:
- return;
- case PROTECT_IF_ALIGNED_ELSE_ALLOW:
- break;
- default:
- ASSERT (FALSE);
- return;
- }
-
- ImageRecord = AllocateZeroPool (sizeof (*ImageRecord));
- if (ImageRecord == NULL) {
- return;
- }
-
- RequiredAlignment = GetMemoryProtectionSectionAlignment (LoadedImage->ImageCodeType);
-
- Status = CreateImagePropertiesRecord (
- LoadedImage->ImageBase,
- LoadedImage->ImageSize,
- &RequiredAlignment,
- ImageRecord
- );
-
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a failed to create image properties record\n", __func__));
- FreePool (ImageRecord);
- goto Finish;
- }
-
- //
- // CPU ARCH present. Update memory attribute directly.
- //
- SetUefiImageProtectionAttributes (ImageRecord);
-
- //
- // Record the image record in the list so we can undo the protections later
- //
- InsertTailList (&mProtectedImageRecordList, &ImageRecord->Link);
-
-Finish:
- return;
-}
-
-/**
- Unprotect UEFI image.
-
- @param[in] LoadedImage The loaded image protocol
- @param[in] LoadedImageDevicePath The loaded image device path protocol
-**/
-VOID
-UnprotectUefiImage (
- IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
- IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath
- )
-{
- IMAGE_PROPERTIES_RECORD *ImageRecord;
- LIST_ENTRY *ImageRecordLink;
-
- if (PcdGet32 (PcdImageProtectionPolicy) != 0) {
- for (ImageRecordLink = mProtectedImageRecordList.ForwardLink;
- ImageRecordLink != &mProtectedImageRecordList;
- ImageRecordLink = ImageRecordLink->ForwardLink)
- {
- ImageRecord = CR (
- ImageRecordLink,
- IMAGE_PROPERTIES_RECORD,
- Link,
- IMAGE_PROPERTIES_RECORD_SIGNATURE
- );
-
- if (ImageRecord->ImageBase == (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase) {
- SetUefiImageMemoryAttributes (
- ImageRecord->ImageBase,
- ImageRecord->ImageSize,
- 0
- );
- DeleteImagePropertiesRecord (ImageRecord);
- return;
- }
- }
- }
-}
-
-/**
- Return the EFI memory permission attribute associated with memory
- type 'MemoryType' under the configured DXE memory protection policy.
-
- @param MemoryType Memory type.
-**/
-STATIC
-UINT64
-GetPermissionAttributeForMemoryType (
- IN EFI_MEMORY_TYPE MemoryType
- )
-{
- UINT64 TestBit;
-
- if ((UINT32)MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) {
- TestBit = BIT63;
- } else if ((UINT32)MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {
- TestBit = BIT62;
- } else {
- TestBit = LShiftU64 (1, MemoryType);
- }
-
- if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & TestBit) != 0) {
- return EFI_MEMORY_XP;
- } else {
- return 0;
- }
-}
-
-/**
- Sort memory map entries based upon PhysicalStart, from low to high.
-
- @param MemoryMap A pointer to the buffer in which firmware places
- the current memory map.
- @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
- @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-**/
-STATIC
-VOID
-SortMemoryMap (
- IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
- IN UINTN MemoryMapSize,
- IN UINTN DescriptorSize
- )
-{
- EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
- EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
- EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
- EFI_MEMORY_DESCRIPTOR TempMemoryMap;
-
- MemoryMapEntry = MemoryMap;
- NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
- MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
- while (MemoryMapEntry < MemoryMapEnd) {
- while (NextMemoryMapEntry < MemoryMapEnd) {
- if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {
- CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
- CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
- CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof (EFI_MEMORY_DESCRIPTOR));
- }
-
- NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
- }
-
- MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
- NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
- }
-}
-
-/**
- Merge adjacent memory map entries if they use the same memory protection policy
-
- @param[in, out] MemoryMap A pointer to the buffer in which firmware places
- the current memory map.
- @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
- MemoryMap buffer. On input, this is the size of
- the current memory map. On output,
- it is the size of new memory map after merge.
- @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
-**/
-STATIC
-VOID
-MergeMemoryMapForProtectionPolicy (
- IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
- IN OUT UINTN *MemoryMapSize,
- IN UINTN DescriptorSize
- )
-{
- EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
- EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
- UINT64 MemoryBlockLength;
- EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry;
- EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
- UINT64 Attributes;
-
- SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
-
- MemoryMapEntry = MemoryMap;
- NewMemoryMapEntry = MemoryMap;
- MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + *MemoryMapSize);
- while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
- CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
- NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
-
- do {
- MemoryBlockLength = (UINT64)(EFI_PAGES_TO_SIZE ((UINTN)MemoryMapEntry->NumberOfPages));
- Attributes = GetPermissionAttributeForMemoryType (MemoryMapEntry->Type);
-
- if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
- (Attributes == GetPermissionAttributeForMemoryType (NextMemoryMapEntry->Type)) &&
- ((MemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart))
- {
- MemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
- if (NewMemoryMapEntry != MemoryMapEntry) {
- NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
- }
-
- NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
- continue;
- } else {
- MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
- break;
- }
- } while (TRUE);
-
- MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
- NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);
- }
-
- *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;
-
- return;
-}
-
-/**
- Remove exec permissions from all regions whose type is identified by
- PcdDxeNxMemoryProtectionPolicy.
-**/
-STATIC
-VOID
-InitializeDxeNxMemoryProtectionPolicy (
- VOID
- )
-{
- UINTN MemoryMapSize;
- UINTN MapKey;
- UINTN DescriptorSize;
- UINT32 DescriptorVersion;
- EFI_MEMORY_DESCRIPTOR *MemoryMap;
- EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
- EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
- EFI_STATUS Status;
- UINT64 Attributes;
- LIST_ENTRY *Link;
- EFI_GCD_MAP_ENTRY *Entry;
- EFI_PEI_HOB_POINTERS Hob;
- EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
- EFI_PHYSICAL_ADDRESS StackBase;
-
- //
- // Get the EFI memory map.
- //
- MemoryMapSize = 0;
- MemoryMap = NULL;
-
- Status = gBS->GetMemoryMap (
- &MemoryMapSize,
- MemoryMap,
- &MapKey,
- &DescriptorSize,
- &DescriptorVersion
- );
- ASSERT (Status == EFI_BUFFER_TOO_SMALL);
- do {
- MemoryMap = (EFI_MEMORY_DESCRIPTOR *)AllocatePool (MemoryMapSize);
- ASSERT (MemoryMap != NULL);
- Status = gBS->GetMemoryMap (
- &MemoryMapSize,
- MemoryMap,
- &MapKey,
- &DescriptorSize,
- &DescriptorVersion
- );
- if (EFI_ERROR (Status)) {
- FreePool (MemoryMap);
- }
- } while (Status == EFI_BUFFER_TOO_SMALL);
-
- ASSERT_EFI_ERROR (Status);
-
- StackBase = 0;
- if (PcdGetBool (PcdCpuStackGuard)) {
- //
- // Get the base of stack from Hob.
- //
- Hob.Raw = GetHobList ();
- while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
- MemoryHob = Hob.MemoryAllocation;
- if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &MemoryHob->AllocDescriptor.Name)) {
- DEBUG ((
- DEBUG_INFO,
- "%a: StackBase = 0x%016lx StackSize = 0x%016lx\n",
- __func__,
- MemoryHob->AllocDescriptor.MemoryBaseAddress,
- MemoryHob->AllocDescriptor.MemoryLength
- ));
-
- StackBase = MemoryHob->AllocDescriptor.MemoryBaseAddress;
- //
- // Ensure the base of the stack is page-size aligned.
- //
- ASSERT ((StackBase & EFI_PAGE_MASK) == 0);
- break;
- }
-
- Hob.Raw = GET_NEXT_HOB (Hob);
- }
-
- //
- // Ensure the base of stack can be found from Hob when stack guard is
- // enabled.
- //
- ASSERT (StackBase != 0);
- }
-
- DEBUG ((
- DEBUG_INFO,
- "%a: applying strict permissions to active memory regions\n",
- __func__
- ));
-
- MergeMemoryMapForProtectionPolicy (MemoryMap, &MemoryMapSize, DescriptorSize);
-
- MemoryMapEntry = MemoryMap;
- MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
- while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
- Attributes = GetPermissionAttributeForMemoryType (MemoryMapEntry->Type);
- if (Attributes != 0) {
- SetUefiImageMemoryAttributes (
- MemoryMapEntry->PhysicalStart,
- LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT),
- Attributes
- );
-
- //
- // Add EFI_MEMORY_RP attribute for page 0 if NULL pointer detection is
- // enabled.
- //
- if ((MemoryMapEntry->PhysicalStart == 0) &&
- (PcdGet8 (PcdNullPointerDetectionPropertyMask) != 0))
- {
- ASSERT (MemoryMapEntry->NumberOfPages > 0);
- SetUefiImageMemoryAttributes (
- 0,
- EFI_PAGES_TO_SIZE (1),
- EFI_MEMORY_RP | Attributes
- );
- }
-
- //
- // Add EFI_MEMORY_RP attribute for the first page of the stack if stack
- // guard is enabled.
- //
- if ((StackBase != 0) &&
- ((StackBase >= MemoryMapEntry->PhysicalStart) &&
- (StackBase < MemoryMapEntry->PhysicalStart +
- LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT))) &&
- PcdGetBool (PcdCpuStackGuard))
- {
- SetUefiImageMemoryAttributes (
- StackBase,
- EFI_PAGES_TO_SIZE (1),
- EFI_MEMORY_RP | Attributes
- );
- }
- }
-
- MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
- }
-
- FreePool (MemoryMap);
-
- //
- // Apply the policy for RAM regions that we know are present and
- // accessible, but have not been added to the UEFI memory map (yet).
- //
- if (GetPermissionAttributeForMemoryType (EfiConventionalMemory) != 0) {
- DEBUG ((
- DEBUG_INFO,
- "%a: applying strict permissions to inactive memory regions\n",
- __func__
- ));
-
- CoreAcquireGcdMemoryLock ();
-
- Link = mGcdMemorySpaceMap.ForwardLink;
- while (Link != &mGcdMemorySpaceMap) {
- Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
-
- if ((Entry->GcdMemoryType == EfiGcdMemoryTypeReserved) &&
- (Entry->EndAddress < MAX_ADDRESS) &&
- ((Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
- (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)))
- {
- Attributes = GetPermissionAttributeForMemoryType (EfiConventionalMemory) |
- (Entry->Attributes & EFI_CACHE_ATTRIBUTE_MASK);
-
- DEBUG ((
- DEBUG_INFO,
- "Untested GCD memory space region: - 0x%016lx - 0x%016lx (0x%016lx)\n",
- Entry->BaseAddress,
- Entry->EndAddress - Entry->BaseAddress + 1,
- Attributes
- ));
-
- ASSERT (gCpu != NULL);
- gCpu->SetMemoryAttributes (
- gCpu,
- Entry->BaseAddress,
- Entry->EndAddress - Entry->BaseAddress + 1,
- Attributes
- );
- }
-
- Link = Link->ForwardLink;
- }
-
- CoreReleaseGcdMemoryLock ();
- }
-}
-
-/**
- A notification for CPU_ARCH protocol.
-
- @param[in] Event Event whose notification function is being invoked.
- @param[in] Context Pointer to the notification function's context,
- which is implementation-dependent.
-
-**/
-VOID
-EFIAPI
-MemoryProtectionCpuArchProtocolNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- EFI_STATUS Status;
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
- EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
- UINTN NoHandles;
- EFI_HANDLE *HandleBuffer;
- UINTN Index;
-
- DEBUG ((DEBUG_INFO, "MemoryProtectionCpuArchProtocolNotify:\n"));
- Status = CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // Apply the memory protection policy on non-BScode/RTcode regions.
- //
- if (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) != 0) {
- InitializeDxeNxMemoryProtectionPolicy ();
- }
-
- //
- // Call notify function meant for Heap Guard.
- //
- HeapGuardCpuArchProtocolNotify ();
-
- if (mImageProtectionPolicy == 0) {
- goto Done;
- }
-
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiLoadedImageProtocolGuid,
- NULL,
- &NoHandles,
- &HandleBuffer
- );
- if (EFI_ERROR (Status) && (NoHandles == 0)) {
- goto Done;
- }
-
- for (Index = 0; Index < NoHandles; Index++) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiLoadedImageProtocolGuid,
- (VOID **)&LoadedImage
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiLoadedImageDevicePathProtocolGuid,
- (VOID **)&LoadedImageDevicePath
- );
- if (EFI_ERROR (Status)) {
- LoadedImageDevicePath = NULL;
- }
-
- ProtectUefiImage (LoadedImage, LoadedImageDevicePath);
- }
-
- FreePool (HandleBuffer);
-
-Done:
- CoreCloseEvent (Event);
-}
-
-/**
- ExitBootServices Callback function for memory protection.
-**/
-VOID
-MemoryProtectionExitBootServicesCallback (
- VOID
- )
-{
- EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage;
- LIST_ENTRY *Link;
-
- //
- // We need remove the RT protection, because RT relocation need write code segment
- // at SetVirtualAddressMap(). We cannot assume OS/Loader has taken over page table at that time.
- //
- // Firmware does not own page tables after ExitBootServices(), so the OS would
- // have to relax protection of RT code pages across SetVirtualAddressMap(), or
- // delay setting protections on RT code pages until after SetVirtualAddressMap().
- // OS may set protection on RT based upon EFI_MEMORY_ATTRIBUTES_TABLE later.
- //
- if (mImageProtectionPolicy != 0) {
- for (Link = gRuntime->ImageHead.ForwardLink; Link != &gRuntime->ImageHead; Link = Link->ForwardLink) {
- RuntimeImage = BASE_CR (Link, EFI_RUNTIME_IMAGE_ENTRY, Link);
- SetUefiImageMemoryAttributes ((UINT64)(UINTN)RuntimeImage->ImageBase, ALIGN_VALUE (RuntimeImage->ImageSize, EFI_PAGE_SIZE), 0);
- }
- }
-}
-
-/**
- Disable NULL pointer detection after EndOfDxe. This is a workaround resort in
- order to skip unfixable NULL pointer access issues detected in OptionROM or
- boot loaders.
-
- @param[in] Event The Event this notify function registered to.
- @param[in] Context Pointer to the context data registered to the Event.
-**/
-VOID
-EFIAPI
-DisableNullDetectionAtTheEndOfDxe (
- EFI_EVENT Event,
- VOID *Context
- )
-{
- EFI_STATUS Status;
- EFI_GCD_MEMORY_SPACE_DESCRIPTOR Desc;
-
- DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): start\r\n"));
- //
- // Disable NULL pointer detection by enabling first 4K page
- //
- Status = CoreGetMemorySpaceDescriptor (0, &Desc);
- ASSERT_EFI_ERROR (Status);
-
- if ((Desc.Capabilities & EFI_MEMORY_RP) == 0) {
- Status = CoreSetMemorySpaceCapabilities (
- 0,
- EFI_PAGE_SIZE,
- Desc.Capabilities | EFI_MEMORY_RP
- );
- ASSERT_EFI_ERROR (Status);
- }
-
- Status = CoreSetMemorySpaceAttributes (
- 0,
- EFI_PAGE_SIZE,
- Desc.Attributes & ~EFI_MEMORY_RP
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Page 0 might have be allocated to avoid misuses. Free it here anyway.
- //
- CoreFreePages (0, 1);
-
- CoreCloseEvent (Event);
- DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): end\r\n"));
-
- return;
-}
-
-/**
- Initialize Memory Protection support.
-**/
-VOID
-EFIAPI
-CoreInitializeMemoryProtection (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_EVENT Event;
- EFI_EVENT EndOfDxeEvent;
- VOID *Registration;
-
- mImageProtectionPolicy = PcdGet32 (PcdImageProtectionPolicy);
-
- InitializeListHead (&mProtectedImageRecordList);
-
- //
- // Sanity check the PcdDxeNxMemoryProtectionPolicy setting:
- // - code regions should have no EFI_MEMORY_XP attribute
- // - EfiConventionalMemory and EfiBootServicesData should use the
- // same attribute
- //
- ASSERT ((GetPermissionAttributeForMemoryType (EfiBootServicesCode) & EFI_MEMORY_XP) == 0);
- ASSERT ((GetPermissionAttributeForMemoryType (EfiRuntimeServicesCode) & EFI_MEMORY_XP) == 0);
- ASSERT ((GetPermissionAttributeForMemoryType (EfiLoaderCode) & EFI_MEMORY_XP) == 0);
- ASSERT (
- GetPermissionAttributeForMemoryType (EfiBootServicesData) ==
- GetPermissionAttributeForMemoryType (EfiConventionalMemory)
- );
-
- Status = CoreCreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- MemoryProtectionCpuArchProtocolNotify,
- NULL,
- &Event
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Register for protocol notifactions on this event
- //
- Status = CoreRegisterProtocolNotify (
- &gEfiCpuArchProtocolGuid,
- Event,
- &Registration
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Register a callback to disable NULL pointer detection at EndOfDxe
- //
- if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7))
- == (BIT0|BIT7))
- {
- Status = CoreCreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- DisableNullDetectionAtTheEndOfDxe,
- NULL,
- &gEfiEndOfDxeEventGroupGuid,
- &EndOfDxeEvent
- );
- ASSERT_EFI_ERROR (Status);
- }
-
- return;
-}
-
-/**
- Returns whether we are currently executing in SMM mode.
-**/
-STATIC
-BOOLEAN
-IsInSmm (
- VOID
- )
-{
- BOOLEAN InSmm;
-
- InSmm = FALSE;
- if (gSmmBase2 != NULL) {
- gSmmBase2->InSmm (gSmmBase2, &InSmm);
- }
-
- return InSmm;
-}
-
-/**
- Manage memory permission attributes on a memory range, according to the
- configured DXE memory protection policy.
-
- @param OldType The old memory type of the range
- @param NewType The new memory type of the range
- @param Memory The base address of the range
- @param Length The size of the range (in bytes)
-
- @return EFI_SUCCESS If we are executing in SMM mode. No permission attributes
- are updated in this case
- @return EFI_SUCCESS If the the CPU arch protocol is not installed yet
- @return EFI_SUCCESS If no DXE memory protection policy has been configured
- @return EFI_SUCCESS If OldType and NewType use the same permission attributes
- @return other Return value of gCpu->SetMemoryAttributes()
-
-**/
-EFI_STATUS
-EFIAPI
-ApplyMemoryProtectionPolicy (
- IN EFI_MEMORY_TYPE OldType,
- IN EFI_MEMORY_TYPE NewType,
- IN EFI_PHYSICAL_ADDRESS Memory,
- IN UINT64 Length
- )
-{
- UINT64 OldAttributes;
- UINT64 NewAttributes;
-
- //
- // The policy configured in PcdDxeNxMemoryProtectionPolicy
- // does not apply to allocations performed in SMM mode.
- //
- if (IsInSmm ()) {
- return EFI_SUCCESS;
- }
-
- //
- // If the CPU arch protocol is not installed yet, we cannot manage memory
- // permission attributes, and it is the job of the driver that installs this
- // protocol to set the permissions on existing allocations.
- //
- if (gCpu == NULL) {
- return EFI_SUCCESS;
- }
-
- //
- // Check if a DXE memory protection policy has been configured
- //
- if (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) == 0) {
- return EFI_SUCCESS;
- }
-
- //
- // Don't overwrite Guard pages, which should be the first and/or last page,
- // if any.
- //
- if (IsHeapGuardEnabled (GUARD_HEAP_TYPE_PAGE|GUARD_HEAP_TYPE_POOL)) {
- if (IsGuardPage (Memory)) {
- Memory += EFI_PAGE_SIZE;
- Length -= EFI_PAGE_SIZE;
- if (Length == 0) {
- return EFI_SUCCESS;
- }
- }
-
- if (IsGuardPage (Memory + Length - EFI_PAGE_SIZE)) {
- Length -= EFI_PAGE_SIZE;
- if (Length == 0) {
- return EFI_SUCCESS;
- }
- }
- }
-
- //
- // Update the executable permissions according to the DXE memory
- // protection policy, but only if
- // - the policy is different between the old and the new type, or
- // - this is a newly added region (OldType == EfiMaxMemoryType)
- //
- NewAttributes = GetPermissionAttributeForMemoryType (NewType);
-
- if (OldType != EfiMaxMemoryType) {
- OldAttributes = GetPermissionAttributeForMemoryType (OldType);
- if (OldAttributes == NewAttributes) {
- // policy is the same between OldType and NewType
- return EFI_SUCCESS;
- }
- } else if (NewAttributes == 0) {
- // newly added region of a type that does not require protection
- return EFI_SUCCESS;
- }
-
- return gCpu->SetMemoryAttributes (gCpu, Memory, Length, NewAttributes);
-}
+/** @file
+ UEFI Memory Protection support.
+
+ If the UEFI image is page aligned, the image code section is set to read only
+ and the image data section is set to non-executable.
+
+ 1) This policy is applied for all UEFI image including boot service driver,
+ runtime driver or application.
+ 2) This policy is applied only if the UEFI image meets the page alignment
+ requirement.
+ 3) This policy is applied only if the Source UEFI image matches the
+ PcdImageProtectionPolicy definition.
+ 4) This policy is not applied to the non-PE image region.
+
+ The DxeCore calls CpuArchProtocol->SetMemoryAttributes() to protect
+ the image. If the CpuArch protocol is not installed yet, the DxeCore
+ enqueues the protection request. Once the CpuArch is installed, the
+ DxeCore dequeues the protection request and applies policy.
+
+ Once the image is unloaded, the protection is removed automatically.
+
+Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/ImagePropertiesRecordLib.h>
+
+#include <Guid/EventGroup.h>
+#include <Guid/MemoryAttributesTable.h>
+
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include "DxeMain.h"
+#include "Mem/HeapGuard.h"
+
+//
+// Image type definitions
+//
+#define IMAGE_UNKNOWN 0x00000001
+#define IMAGE_FROM_FV 0x00000002
+
+//
+// Protection policy bit definition
+//
+#define DO_NOT_PROTECT 0x00000000
+#define PROTECT_IF_ALIGNED_ELSE_ALLOW 0x00000001
+
+#define MEMORY_TYPE_OS_RESERVED_MIN 0x80000000
+#define MEMORY_TYPE_OEM_RESERVED_MIN 0x70000000
+
+#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
+ ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
+
+UINT32 mImageProtectionPolicy;
+
+extern LIST_ENTRY mGcdMemorySpaceMap;
+
+STATIC LIST_ENTRY mProtectedImageRecordList;
+
+/**
+ Get the image type.
+
+ @param[in] File This is a pointer to the device path of the file that is
+ being dispatched.
+
+ @return UINT32 Image Type
+**/
+UINT32
+GetImageType (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+
+ if (File == NULL) {
+ return IMAGE_UNKNOWN;
+ }
+
+ //
+ // First check to see if File is from a Firmware Volume
+ //
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
+ Status = gBS->LocateDevicePath (
+ &gEfiFirmwareVolume2ProtocolGuid,
+ &TempDevicePath,
+ &DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ DeviceHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return IMAGE_FROM_FV;
+ }
+ }
+
+ return IMAGE_UNKNOWN;
+}
+
+/**
+ Get UEFI image protection policy based upon image type.
+
+ @param[in] ImageType The UEFI image type
+
+ @return UEFI image protection policy
+**/
+UINT32
+GetProtectionPolicyFromImageType (
+ IN UINT32 ImageType
+ )
+{
+ if ((ImageType & mImageProtectionPolicy) == 0) {
+ return DO_NOT_PROTECT;
+ } else {
+ return PROTECT_IF_ALIGNED_ELSE_ALLOW;
+ }
+}
+
+/**
+ Get UEFI image protection policy based upon loaded image device path.
+
+ @param[in] LoadedImage The loaded image protocol
+ @param[in] LoadedImageDevicePath The loaded image device path protocol
+
+ @return UEFI image protection policy
+**/
+UINT32
+GetUefiImageProtectionPolicy (
+ IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
+ IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath
+ )
+{
+ BOOLEAN InSmm;
+ UINT32 ImageType;
+ UINT32 ProtectionPolicy;
+
+ //
+ // Check SMM
+ //
+ InSmm = FALSE;
+ if (gSmmBase2 != NULL) {
+ gSmmBase2->InSmm (gSmmBase2, &InSmm);
+ }
+
+ if (InSmm) {
+ return FALSE;
+ }
+
+ //
+ // Check DevicePath
+ //
+ if (LoadedImage == gDxeCoreLoadedImage) {
+ ImageType = IMAGE_FROM_FV;
+ } else {
+ ImageType = GetImageType (LoadedImageDevicePath);
+ }
+
+ ProtectionPolicy = GetProtectionPolicyFromImageType (ImageType);
+ return ProtectionPolicy;
+}
+
+/**
+ Set UEFI image memory attributes.
+
+ @param[in] BaseAddress Specified start address
+ @param[in] Length Specified length
+ @param[in] Attributes Specified attributes
+**/
+VOID
+SetUefiImageMemoryAttributes (
+ IN UINT64 BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
+ UINT64 FinalAttributes;
+
+ Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ FinalAttributes = (Descriptor.Attributes & EFI_CACHE_ATTRIBUTE_MASK) | (Attributes & EFI_MEMORY_ATTRIBUTE_MASK);
+
+ DEBUG ((DEBUG_INFO, "SetUefiImageMemoryAttributes - 0x%016lx - 0x%016lx (0x%016lx)\n", BaseAddress, Length, FinalAttributes));
+
+ ASSERT (gCpu != NULL);
+ gCpu->SetMemoryAttributes (gCpu, BaseAddress, Length, FinalAttributes);
+}
+
+/**
+ Set UEFI image protection attributes.
+
+ @param[in] ImageRecord A UEFI image record
+**/
+VOID
+SetUefiImageProtectionAttributes (
+ IN IMAGE_PROPERTIES_RECORD *ImageRecord
+ )
+{
+ IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
+ LIST_ENTRY *ImageRecordCodeSectionLink;
+ LIST_ENTRY *ImageRecordCodeSectionEndLink;
+ LIST_ENTRY *ImageRecordCodeSectionList;
+ UINT64 CurrentBase;
+ UINT64 ImageEnd;
+
+ ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
+
+ CurrentBase = ImageRecord->ImageBase;
+ ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
+
+ ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
+ ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
+ while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
+ ImageRecordCodeSection = CR (
+ ImageRecordCodeSectionLink,
+ IMAGE_PROPERTIES_RECORD_CODE_SECTION,
+ Link,
+ IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
+ );
+ ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
+
+ ASSERT (CurrentBase <= ImageRecordCodeSection->CodeSegmentBase);
+ if (CurrentBase < ImageRecordCodeSection->CodeSegmentBase) {
+ //
+ // DATA
+ //
+ SetUefiImageMemoryAttributes (
+ CurrentBase,
+ ImageRecordCodeSection->CodeSegmentBase - CurrentBase,
+ EFI_MEMORY_XP
+ );
+ }
+
+ //
+ // CODE
+ //
+ SetUefiImageMemoryAttributes (
+ ImageRecordCodeSection->CodeSegmentBase,
+ ImageRecordCodeSection->CodeSegmentSize,
+ EFI_MEMORY_RO
+ );
+ CurrentBase = ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize;
+ }
+
+ //
+ // Last DATA
+ //
+ ASSERT (CurrentBase <= ImageEnd);
+ if (CurrentBase < ImageEnd) {
+ //
+ // DATA
+ //
+ SetUefiImageMemoryAttributes (
+ CurrentBase,
+ ImageEnd - CurrentBase,
+ EFI_MEMORY_XP
+ );
+ }
+
+ return;
+}
+
+/**
+ Return the section alignment requirement for the PE image section type.
+
+ @param[in] MemoryType PE/COFF image memory type
+
+ @retval The required section alignment for this memory type
+
+**/
+STATIC
+UINT32
+GetMemoryProtectionSectionAlignment (
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ UINT32 SectionAlignment;
+
+ switch (MemoryType) {
+ case EfiRuntimeServicesCode:
+ case EfiACPIMemoryNVS:
+ case EfiReservedMemoryType:
+ SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+ break;
+ case EfiRuntimeServicesData:
+ ASSERT (FALSE);
+ SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+ break;
+ case EfiBootServicesCode:
+ case EfiLoaderCode:
+ SectionAlignment = EFI_PAGE_SIZE;
+ break;
+ case EfiACPIReclaimMemory:
+ default:
+ ASSERT (FALSE);
+ SectionAlignment = EFI_PAGE_SIZE;
+ break;
+ }
+
+ return SectionAlignment;
+}
+
+/**
+ Protect UEFI PE/COFF image.
+
+ @param[in] LoadedImage The loaded image protocol
+ @param[in] LoadedImageDevicePath The loaded image device path protocol
+**/
+VOID
+ProtectUefiImage (
+ IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
+ IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath
+ )
+{
+ IMAGE_PROPERTIES_RECORD *ImageRecord;
+ UINT32 ProtectionPolicy;
+ EFI_STATUS Status;
+ UINT32 RequiredAlignment;
+
+ DEBUG ((DEBUG_INFO, "ProtectUefiImageCommon - 0x%x\n", LoadedImage));
+ DEBUG ((DEBUG_INFO, " - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase, LoadedImage->ImageSize));
+
+ if (gCpu == NULL) {
+ return;
+ }
+
+ ProtectionPolicy = GetUefiImageProtectionPolicy (LoadedImage, LoadedImageDevicePath);
+ switch (ProtectionPolicy) {
+ case DO_NOT_PROTECT:
+ return;
+ case PROTECT_IF_ALIGNED_ELSE_ALLOW:
+ break;
+ default:
+ ASSERT (FALSE);
+ return;
+ }
+
+ ImageRecord = AllocateZeroPool (sizeof (*ImageRecord));
+ if (ImageRecord == NULL) {
+ return;
+ }
+
+ RequiredAlignment = GetMemoryProtectionSectionAlignment (LoadedImage->ImageCodeType);
+
+ Status = CreateImagePropertiesRecord (
+ LoadedImage->ImageBase,
+ LoadedImage->ImageSize,
+ &RequiredAlignment,
+ ImageRecord
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to create image properties record\n", __func__));
+ FreePool (ImageRecord);
+ goto Finish;
+ }
+
+ //
+ // CPU ARCH present. Update memory attribute directly.
+ //
+ SetUefiImageProtectionAttributes (ImageRecord);
+
+ //
+ // Record the image record in the list so we can undo the protections later
+ //
+ InsertTailList (&mProtectedImageRecordList, &ImageRecord->Link);
+
+Finish:
+ return;
+}
+
+/**
+ Unprotect UEFI image.
+
+ @param[in] LoadedImage The loaded image protocol
+ @param[in] LoadedImageDevicePath The loaded image device path protocol
+**/
+VOID
+UnprotectUefiImage (
+ IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
+ IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath
+ )
+{
+ IMAGE_PROPERTIES_RECORD *ImageRecord;
+ LIST_ENTRY *ImageRecordLink;
+
+ if (PcdGet32 (PcdImageProtectionPolicy) != 0) {
+ for (ImageRecordLink = mProtectedImageRecordList.ForwardLink;
+ ImageRecordLink != &mProtectedImageRecordList;
+ ImageRecordLink = ImageRecordLink->ForwardLink)
+ {
+ ImageRecord = CR (
+ ImageRecordLink,
+ IMAGE_PROPERTIES_RECORD,
+ Link,
+ IMAGE_PROPERTIES_RECORD_SIGNATURE
+ );
+
+ if (ImageRecord->ImageBase == (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase) {
+ SetUefiImageMemoryAttributes (
+ ImageRecord->ImageBase,
+ ImageRecord->ImageSize,
+ 0
+ );
+ DeleteImagePropertiesRecord (ImageRecord);
+ return;
+ }
+ }
+ }
+}
+
+/**
+ Return the EFI memory permission attribute associated with memory
+ type 'MemoryType' under the configured DXE memory protection policy.
+
+ @param MemoryType Memory type.
+**/
+STATIC
+UINT64
+GetPermissionAttributeForMemoryType (
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ UINT64 TestBit;
+
+ if ((UINT32)MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) {
+ TestBit = BIT63;
+ } else if ((UINT32)MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {
+ TestBit = BIT62;
+ } else {
+ TestBit = LShiftU64 (1, MemoryType);
+ }
+
+ if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & TestBit) != 0) {
+ return EFI_MEMORY_XP;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ Sort memory map entries based upon PhysicalStart, from low to high.
+
+ @param MemoryMap A pointer to the buffer in which firmware places
+ the current memory map.
+ @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
+ @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+**/
+STATIC
+VOID
+SortMemoryMap (
+ IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ IN UINTN MemoryMapSize,
+ IN UINTN DescriptorSize
+ )
+{
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
+ EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
+ EFI_MEMORY_DESCRIPTOR TempMemoryMap;
+
+ MemoryMapEntry = MemoryMap;
+ NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+ MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
+ while (MemoryMapEntry < MemoryMapEnd) {
+ while (NextMemoryMapEntry < MemoryMapEnd) {
+ if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {
+ CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
+ CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
+ CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof (EFI_MEMORY_DESCRIPTOR));
+ }
+
+ NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
+ }
+
+ MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+ NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+ }
+}
+
+/**
+ Merge adjacent memory map entries if they use the same memory protection policy
+
+ @param[in, out] MemoryMap A pointer to the buffer in which firmware places
+ the current memory map.
+ @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
+ MemoryMap buffer. On input, this is the size of
+ the current memory map. On output,
+ it is the size of new memory map after merge.
+ @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
+**/
+STATIC
+VOID
+MergeMemoryMapForProtectionPolicy (
+ IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ IN OUT UINTN *MemoryMapSize,
+ IN UINTN DescriptorSize
+ )
+{
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
+ UINT64 MemoryBlockLength;
+ EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry;
+ EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
+ UINT64 Attributes;
+
+ SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
+
+ MemoryMapEntry = MemoryMap;
+ NewMemoryMapEntry = MemoryMap;
+ MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + *MemoryMapSize);
+ while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
+ CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
+ NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+
+ do {
+ MemoryBlockLength = (UINT64)(EFI_PAGES_TO_SIZE ((UINTN)MemoryMapEntry->NumberOfPages));
+ Attributes = GetPermissionAttributeForMemoryType (MemoryMapEntry->Type);
+
+ if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
+ (Attributes == GetPermissionAttributeForMemoryType (NextMemoryMapEntry->Type)) &&
+ ((MemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart))
+ {
+ MemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
+ if (NewMemoryMapEntry != MemoryMapEntry) {
+ NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
+ }
+
+ NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
+ continue;
+ } else {
+ MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
+ break;
+ }
+ } while (TRUE);
+
+ MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+ NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);
+ }
+
+ *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;
+
+ return;
+}
+
+/**
+ Remove exec permissions from all regions whose type is identified by
+ PcdDxeNxMemoryProtectionPolicy.
+**/
+STATIC
+VOID
+InitializeDxeNxMemoryProtectionPolicy (
+ VOID
+ )
+{
+ UINTN MemoryMapSize;
+ UINTN MapKey;
+ UINTN DescriptorSize;
+ UINT32 DescriptorVersion;
+ EFI_MEMORY_DESCRIPTOR *MemoryMap;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
+ EFI_STATUS Status;
+ UINT64 Attributes;
+ LIST_ENTRY *Link;
+ EFI_GCD_MAP_ENTRY *Entry;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
+ EFI_PHYSICAL_ADDRESS StackBase;
+
+ //
+ // Get the EFI memory map.
+ //
+ MemoryMapSize = 0;
+ MemoryMap = NULL;
+
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+ do {
+ MemoryMap = (EFI_MEMORY_DESCRIPTOR *)AllocatePool (MemoryMapSize);
+ ASSERT (MemoryMap != NULL);
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (MemoryMap);
+ }
+ } while (Status == EFI_BUFFER_TOO_SMALL);
+
+ ASSERT_EFI_ERROR (Status);
+
+ StackBase = 0;
+ if (PcdGetBool (PcdCpuStackGuard)) {
+ //
+ // Get the base of stack from Hob.
+ //
+ Hob.Raw = GetHobList ();
+ while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
+ MemoryHob = Hob.MemoryAllocation;
+ if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &MemoryHob->AllocDescriptor.Name)) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: StackBase = 0x%016lx StackSize = 0x%016lx\n",
+ __func__,
+ MemoryHob->AllocDescriptor.MemoryBaseAddress,
+ MemoryHob->AllocDescriptor.MemoryLength
+ ));
+
+ StackBase = MemoryHob->AllocDescriptor.MemoryBaseAddress;
+ //
+ // Ensure the base of the stack is page-size aligned.
+ //
+ ASSERT ((StackBase & EFI_PAGE_MASK) == 0);
+ break;
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+
+ //
+ // Ensure the base of stack can be found from Hob when stack guard is
+ // enabled.
+ //
+ ASSERT (StackBase != 0);
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: applying strict permissions to active memory regions\n",
+ __func__
+ ));
+
+ MergeMemoryMapForProtectionPolicy (MemoryMap, &MemoryMapSize, DescriptorSize);
+
+ MemoryMapEntry = MemoryMap;
+ MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
+ while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
+ Attributes = GetPermissionAttributeForMemoryType (MemoryMapEntry->Type);
+ if (Attributes != 0) {
+ SetUefiImageMemoryAttributes (
+ MemoryMapEntry->PhysicalStart,
+ LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT),
+ Attributes
+ );
+
+ //
+ // Add EFI_MEMORY_RP attribute for page 0 if NULL pointer detection is
+ // enabled.
+ //
+ if ((MemoryMapEntry->PhysicalStart == 0) &&
+ (PcdGet8 (PcdNullPointerDetectionPropertyMask) != 0))
+ {
+ ASSERT (MemoryMapEntry->NumberOfPages > 0);
+ SetUefiImageMemoryAttributes (
+ 0,
+ EFI_PAGES_TO_SIZE (1),
+ EFI_MEMORY_RP | Attributes
+ );
+ }
+
+ //
+ // Add EFI_MEMORY_RP attribute for the first page of the stack if stack
+ // guard is enabled.
+ //
+ if ((StackBase != 0) &&
+ ((StackBase >= MemoryMapEntry->PhysicalStart) &&
+ (StackBase < MemoryMapEntry->PhysicalStart +
+ LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT))) &&
+ PcdGetBool (PcdCpuStackGuard))
+ {
+ SetUefiImageMemoryAttributes (
+ StackBase,
+ EFI_PAGES_TO_SIZE (1),
+ EFI_MEMORY_RP | Attributes
+ );
+ }
+ }
+
+ MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
+ }
+
+ FreePool (MemoryMap);
+
+ //
+ // Apply the policy for RAM regions that we know are present and
+ // accessible, but have not been added to the UEFI memory map (yet).
+ //
+ if (GetPermissionAttributeForMemoryType (EfiConventionalMemory) != 0) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: applying strict permissions to inactive memory regions\n",
+ __func__
+ ));
+
+ CoreAcquireGcdMemoryLock ();
+
+ Link = mGcdMemorySpaceMap.ForwardLink;
+ while (Link != &mGcdMemorySpaceMap) {
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
+
+ if ((Entry->GcdMemoryType == EfiGcdMemoryTypeReserved) &&
+ (Entry->EndAddress < MAX_ADDRESS) &&
+ ((Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
+ (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)))
+ {
+ Attributes = GetPermissionAttributeForMemoryType (EfiConventionalMemory) |
+ (Entry->Attributes & EFI_CACHE_ATTRIBUTE_MASK);
+
+ DEBUG ((
+ DEBUG_INFO,
+ "Untested GCD memory space region: - 0x%016lx - 0x%016lx (0x%016lx)\n",
+ Entry->BaseAddress,
+ Entry->EndAddress - Entry->BaseAddress + 1,
+ Attributes
+ ));
+
+ ASSERT (gCpu != NULL);
+ gCpu->SetMemoryAttributes (
+ gCpu,
+ Entry->BaseAddress,
+ Entry->EndAddress - Entry->BaseAddress + 1,
+ Attributes
+ );
+ }
+
+ Link = Link->ForwardLink;
+ }
+
+ CoreReleaseGcdMemoryLock ();
+ }
+}
+
+/**
+ A notification for CPU_ARCH protocol.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context,
+ which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+MemoryProtectionCpuArchProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
+ UINTN NoHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+
+ DEBUG ((DEBUG_INFO, "MemoryProtectionCpuArchProtocolNotify:\n"));
+ Status = CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Apply the memory protection policy on non-BScode/RTcode regions.
+ //
+ if (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) != 0) {
+ InitializeDxeNxMemoryProtectionPolicy ();
+ }
+
+ //
+ // Call notify function meant for Heap Guard.
+ //
+ HeapGuardCpuArchProtocolNotify ();
+
+ if (mImageProtectionPolicy == 0) {
+ goto Done;
+ }
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiLoadedImageProtocolGuid,
+ NULL,
+ &NoHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) && (NoHandles == 0)) {
+ goto Done;
+ }
+
+ for (Index = 0; Index < NoHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ (VOID **)&LoadedImageDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ LoadedImageDevicePath = NULL;
+ }
+
+ ProtectUefiImage (LoadedImage, LoadedImageDevicePath);
+ }
+
+ FreePool (HandleBuffer);
+
+Done:
+ CoreCloseEvent (Event);
+}
+
+/**
+ ExitBootServices Callback function for memory protection.
+**/
+VOID
+MemoryProtectionExitBootServicesCallback (
+ VOID
+ )
+{
+ EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage;
+ LIST_ENTRY *Link;
+
+ //
+ // We need remove the RT protection, because RT relocation need write code segment
+ // at SetVirtualAddressMap(). We cannot assume OS/Loader has taken over page table at that time.
+ //
+ // Firmware does not own page tables after ExitBootServices(), so the OS would
+ // have to relax protection of RT code pages across SetVirtualAddressMap(), or
+ // delay setting protections on RT code pages until after SetVirtualAddressMap().
+ // OS may set protection on RT based upon EFI_MEMORY_ATTRIBUTES_TABLE later.
+ //
+ if (mImageProtectionPolicy != 0) {
+ for (Link = gRuntime->ImageHead.ForwardLink; Link != &gRuntime->ImageHead; Link = Link->ForwardLink) {
+ RuntimeImage = BASE_CR (Link, EFI_RUNTIME_IMAGE_ENTRY, Link);
+ SetUefiImageMemoryAttributes ((UINT64)(UINTN)RuntimeImage->ImageBase, ALIGN_VALUE (RuntimeImage->ImageSize, EFI_PAGE_SIZE), 0);
+ }
+ }
+}
+
+/**
+ Disable NULL pointer detection after EndOfDxe. This is a workaround resort in
+ order to skip unfixable NULL pointer access issues detected in OptionROM or
+ boot loaders.
+
+ @param[in] Event The Event this notify function registered to.
+ @param[in] Context Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+DisableNullDetectionAtTheEndOfDxe (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR Desc;
+
+ DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): start\r\n"));
+ //
+ // Disable NULL pointer detection by enabling first 4K page
+ //
+ Status = CoreGetMemorySpaceDescriptor (0, &Desc);
+ ASSERT_EFI_ERROR (Status);
+
+ if ((Desc.Capabilities & EFI_MEMORY_RP) == 0) {
+ Status = CoreSetMemorySpaceCapabilities (
+ 0,
+ EFI_PAGE_SIZE,
+ Desc.Capabilities | EFI_MEMORY_RP
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = CoreSetMemorySpaceAttributes (
+ 0,
+ EFI_PAGE_SIZE,
+ Desc.Attributes & ~EFI_MEMORY_RP
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Page 0 might have be allocated to avoid misuses. Free it here anyway.
+ //
+ CoreFreePages (0, 1);
+
+ CoreCloseEvent (Event);
+ DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): end\r\n"));
+
+ return;
+}
+
+/**
+ Initialize Memory Protection support.
+**/
+VOID
+EFIAPI
+CoreInitializeMemoryProtection (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+ EFI_EVENT EndOfDxeEvent;
+ VOID *Registration;
+
+ mImageProtectionPolicy = PcdGet32 (PcdImageProtectionPolicy);
+
+ InitializeListHead (&mProtectedImageRecordList);
+
+ //
+ // Sanity check the PcdDxeNxMemoryProtectionPolicy setting:
+ // - code regions should have no EFI_MEMORY_XP attribute
+ // - EfiConventionalMemory and EfiBootServicesData should use the
+ // same attribute
+ //
+ ASSERT ((GetPermissionAttributeForMemoryType (EfiBootServicesCode) & EFI_MEMORY_XP) == 0);
+ ASSERT ((GetPermissionAttributeForMemoryType (EfiRuntimeServicesCode) & EFI_MEMORY_XP) == 0);
+ ASSERT ((GetPermissionAttributeForMemoryType (EfiLoaderCode) & EFI_MEMORY_XP) == 0);
+ ASSERT (
+ GetPermissionAttributeForMemoryType (EfiBootServicesData) ==
+ GetPermissionAttributeForMemoryType (EfiConventionalMemory)
+ );
+
+ Status = CoreCreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ MemoryProtectionCpuArchProtocolNotify,
+ NULL,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for protocol notifactions on this event
+ //
+ Status = CoreRegisterProtocolNotify (
+ &gEfiCpuArchProtocolGuid,
+ Event,
+ &Registration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register a callback to disable NULL pointer detection at EndOfDxe
+ //
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7))
+ == (BIT0|BIT7))
+ {
+ Status = CoreCreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ DisableNullDetectionAtTheEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return;
+}
+
+/**
+ Returns whether we are currently executing in SMM mode.
+**/
+STATIC
+BOOLEAN
+IsInSmm (
+ VOID
+ )
+{
+ BOOLEAN InSmm;
+
+ InSmm = FALSE;
+ if (gSmmBase2 != NULL) {
+ gSmmBase2->InSmm (gSmmBase2, &InSmm);
+ }
+
+ return InSmm;
+}
+
+/**
+ Manage memory permission attributes on a memory range, according to the
+ configured DXE memory protection policy.
+
+ @param OldType The old memory type of the range
+ @param NewType The new memory type of the range
+ @param Memory The base address of the range
+ @param Length The size of the range (in bytes)
+
+ @return EFI_SUCCESS If we are executing in SMM mode. No permission attributes
+ are updated in this case
+ @return EFI_SUCCESS If the the CPU arch protocol is not installed yet
+ @return EFI_SUCCESS If no DXE memory protection policy has been configured
+ @return EFI_SUCCESS If OldType and NewType use the same permission attributes
+ @return other Return value of gCpu->SetMemoryAttributes()
+
+**/
+EFI_STATUS
+EFIAPI
+ApplyMemoryProtectionPolicy (
+ IN EFI_MEMORY_TYPE OldType,
+ IN EFI_MEMORY_TYPE NewType,
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINT64 Length
+ )
+{
+ UINT64 OldAttributes;
+ UINT64 NewAttributes;
+
+ //
+ // The policy configured in PcdDxeNxMemoryProtectionPolicy
+ // does not apply to allocations performed in SMM mode.
+ //
+ if (IsInSmm ()) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If the CPU arch protocol is not installed yet, we cannot manage memory
+ // permission attributes, and it is the job of the driver that installs this
+ // protocol to set the permissions on existing allocations.
+ //
+ if (gCpu == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Check if a DXE memory protection policy has been configured
+ //
+ if (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Don't overwrite Guard pages, which should be the first and/or last page,
+ // if any.
+ //
+ if (IsHeapGuardEnabled (GUARD_HEAP_TYPE_PAGE|GUARD_HEAP_TYPE_POOL)) {
+ if (IsGuardPage (Memory)) {
+ Memory += EFI_PAGE_SIZE;
+ Length -= EFI_PAGE_SIZE;
+ if (Length == 0) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (IsGuardPage (Memory + Length - EFI_PAGE_SIZE)) {
+ Length -= EFI_PAGE_SIZE;
+ if (Length == 0) {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ //
+ // Update the executable permissions according to the DXE memory
+ // protection policy, but only if
+ // - the policy is different between the old and the new type, or
+ // - this is a newly added region (OldType == EfiMaxMemoryType)
+ //
+ NewAttributes = GetPermissionAttributeForMemoryType (NewType);
+
+ if (OldType != EfiMaxMemoryType) {
+ OldAttributes = GetPermissionAttributeForMemoryType (OldType);
+ if (OldAttributes == NewAttributes) {
+ // policy is the same between OldType and NewType
+ return EFI_SUCCESS;
+ }
+ } else if (NewAttributes == 0) {
+ // newly added region of a type that does not require protection
+ return EFI_SUCCESS;
+ }
+
+ return gCpu->SetMemoryAttributes (gCpu, Memory, Length, NewAttributes);
+}
diff --git a/MdeModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c b/MdeModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c
index c3cabc0d36..e1b092176b 100644
--- a/MdeModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c
+++ b/MdeModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c
@@ -1,66 +1,66 @@
-/** @file
- UEFI Miscellaneous boot Services SetWatchdogTimer service implementation
-
-Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "DxeMain.h"
-
-#define WATCHDOG_TIMER_CALIBRATE_PER_SECOND 10000000
-
-/**
- Sets the system's watchdog timer.
-
- @param Timeout The number of seconds to set the watchdog timer to.
- A value of zero disables the timer.
- @param WatchdogCode The numeric code to log on a watchdog timer timeout
- event. The firmware reserves codes 0x0000 to 0xFFFF.
- Loaders and operating systems may use other timeout
- codes.
- @param DataSize The size, in bytes, of WatchdogData.
- @param WatchdogData A data buffer that includes a Null-terminated Unicode
- string, optionally followed by additional binary data.
- The string is a description that the call may use to
- further indicate the reason to be logged with a
- watchdog event.
-
- @return EFI_SUCCESS Timeout has been set
- @return EFI_NOT_AVAILABLE_YET WatchdogTimer is not available yet
- @return EFI_UNSUPPORTED System does not have a timer (currently not used)
- @return EFI_DEVICE_ERROR Could not complete due to hardware error
-
-**/
-EFI_STATUS
-EFIAPI
-CoreSetWatchdogTimer (
- IN UINTN Timeout,
- IN UINT64 WatchdogCode,
- IN UINTN DataSize,
- IN CHAR16 *WatchdogData OPTIONAL
- )
-{
- EFI_STATUS Status;
-
- //
- // Check our architectural protocol
- //
- if (gWatchdogTimer == NULL) {
- return EFI_NOT_AVAILABLE_YET;
- }
-
- //
- // Attempt to set the timeout
- //
- Status = gWatchdogTimer->SetTimerPeriod (gWatchdogTimer, MultU64x32 (Timeout, WATCHDOG_TIMER_CALIBRATE_PER_SECOND));
-
- //
- // Check for errors
- //
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- return EFI_SUCCESS;
-}
+/** @file
+ UEFI Miscellaneous boot Services SetWatchdogTimer service implementation
+
+Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "DxeMain.h"
+
+#define WATCHDOG_TIMER_CALIBRATE_PER_SECOND 10000000
+
+/**
+ Sets the system's watchdog timer.
+
+ @param Timeout The number of seconds to set the watchdog timer to.
+ A value of zero disables the timer.
+ @param WatchdogCode The numeric code to log on a watchdog timer timeout
+ event. The firmware reserves codes 0x0000 to 0xFFFF.
+ Loaders and operating systems may use other timeout
+ codes.
+ @param DataSize The size, in bytes, of WatchdogData.
+ @param WatchdogData A data buffer that includes a Null-terminated Unicode
+ string, optionally followed by additional binary data.
+ The string is a description that the call may use to
+ further indicate the reason to be logged with a
+ watchdog event.
+
+ @return EFI_SUCCESS Timeout has been set
+ @return EFI_NOT_AVAILABLE_YET WatchdogTimer is not available yet
+ @return EFI_UNSUPPORTED System does not have a timer (currently not used)
+ @return EFI_DEVICE_ERROR Could not complete due to hardware error
+
+**/
+EFI_STATUS
+EFIAPI
+CoreSetWatchdogTimer (
+ IN UINTN Timeout,
+ IN UINT64 WatchdogCode,
+ IN UINTN DataSize,
+ IN CHAR16 *WatchdogData OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Check our architectural protocol
+ //
+ if (gWatchdogTimer == NULL) {
+ return EFI_NOT_AVAILABLE_YET;
+ }
+
+ //
+ // Attempt to set the timeout
+ //
+ Status = gWatchdogTimer->SetTimerPeriod (gWatchdogTimer, MultU64x32 (Timeout, WATCHDOG_TIMER_CALIBRATE_PER_SECOND));
+
+ //
+ // Check for errors
+ //
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Core/Dxe/Misc/Stall.c b/MdeModulePkg/Core/Dxe/Misc/Stall.c
index 35e045d41a..43a272af6c 100644
--- a/MdeModulePkg/Core/Dxe/Misc/Stall.c
+++ b/MdeModulePkg/Core/Dxe/Misc/Stall.c
@@ -1,109 +1,109 @@
-/** @file
- UEFI Miscellaneous boot Services Stall service implementation
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-//
-// Include statements
-//
-
-#include "DxeMain.h"
-
-/**
- Internal worker function to call the Metronome Architectural Protocol for
- the number of ticks specified by the UINT64 Counter value. WaitForTick()
- service of the Metronome Architectural Protocol uses a UINT32 for the number
- of ticks to wait, so this function loops when Counter is larger than 0xffffffff.
-
- @param Counter Number of ticks to wait.
-
-**/
-VOID
-CoreInternalWaitForTick (
- IN UINT64 Counter
- )
-{
- while (RShiftU64 (Counter, 32) > 0) {
- gMetronome->WaitForTick (gMetronome, 0xffffffff);
- Counter -= 0xffffffff;
- }
-
- gMetronome->WaitForTick (gMetronome, (UINT32)Counter);
-}
-
-/**
- Introduces a fine-grained stall.
-
- @param Microseconds The number of microseconds to stall execution.
-
- @retval EFI_SUCCESS Execution was stalled for at least the requested
- amount of microseconds.
- @retval EFI_NOT_AVAILABLE_YET gMetronome is not available yet
-
-**/
-EFI_STATUS
-EFIAPI
-CoreStall (
- IN UINTN Microseconds
- )
-{
- UINT64 Counter;
- UINT32 Remainder;
- UINTN Index;
-
- if (gMetronome == NULL) {
- return EFI_NOT_AVAILABLE_YET;
- }
-
- //
- // Counter = Microseconds * 10 / gMetronome->TickPeriod
- // 0x1999999999999999 = (2^64 - 1) / 10
- //
- if ((UINT64)Microseconds > 0x1999999999999999ULL) {
- //
- // Microseconds is too large to multiple by 10 first. Perform the divide
- // operation first and loop 10 times to avoid 64-bit math overflow.
- //
- Counter = DivU64x32Remainder (
- Microseconds,
- gMetronome->TickPeriod,
- &Remainder
- );
- for (Index = 0; Index < 10; Index++) {
- CoreInternalWaitForTick (Counter);
- }
-
- if (Remainder != 0) {
- //
- // If Remainder was not zero, then normally, Counter would be rounded
- // up by 1 tick. In this case, since a loop for 10 counts was used
- // to emulate the multiply by 10 operation, Counter needs to be rounded
- // up by 10 counts.
- //
- CoreInternalWaitForTick (10);
- }
- } else {
- //
- // Calculate the number of ticks by dividing the number of microseconds by
- // the TickPeriod. Calculation is based on 100ns unit.
- //
- Counter = DivU64x32Remainder (
- MultU64x32 (Microseconds, 10),
- gMetronome->TickPeriod,
- &Remainder
- );
- if (Remainder != 0) {
- //
- // If Remainder is not zero, then round Counter up by one tick.
- //
- Counter++;
- }
-
- CoreInternalWaitForTick (Counter);
- }
-
- return EFI_SUCCESS;
-}
+/** @file
+ UEFI Miscellaneous boot Services Stall service implementation
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// Include statements
+//
+
+#include "DxeMain.h"
+
+/**
+ Internal worker function to call the Metronome Architectural Protocol for
+ the number of ticks specified by the UINT64 Counter value. WaitForTick()
+ service of the Metronome Architectural Protocol uses a UINT32 for the number
+ of ticks to wait, so this function loops when Counter is larger than 0xffffffff.
+
+ @param Counter Number of ticks to wait.
+
+**/
+VOID
+CoreInternalWaitForTick (
+ IN UINT64 Counter
+ )
+{
+ while (RShiftU64 (Counter, 32) > 0) {
+ gMetronome->WaitForTick (gMetronome, 0xffffffff);
+ Counter -= 0xffffffff;
+ }
+
+ gMetronome->WaitForTick (gMetronome, (UINT32)Counter);
+}
+
+/**
+ Introduces a fine-grained stall.
+
+ @param Microseconds The number of microseconds to stall execution.
+
+ @retval EFI_SUCCESS Execution was stalled for at least the requested
+ amount of microseconds.
+ @retval EFI_NOT_AVAILABLE_YET gMetronome is not available yet
+
+**/
+EFI_STATUS
+EFIAPI
+CoreStall (
+ IN UINTN Microseconds
+ )
+{
+ UINT64 Counter;
+ UINT32 Remainder;
+ UINTN Index;
+
+ if (gMetronome == NULL) {
+ return EFI_NOT_AVAILABLE_YET;
+ }
+
+ //
+ // Counter = Microseconds * 10 / gMetronome->TickPeriod
+ // 0x1999999999999999 = (2^64 - 1) / 10
+ //
+ if ((UINT64)Microseconds > 0x1999999999999999ULL) {
+ //
+ // Microseconds is too large to multiple by 10 first. Perform the divide
+ // operation first and loop 10 times to avoid 64-bit math overflow.
+ //
+ Counter = DivU64x32Remainder (
+ Microseconds,
+ gMetronome->TickPeriod,
+ &Remainder
+ );
+ for (Index = 0; Index < 10; Index++) {
+ CoreInternalWaitForTick (Counter);
+ }
+
+ if (Remainder != 0) {
+ //
+ // If Remainder was not zero, then normally, Counter would be rounded
+ // up by 1 tick. In this case, since a loop for 10 counts was used
+ // to emulate the multiply by 10 operation, Counter needs to be rounded
+ // up by 10 counts.
+ //
+ CoreInternalWaitForTick (10);
+ }
+ } else {
+ //
+ // Calculate the number of ticks by dividing the number of microseconds by
+ // the TickPeriod. Calculation is based on 100ns unit.
+ //
+ Counter = DivU64x32Remainder (
+ MultU64x32 (Microseconds, 10),
+ gMetronome->TickPeriod,
+ &Remainder
+ );
+ if (Remainder != 0) {
+ //
+ // If Remainder is not zero, then round Counter up by one tick.
+ //
+ Counter++;
+ }
+
+ CoreInternalWaitForTick (Counter);
+ }
+
+ return EFI_SUCCESS;
+}