/** @file\r
SMM IPL that produces SMM related runtime protocols and load the SMM Core into SMRAM\r
\r
- Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials are licensed and made available \r
- under the terms and conditions of the BSD License which accompanies this \r
- distribution. The full text of the license may be found at \r
- http://opensource.org/licenses/bsd-license.php \r
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
**/\r
\r
\r
#include "PiSmmCorePrivateData.h"\r
\r
+#define SMRAM_CAPABILITIES (EFI_MEMORY_WB | EFI_MEMORY_UC)\r
+\r
+#define MEMORY_CACHE_ATTRIBUTES (EFI_MEMORY_UC | EFI_MEMORY_WC | \\r
+ EFI_MEMORY_WT | EFI_MEMORY_WB | \\r
+ EFI_MEMORY_WP | EFI_MEMORY_UCE)\r
+\r
+#define MEMORY_PAGE_ATTRIBUTES (EFI_MEMORY_XP | EFI_MEMORY_RP | EFI_MEMORY_RO)\r
+\r
//\r
// Function prototypes from produced protocols\r
//\r
\r
/**\r
Communicates with a registered handler.\r
- \r
- This function provides a service to send and receive messages from a registered \r
- UEFI service. This function is part of the SMM Communication Protocol that may \r
- be called in physical mode prior to SetVirtualAddressMap() and in virtual mode \r
+\r
+ This function provides a service to send and receive messages from a registered\r
+ UEFI service. This function is part of the SMM Communication Protocol that may\r
+ be called in physical mode prior to SetVirtualAddressMap() and in virtual mode\r
after SetVirtualAddressMap().\r
\r
@param[in] This The EFI_SMM_COMMUNICATION_PROTOCOL instance.\r
);\r
\r
//\r
-// Data structure used to declare a table of protocol notifications and event \r
+// Data structure used to declare a table of protocol notifications and event\r
// notifications required by the SMM IPL\r
//\r
typedef struct {\r
SMM_IPL_EVENT_NOTIFICATION mSmmIplEvents[] = {\r
//\r
// Declare protocol notification on the SMM Configuration protocol. When this notification is established,\r
- // the associated event is immediately signalled, so the notification function will be executed and the \r
+ // the associated event is immediately signalled, so the notification function will be executed and the\r
// SMM Configuration Protocol will be found if it is already in the handle database.\r
//\r
{ TRUE, FALSE, &gEfiSmmConfigurationProtocolGuid, SmmIplSmmConfigurationEventNotify, &gEfiSmmConfigurationProtocolGuid, TPL_NOTIFY, NULL },\r
//\r
- // Declare protocol notification on DxeSmmReadyToLock protocols. When this notification is established, \r
- // the associated event is immediately signalled, so the notification function will be executed and the \r
+ // Declare protocol notification on DxeSmmReadyToLock protocols. When this notification is established,\r
+ // the associated event is immediately signalled, so the notification function will be executed and the\r
// DXE SMM Ready To Lock Protocol will be found if it is already in the handle database.\r
//\r
{ TRUE, TRUE, &gEfiDxeSmmReadyToLockProtocolGuid, SmmIplReadyToLockEventNotify, &gEfiDxeSmmReadyToLockProtocolGuid, TPL_CALLBACK, NULL },\r
//\r
// Declare event notification on EndOfDxe event. When this notification is established,\r
- // the associated event is immediately signalled, so the notification function will be executed and the \r
+ // the associated event is immediately signalled, so the notification function will be executed and the\r
// SMM End Of Dxe Protocol will be found if it is already in the handle database.\r
//\r
{ FALSE, TRUE, &gEfiEndOfDxeEventGroupGuid, SmmIplGuidedEventNotify, &gEfiEndOfDxeEventGroupGuid, TPL_CALLBACK, NULL },\r
//\r
{ FALSE, TRUE, &gEfiEventReadyToBootGuid, SmmIplReadyToLockEventNotify, &gEfiEventReadyToBootGuid, TPL_CALLBACK, NULL },\r
//\r
- // Declare event notification on Legacy Boot Event Group. This is used to inform the SMM Core that the platform \r
- // is performing a legacy boot operation, and that the UEFI environment is no longer available and the SMM Core \r
+ // Declare event notification on Legacy Boot Event Group. This is used to inform the SMM Core that the platform\r
+ // is performing a legacy boot operation, and that the UEFI environment is no longer available and the SMM Core\r
// must guarantee that it does not access any UEFI related structures outside of SMRAM.\r
// It is also to inform the SMM Core to notify SMM driver that system enter legacy boot.\r
//\r
//\r
{ FALSE, FALSE, &gEfiEventReadyToBootGuid, SmmIplGuidedEventNotify, &gEfiEventReadyToBootGuid, TPL_CALLBACK, NULL },\r
//\r
- // Declare event notification on SetVirtualAddressMap() Event Group. This is used to convert gSmmCorePrivate \r
+ // Declare event notification on SetVirtualAddressMap() Event Group. This is used to convert gSmmCorePrivate\r
// and mSmmControl2 from physical addresses to virtual addresses.\r
//\r
{ FALSE, FALSE, &gEfiEventVirtualAddressChangeGuid, SmmIplSetVirtualAddressNotify, NULL, TPL_CALLBACK, NULL },\r
\r
/**\r
Find the maximum SMRAM cache range that covers the range specified by SmramRange.\r
- \r
+\r
This function searches and joins all adjacent ranges of SmramRange into a range to be cached.\r
\r
@param SmramRange The SMRAM range to search from.\r
}\r
}\r
} while (FoundAjacentRange);\r
- \r
+\r
}\r
\r
/**\r
if ((This == NULL) ||(Smst == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
if (!gSmmCorePrivate->InSmm) {\r
return EFI_UNSUPPORTED;\r
}\r
- \r
+\r
*Smst = gSmmCorePrivate->Smst;\r
\r
return EFI_SUCCESS;\r
\r
/**\r
Communicates with a registered handler.\r
- \r
- This function provides a service to send and receive messages from a registered \r
- UEFI service. This function is part of the SMM Communication Protocol that may \r
- be called in physical mode prior to SetVirtualAddressMap() and in virtual mode \r
+\r
+ This function provides a service to send and receive messages from a registered\r
+ UEFI service. This function is part of the SMM Communication Protocol that may\r
+ be called in physical mode prior to SetVirtualAddressMap() and in virtual mode\r
after SetVirtualAddressMap().\r
\r
@param[in] This The EFI_SMM_COMMUNICATION_PROTOCOL instance.\r
}\r
\r
//\r
- // Return status from software SMI \r
+ // Return status from software SMI\r
//\r
if (CommSize != NULL) {\r
*CommSize = gSmmCorePrivate->BufferSize;\r
if ((!gSmmCorePrivate->InSmm) && (!mSmmAccess->OpenState || mSmmAccess->LockState)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
//\r
// Save current InSmm state and set InSmm state to TRUE\r
//\r
//\r
TempCommSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
Status = gSmmCorePrivate->Smst->SmiManage (\r
- &CommunicateHeader->HeaderGuid, \r
- NULL, \r
- CommunicateHeader->Data, \r
+ &CommunicateHeader->HeaderGuid,\r
+ NULL,\r
+ CommunicateHeader->Data,\r
&TempCommSize\r
);\r
TempCommSize += OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
UINTN Size;\r
\r
//\r
- // Use Guid to initialize EFI_SMM_COMMUNICATE_HEADER structure \r
+ // Use Guid to initialize EFI_SMM_COMMUNICATE_HEADER structure\r
//\r
CopyGuid (&mCommunicateHeader.HeaderGuid, (EFI_GUID *)Context);\r
mCommunicateHeader.MessageLength = 1;\r
//\r
Size = sizeof (mCommunicateHeader);\r
SmmCommunicationCommunicate (&mSmmCommunication, &mCommunicateHeader, &Size);\r
- \r
+\r
//\r
// Return if there is no request to restart the SMM Core Dispatcher\r
//\r
if (mCommunicateHeader.Data[0] != COMM_BUFFER_SMM_DISPATCH_RESTART) {\r
return;\r
}\r
- \r
+\r
//\r
// Attempt to reset SMRAM cacheability to UC\r
// Assume CPU AP is available at this time\r
//\r
Status = gDS->SetMemorySpaceAttributes(\r
- mSmramCacheBase, \r
+ mSmramCacheBase,\r
mSmramCacheSize,\r
EFI_MEMORY_UC\r
);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_WARN, "SMM IPL failed to reset SMRAM window to EFI_MEMORY_UC\n"));\r
- } \r
+ }\r
\r
//\r
// Close all SMRAM ranges to protect SMRAM\r
ASSERT_EFI_ERROR (Status);\r
\r
//\r
- // Set flag to indicate that the SMM Entry Point has been registered which \r
+ // Set flag to indicate that the SMM Entry Point has been registered which\r
// means that SMIs are now fully operational.\r
//\r
gSmmCorePrivate->SmmEntryPointRegistered = TRUE;\r
if (mSmmLocked) {\r
return;\r
}\r
- \r
+\r
//\r
// Make sure this notification is for this handler\r
//\r
}\r
} else {\r
//\r
- // If SMM is not locked yet and we got here from gEfiEventReadyToBootGuid being \r
+ // If SMM is not locked yet and we got here from gEfiEventReadyToBootGuid being\r
// signaled, then gEfiDxeSmmReadyToLockProtocolGuid was not installed as expected.\r
// Print a warning on debug builds.\r
//\r
// Lock the SMRAM (Note: Locking SMRAM may not be supported on all platforms)\r
//\r
mSmmAccess->Lock (mSmmAccess);\r
- \r
+\r
//\r
- // Close protocol and event notification events that do not apply after the \r
- // DXE SMM Ready To Lock Protocol has been installed or the Ready To Boot \r
+ // Close protocol and event notification events that do not apply after the\r
+ // DXE SMM Ready To Lock Protocol has been installed or the Ready To Boot\r
// event has been signalled.\r
//\r
for (Index = 0; mSmmIplEvents[Index].NotifyFunction != NULL; Index++) {\r
// Print debug message that the SMRAM window is now locked.\r
//\r
DEBUG ((DEBUG_INFO, "SMM IPL locked SMRAM window\n"));\r
- \r
+\r
//\r
// Set flag so this operation will not be performed again\r
//\r
// Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber\r
//\r
SmmCodeSize = EFI_PAGES_TO_SIZE (PcdGet32(PcdLoadFixAddressSmmCodePageNumber));\r
- \r
+\r
FixLoadingAddress = 0;\r
Status = EFI_NOT_FOUND;\r
SmramBase = mLMFAConfigurationTable->SmramBase;\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- \r
+\r
Status = EFI_NOT_FOUND;\r
- \r
+\r
if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
//\r
// Build tool saves the offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields in the\r
/**\r
Load the SMM Core image into SMRAM and executes the SMM Core from SMRAM.\r
\r
- @param[in, out] SmramRange Descriptor for the range of SMRAM to reload the \r
+ @param[in, out] SmramRange Descriptor for the range of SMRAM to reload the\r
currently executing image, the rang of SMRAM to\r
hold SMM Core will be excluded.\r
@param[in, out] SmramRangeSmmCore Descriptor for the range of SMRAM to hold SMM Core.\r
\r
//\r
// Search all Firmware Volumes for a PE/COFF image in a file of type SMM_CORE\r
- // \r
+ //\r
Status = GetSectionFromAnyFvByFileType (\r
- EFI_FV_FILETYPE_SMM_CORE, \r
+ EFI_FV_FILETYPE_SMM_CORE,\r
0,\r
- EFI_SECTION_PE32, \r
+ EFI_SECTION_PE32,\r
0,\r
- &SourceBuffer, \r
+ &SourceBuffer,\r
&SourceSize\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- \r
+\r
//\r
// Initilize ImageContext\r
//\r
return Status;\r
}\r
//\r
- // if Loading module at Fixed Address feature is enabled, the SMM core driver will be loaded to \r
+ // if Loading module at Fixed Address feature is enabled, the SMM core driver will be loaded to\r
// the address assigned by build tool.\r
//\r
if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
} else {\r
DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR: Loading module at fixed address at address failed\n"));\r
//\r
- // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR \r
+ // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR\r
// specified by SmramRange\r
//\r
PageCount = (UINTN)EFI_SIZE_TO_PAGES((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);\r
}\r
} else {\r
//\r
- // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR \r
+ // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR\r
// specified by SmramRange\r
//\r
PageCount = (UINTN)EFI_SIZE_TO_PAGES((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);\r
//\r
ImageContext.ImageAddress = SmramRangeSmmCore->CpuStart;\r
}\r
- \r
+\r
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);\r
\r
/**\r
The Entry Point for SMM IPL\r
\r
- Load SMM Core into SMRAM, register SMM Core entry point for SMIs, install \r
- SMM Base 2 Protocol and SMM Communication Protocol, and register for the \r
+ Load SMM Core into SMRAM, register SMM Core entry point for SMIs, install\r
+ SMM Base 2 Protocol and SMM Communication Protocol, and register for the\r
critical events required to coordinate between DXE and SMM environments.\r
- \r
+\r
@param ImageHandle The firmware allocated handle for the EFI image.\r
@param SystemTable A pointer to the EFI System Table.\r
\r
EFI_CPU_ARCH_PROTOCOL *CpuArch;\r
EFI_STATUS SetAttrStatus;\r
EFI_SMRAM_DESCRIPTOR *SmramRangeSmmDriver;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc;\r
\r
//\r
- // Fill in the image handle of the SMM IPL so the SMM Core can use this as the \r
- // ParentImageHandle field of the Load Image Protocol for all SMM Drivers loaded \r
+ // Fill in the image handle of the SMM IPL so the SMM Core can use this as the\r
+ // ParentImageHandle field of the Load Image Protocol for all SMM Drivers loaded\r
// by the SMM Core\r
//\r
mSmmCorePrivateData.SmmIplImageHandle = ImageHandle;\r
// Print debug message that the SMRAM window is now open.\r
//\r
DEBUG ((DEBUG_INFO, "SMM IPL opened SMRAM window\n"));\r
- \r
+\r
//\r
// Find the largest SMRAM range between 1MB and 4GB that is at least 256KB - 4K in size\r
//\r
//\r
// Print debug message showing SMRAM window that will be used by SMM IPL and SMM Core\r
//\r
- DEBUG ((DEBUG_INFO, "SMM IPL found SMRAM window %p - %p\n", \r
- (VOID *)(UINTN)mCurrentSmramRange->CpuStart, \r
+ DEBUG ((DEBUG_INFO, "SMM IPL found SMRAM window %p - %p\n",\r
+ (VOID *)(UINTN)mCurrentSmramRange->CpuStart,\r
(VOID *)(UINTN)(mCurrentSmramRange->CpuStart + mCurrentSmramRange->PhysicalSize - 1)\r
));\r
\r
GetSmramCacheRange (mCurrentSmramRange, &mSmramCacheBase, &mSmramCacheSize);\r
//\r
- // If CPU AP is present, attempt to set SMRAM cacheability to WB\r
+ // Make sure we can change the desired memory attributes.\r
+ //\r
+ Status = gDS->GetMemorySpaceDescriptor (\r
+ mSmramCacheBase,\r
+ &MemDesc\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ if ((MemDesc.Capabilities & SMRAM_CAPABILITIES) != SMRAM_CAPABILITIES) {\r
+ gDS->SetMemorySpaceCapabilities (\r
+ mSmramCacheBase,\r
+ mSmramCacheSize,\r
+ MemDesc.Capabilities | SMRAM_CAPABILITIES\r
+ );\r
+ }\r
+ //\r
+ // If CPU AP is present, attempt to set SMRAM cacheability to WB and clear\r
+ // all paging attributes.\r
// Note that it is expected that cacheability of SMRAM has been set to WB if CPU AP\r
// is not available here.\r
//\r
CpuArch = NULL;\r
Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&CpuArch);\r
if (!EFI_ERROR (Status)) {\r
- Status = gDS->SetMemorySpaceAttributes(\r
- mSmramCacheBase, \r
+ MemDesc.Attributes &= ~(MEMORY_CACHE_ATTRIBUTES | MEMORY_PAGE_ATTRIBUTES);\r
+ MemDesc.Attributes |= EFI_MEMORY_WB;\r
+ Status = gDS->SetMemorySpaceAttributes (\r
+ mSmramCacheBase,\r
mSmramCacheSize,\r
- EFI_MEMORY_WB\r
+ MemDesc.Attributes\r
);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_WARN, "SMM IPL failed to set SMRAM window to EFI_MEMORY_WB\n"));\r
- } \r
+ }\r
+\r
+ DEBUG_CODE (\r
+ gDS->GetMemorySpaceDescriptor (\r
+ mSmramCacheBase,\r
+ &MemDesc\r
+ );\r
+ DEBUG ((DEBUG_INFO, "SMRAM attributes: %016lx\n", MemDesc.Attributes));\r
+ ASSERT ((MemDesc.Attributes & MEMORY_PAGE_ATTRIBUTES) == 0);\r
+ );\r
}\r
//\r
// if Loading module at Fixed Address feature is enabled, save the SMRAM base to Load\r
//\r
if (CpuArch != NULL) {\r
SetAttrStatus = gDS->SetMemorySpaceAttributes(\r
- mSmramCacheBase, \r
+ mSmramCacheBase,\r
mSmramCacheSize,\r
EFI_MEMORY_UC\r
);\r
if (EFI_ERROR (SetAttrStatus)) {\r
DEBUG ((DEBUG_WARN, "SMM IPL failed to reset SMRAM window to EFI_MEMORY_UC\n"));\r
- } \r
+ }\r
}\r
}\r
} else {\r
}\r
\r
//\r
- // If the SMM Core could not be loaded then close SMRAM window, free allocated \r
+ // If the SMM Core could not be loaded then close SMRAM window, free allocated\r
// resources, and return an error so SMM IPL will be unloaded.\r
//\r
if (mCurrentSmramRange == NULL || EFI_ERROR (Status)) {\r
\r
return EFI_UNSUPPORTED;\r
}\r
- \r
+\r
//\r
// Install SMM Base2 Protocol and SMM Communication Protocol\r
//\r