/** @file\r
SMM IPL that produces SMM related runtime protocols and load the SMM Core into SMRAM\r
\r
- Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2009 - 2011, 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
#include <Protocol/SmmConfiguration.h>\r
#include <Protocol/SmmControl2.h>\r
#include <Protocol/DxeSmmReadyToLock.h>\r
-#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/Cpu.h>\r
\r
#include <Guid/EventGroup.h>\r
#include <Guid/EventLegacyBios.h>\r
#include <Library/DebugLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/DxeServicesTableLib.h>\r
+#include <Library/DxeServicesLib.h>\r
#include <Library/UefiLib.h>\r
#include <Library/UefiRuntimeLib.h>\r
#include <Library/PcdLib.h>\r
FALSE, // SmmEntryPointRegistered\r
FALSE, // InSmm\r
NULL, // Smst\r
- 0, // BufferSize\r
NULL, // CommunicationBuffer\r
+ 0, // BufferSize\r
EFI_SUCCESS // ReturnStatus\r
};\r
\r
EFI_SMM_ACCESS2_PROTOCOL *mSmmAccess;\r
EFI_SMRAM_DESCRIPTOR *mCurrentSmramRange;\r
BOOLEAN mSmmLocked = FALSE;\r
+EFI_PHYSICAL_ADDRESS mSmramCacheBase;\r
+UINT64 mSmramCacheSize;\r
\r
//\r
// Table of Protocol notification and GUIDed Event notifications that the SMM IPL requires\r
{ FALSE, FALSE, NULL, NULL, NULL, NULL }\r
};\r
\r
+/**\r
+ Find the maximum SMRAM cache range that covers the range specified by SmramRange.\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
+ @param SmramCacheBase The returned cache range base.\r
+ @param SmramCacheSize The returned cache range size.\r
+\r
+**/\r
+VOID\r
+GetSmramCacheRange (\r
+ IN EFI_SMRAM_DESCRIPTOR *SmramRange,\r
+ OUT EFI_PHYSICAL_ADDRESS *SmramCacheBase,\r
+ OUT UINT64 *SmramCacheSize\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_PHYSICAL_ADDRESS RangeCpuStart;\r
+ UINT64 RangePhysicalSize;\r
+ BOOLEAN FoundAjacentRange;\r
+\r
+ *SmramCacheBase = SmramRange->CpuStart;\r
+ *SmramCacheSize = SmramRange->PhysicalSize;\r
+\r
+ do {\r
+ FoundAjacentRange = FALSE;\r
+ for (Index = 0; Index < gSmmCorePrivate->SmramRangeCount; Index++) {\r
+ RangeCpuStart = gSmmCorePrivate->SmramRanges[Index].CpuStart;\r
+ RangePhysicalSize = gSmmCorePrivate->SmramRanges[Index].PhysicalSize;\r
+ if (RangeCpuStart < *SmramCacheBase && *SmramCacheBase == (RangeCpuStart + RangePhysicalSize)) {\r
+ *SmramCacheBase = RangeCpuStart;\r
+ *SmramCacheSize += RangePhysicalSize;\r
+ FoundAjacentRange = TRUE;\r
+ } else if ((*SmramCacheBase + *SmramCacheSize) == RangeCpuStart && RangePhysicalSize > 0) {\r
+ *SmramCacheSize += RangePhysicalSize;\r
+ FoundAjacentRange = TRUE;\r
+ }\r
+ }\r
+ } while (FoundAjacentRange);\r
+ \r
+}\r
+\r
/**\r
Indicate whether the driver is currently executing in the SMM Initialization phase.\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ //\r
+ // CommSize must hold HeaderGuid and MessageLength\r
+ //\r
+ if (*CommSize < OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
//\r
// If not already in SMM, then generate a Software SMI\r
//\r
// Put arguments for Software SMI in gSmmCorePrivate\r
//\r
gSmmCorePrivate->CommunicationBuffer = CommBuffer;\r
- gSmmCorePrivate->BufferSize = CommSize;\r
+ gSmmCorePrivate->BufferSize = *CommSize;\r
\r
//\r
// Generate Software SMI\r
//\r
// Return status from software SMI \r
//\r
+ *CommSize = gSmmCorePrivate->BufferSize;\r
return gSmmCorePrivate->ReturnStatus;\r
}\r
\r
}\r
\r
//\r
- // Don't allow call SmiManage() directly when SMRAM is closed or locked.\r
+ // If we are not in SMM, don't allow call SmiManage() directly when SMRAM is closed or locked.\r
//\r
- if (!mSmmAccess->OpenState || mSmmAccess->LockState) {\r
+ if ((!gSmmCorePrivate->InSmm) && (!mSmmAccess->OpenState || mSmmAccess->LockState)) {\r
return EFI_INVALID_PARAMETER;\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
- mCurrentSmramRange->CpuStart, \r
- mCurrentSmramRange->PhysicalSize,\r
+ mSmramCacheBase, \r
+ mSmramCacheSize,\r
EFI_MEMORY_UC\r
);\r
if (EFI_ERROR (Status)) {\r
EfiConvertPointer (0x0, (VOID **)&mSmmControl2);\r
}\r
\r
-/**\r
- Searches all Firmware Volumes for the first file matching FileType and SectionType and returns the section data.\r
-\r
- @param FileType FileType to search for within any of the firmware volumes in the platform.\r
- @param SectionType SectionType to search for within any of the matching FileTypes in the firmware volumes in the platform.\r
- @param SourceSize Return the size of the returned section data..\r
-\r
- @retval != NULL Pointer to the allocated buffer containing the section data.\r
- @retval NULL Section data was not found.\r
-\r
-**/\r
-VOID *\r
-GetSectionInAnyFv (\r
- IN EFI_FV_FILETYPE FileType,\r
- IN EFI_SECTION_TYPE SectionType,\r
- OUT UINTN *SourceSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN HandleCount;\r
- EFI_HANDLE *HandleBuffer;\r
- UINTN Index;\r
- EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
- UINTN Key;\r
- EFI_GUID NameGuid;\r
- EFI_FV_FILE_ATTRIBUTES Attributes;\r
- VOID *SourceBuffer;\r
- UINT32 AuthenticationStatus;\r
-\r
- HandleBuffer = NULL;\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- NULL,\r
- &HandleCount,\r
- &HandleBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return NULL;\r
- }\r
-\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- Status = gBS->HandleProtocol (\r
- HandleBuffer[Index],\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- (VOID **)&Fv\r
- );\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- //\r
- // Use Firmware Volume 2 Protocol to search for a file of type FileType\r
- //\r
- Key = 0; \r
- Status = Fv->GetNextFile (Fv, &Key, &FileType, &NameGuid, &Attributes, SourceSize);\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- //\r
- // Use Firmware Volume 2 Protocol to read a section of type SectionType\r
- //\r
- SourceBuffer = NULL;\r
- Status = Fv->ReadSection (Fv, &NameGuid, SectionType, 0, &SourceBuffer, SourceSize, &AuthenticationStatus);\r
- if (!EFI_ERROR (Status)) {\r
- FreePool (HandleBuffer);\r
- return SourceBuffer;\r
- }\r
- } \r
-\r
- FreePool(HandleBuffer);\r
- \r
- return NULL;\r
-}\r
/**\r
Get the fixed loadding address from image header assigned by build tool. This function only be called\r
when Loading module at Fixed address feature enabled.\r
//\r
// Search all Firmware Volumes for a PE/COFF image in a file of type SMM_CORE\r
// \r
- SourceBuffer = GetSectionInAnyFv (EFI_FV_FILETYPE_SMM_CORE, EFI_SECTION_PE32, &SourceSize);\r
- if (SourceBuffer == NULL) {\r
- return EFI_NOT_FOUND;\r
+ Status = GetSectionFromAnyFvByFileType (\r
+ EFI_FV_FILETYPE_SMM_CORE, \r
+ 0,\r
+ EFI_SECTION_PE32, \r
+ 0,\r
+ &SourceBuffer, \r
+ &SourceSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
//\r
EFI_SMM_RESERVED_SMRAM_REGION *SmramResRegion;\r
UINT64 MaxSize;\r
VOID *Registration;\r
- UINT64 SmmCodeSize;\r
+ UINT64 SmmCodeSize;\r
EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE *LMFAConfigurationTable;\r
+ EFI_CPU_ARCH_PROTOCOL *CpuArch;\r
\r
//\r
// Fill in the image handle of the SMM IPL so the SMM Core can use this as the \r
//\r
mCurrentSmramRange = NULL;\r
for (Index = 0, MaxSize = SIZE_256KB - EFI_PAGE_SIZE; Index < gSmmCorePrivate->SmramRangeCount; Index++) {\r
+ //\r
+ // Skip any SMRAM region that is already allocated, needs testing, or needs ECC initialization\r
+ //\r
+ if ((gSmmCorePrivate->SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {\r
+ continue;\r
+ }\r
+\r
if (gSmmCorePrivate->SmramRanges[Index].CpuStart >= BASE_1MB) {\r
if ((gSmmCorePrivate->SmramRanges[Index].CpuStart + gSmmCorePrivate->SmramRanges[Index].PhysicalSize) <= BASE_4GB) {\r
if (gSmmCorePrivate->SmramRanges[Index].PhysicalSize >= MaxSize) {\r
(VOID *)(UINTN)(mCurrentSmramRange->CpuStart + mCurrentSmramRange->PhysicalSize - 1)\r
));\r
\r
+ GetSmramCacheRange (mCurrentSmramRange, &mSmramCacheBase, &mSmramCacheSize);\r
//\r
- // Attempt to set SMRAM cacheability to WB\r
+ // If CPU AP is present, attempt to set SMRAM cacheability to WB\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
- Status = gDS->SetMemorySpaceAttributes(\r
- mCurrentSmramRange->CpuStart, \r
- mCurrentSmramRange->PhysicalSize,\r
- EFI_MEMORY_WB\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_WARN, "SMM IPL failed to set SMRAM window to EFI_MEMORY_WB\n"));\r
- } \r
+ CpuArch = NULL;\r
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&CpuArch);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gDS->SetMemorySpaceAttributes(\r
+ mSmramCacheBase, \r
+ mSmramCacheSize,\r
+ EFI_MEMORY_WB\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
// if Loading module at Fixed Address feature is enabled, save the SMRAM base to Load\r
// Modules At Fixed Address Configuration Table.\r
);\r
if (!EFI_ERROR (Status) && LMFAConfigurationTable != NULL) {\r
LMFAConfigurationTable->SmramBase = mCurrentSmramRange->CpuStart;\r
+ //\r
+ // Print the SMRAM base\r
+ //\r
+ DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: TSEG BASE is %x. \n", LMFAConfigurationTable->SmramBase));\r
}\r
- //\r
- // Print the SMRAM base\r
- //\r
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: TSEG BASE is %x. \n", LMFAConfigurationTable->SmramBase));\r
}\r
//\r
// Load SMM Core into SMRAM and execute it from SMRAM\r
//\r
// Attempt to reset SMRAM cacheability to UC\r
//\r
- Status = gDS->SetMemorySpaceAttributes(\r
- mCurrentSmramRange->CpuStart, \r
- mCurrentSmramRange->PhysicalSize,\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
+ if (CpuArch != NULL) {\r
+ Status = gDS->SetMemorySpaceAttributes(\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
} else {\r
//\r