/**\r
Load the SMM Core image into SMRAM and executes the SMM Core from SMRAM.\r
\r
- @param[in] SmramRange Descriptor for the range of SMRAM to reload the \r
- currently executing image.\r
- @param[in] Context Context to pass into SMM Core\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
+ @param[in] Context Context to pass into SMM Core\r
\r
@return EFI_STATUS\r
\r
**/\r
EFI_STATUS\r
ExecuteSmmCoreFromSmram (\r
- IN EFI_SMRAM_DESCRIPTOR *SmramRange,\r
- IN VOID *Context\r
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramRange,\r
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramRangeSmmCore,\r
+ IN VOID *Context\r
)\r
{\r
EFI_STATUS Status;\r
UINTN SourceSize;\r
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
UINTN PageCount;\r
- EFI_PHYSICAL_ADDRESS DestinationBuffer;\r
EFI_IMAGE_ENTRY_POINT EntryPoint;\r
\r
//\r
// Since the memory range to load SMM CORE will be cut out in SMM core, so no need to allocate and free this range\r
//\r
PageCount = 0;\r
- } else {\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
ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));\r
\r
SmramRange->PhysicalSize -= EFI_PAGES_TO_SIZE (PageCount);\r
- DestinationBuffer = SmramRange->CpuStart + SmramRange->PhysicalSize;\r
+ SmramRangeSmmCore->CpuStart = SmramRange->CpuStart + SmramRange->PhysicalSize;\r
+ SmramRangeSmmCore->PhysicalStart = SmramRange->PhysicalStart + SmramRange->PhysicalSize;\r
+ SmramRangeSmmCore->RegionState = SmramRange->RegionState | EFI_ALLOCATED;\r
+ SmramRangeSmmCore->PhysicalSize = EFI_PAGES_TO_SIZE (PageCount);\r
\r
//\r
- // Align buffer on section boundry\r
+ // Align buffer on section boundary\r
//\r
- ImageContext.ImageAddress = DestinationBuffer;\r
+ ImageContext.ImageAddress = SmramRangeSmmCore->CpuStart;\r
}\r
} else {\r
//\r
ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));\r
\r
SmramRange->PhysicalSize -= EFI_PAGES_TO_SIZE (PageCount);\r
- DestinationBuffer = SmramRange->CpuStart + SmramRange->PhysicalSize;\r
+ SmramRangeSmmCore->CpuStart = SmramRange->CpuStart + SmramRange->PhysicalSize;\r
+ SmramRangeSmmCore->PhysicalStart = SmramRange->PhysicalStart + SmramRange->PhysicalSize;\r
+ SmramRangeSmmCore->RegionState = SmramRange->RegionState | EFI_ALLOCATED;\r
+ SmramRangeSmmCore->PhysicalSize = EFI_PAGES_TO_SIZE (PageCount);\r
\r
//\r
- // Align buffer on section boundry\r
+ // Align buffer on section boundary\r
//\r
- ImageContext.ImageAddress = DestinationBuffer;\r
+ ImageContext.ImageAddress = SmramRangeSmmCore->CpuStart;\r
}\r
\r
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
}\r
\r
//\r
- // If the load operation, relocate operation, or the image execution return an\r
- // error, then free memory allocated from the EFI_SRAM_DESCRIPTOR specified by \r
- // SmramRange\r
+ // Always free memory allocted by GetFileBufferByFilePath ()\r
//\r
- if (EFI_ERROR (Status)) {\r
- SmramRange->PhysicalSize += EFI_PAGES_TO_SIZE (PageCount);\r
+ FreePool (SourceBuffer);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ SMM split SMRAM entry.\r
+\r
+ @param[in, out] RangeToCompare Pointer to EFI_SMRAM_DESCRIPTOR to compare.\r
+ @param[in, out] ReservedRangeToCompare Pointer to EFI_SMM_RESERVED_SMRAM_REGION to compare.\r
+ @param[out] Ranges Output pointer to hold split EFI_SMRAM_DESCRIPTOR entry.\r
+ @param[in, out] RangeCount Pointer to range count.\r
+ @param[out] ReservedRanges Output pointer to hold split EFI_SMM_RESERVED_SMRAM_REGION entry.\r
+ @param[in, out] ReservedRangeCount Pointer to reserved range count.\r
+ @param[out] FinalRanges Output pointer to hold split final EFI_SMRAM_DESCRIPTOR entry\r
+ that no need to be split anymore.\r
+ @param[in, out] FinalRangeCount Pointer to final range count.\r
+\r
+**/\r
+VOID\r
+SmmSplitSmramEntry (\r
+ IN OUT EFI_SMRAM_DESCRIPTOR *RangeToCompare,\r
+ IN OUT EFI_SMM_RESERVED_SMRAM_REGION *ReservedRangeToCompare,\r
+ OUT EFI_SMRAM_DESCRIPTOR *Ranges,\r
+ IN OUT UINTN *RangeCount,\r
+ OUT EFI_SMM_RESERVED_SMRAM_REGION *ReservedRanges,\r
+ IN OUT UINTN *ReservedRangeCount,\r
+ OUT EFI_SMRAM_DESCRIPTOR *FinalRanges,\r
+ IN OUT UINTN *FinalRangeCount\r
+ )\r
+{\r
+ UINT64 RangeToCompareEnd;\r
+ UINT64 ReservedRangeToCompareEnd;\r
+\r
+ RangeToCompareEnd = RangeToCompare->CpuStart + RangeToCompare->PhysicalSize;\r
+ ReservedRangeToCompareEnd = ReservedRangeToCompare->SmramReservedStart + ReservedRangeToCompare->SmramReservedSize;\r
+\r
+ if ((RangeToCompare->CpuStart >= ReservedRangeToCompare->SmramReservedStart) &&\r
+ (RangeToCompare->CpuStart < ReservedRangeToCompareEnd)) {\r
+ if (RangeToCompareEnd < ReservedRangeToCompareEnd) {\r
+ //\r
+ // RangeToCompare ReservedRangeToCompare\r
+ // ---- ---- --------------------------------------\r
+ // | | | | -> 1. ReservedRangeToCompare\r
+ // ---- | | |--| --------------------------------------\r
+ // | | | | | |\r
+ // | | | | | | -> 2. FinalRanges[*FinalRangeCount] and increment *FinalRangeCount\r
+ // | | | | | | RangeToCompare->PhysicalSize = 0\r
+ // ---- | | |--| --------------------------------------\r
+ // | | | | -> 3. ReservedRanges[*ReservedRangeCount] and increment *ReservedRangeCount\r
+ // ---- ---- --------------------------------------\r
+ //\r
+\r
+ //\r
+ // 1. Update ReservedRangeToCompare.\r
+ //\r
+ ReservedRangeToCompare->SmramReservedSize = RangeToCompare->CpuStart - ReservedRangeToCompare->SmramReservedStart;\r
+ //\r
+ // 2. Update FinalRanges[FinalRangeCount] and increment *FinalRangeCount.\r
+ // Zero RangeToCompare->PhysicalSize.\r
+ //\r
+ FinalRanges[*FinalRangeCount].CpuStart = RangeToCompare->CpuStart;\r
+ FinalRanges[*FinalRangeCount].PhysicalStart = RangeToCompare->PhysicalStart;\r
+ FinalRanges[*FinalRangeCount].RegionState = RangeToCompare->RegionState | EFI_ALLOCATED;\r
+ FinalRanges[*FinalRangeCount].PhysicalSize = RangeToCompare->PhysicalSize;\r
+ *FinalRangeCount += 1;\r
+ RangeToCompare->PhysicalSize = 0;\r
+ //\r
+ // 3. Update ReservedRanges[*ReservedRangeCount] and increment *ReservedRangeCount.\r
+ //\r
+ ReservedRanges[*ReservedRangeCount].SmramReservedStart = FinalRanges[*FinalRangeCount - 1].CpuStart + FinalRanges[*FinalRangeCount - 1].PhysicalSize;\r
+ ReservedRanges[*ReservedRangeCount].SmramReservedSize = ReservedRangeToCompareEnd - RangeToCompareEnd;\r
+ *ReservedRangeCount += 1;\r
+ } else {\r
+ //\r
+ // RangeToCompare ReservedRangeToCompare\r
+ // ---- ---- --------------------------------------\r
+ // | | | | -> 1. ReservedRangeToCompare\r
+ // ---- | | |--| --------------------------------------\r
+ // | | | | | |\r
+ // | | | | | | -> 2. FinalRanges[*FinalRangeCount] and increment *FinalRangeCount\r
+ // | | | | | |\r
+ // | | ---- |--| --------------------------------------\r
+ // | | | | -> 3. RangeToCompare\r
+ // ---- ---- --------------------------------------\r
+ //\r
+\r
+ //\r
+ // 1. Update ReservedRangeToCompare.\r
+ //\r
+ ReservedRangeToCompare->SmramReservedSize = RangeToCompare->CpuStart - ReservedRangeToCompare->SmramReservedStart;\r
+ //\r
+ // 2. Update FinalRanges[FinalRangeCount] and increment *FinalRangeCount.\r
+ //\r
+ FinalRanges[*FinalRangeCount].CpuStart = RangeToCompare->CpuStart;\r
+ FinalRanges[*FinalRangeCount].PhysicalStart = RangeToCompare->PhysicalStart;\r
+ FinalRanges[*FinalRangeCount].RegionState = RangeToCompare->RegionState | EFI_ALLOCATED;\r
+ FinalRanges[*FinalRangeCount].PhysicalSize = ReservedRangeToCompareEnd - RangeToCompare->CpuStart;\r
+ *FinalRangeCount += 1;\r
+ //\r
+ // 3. Update RangeToCompare.\r
+ //\r
+ RangeToCompare->CpuStart += FinalRanges[*FinalRangeCount - 1].PhysicalSize;\r
+ RangeToCompare->PhysicalStart += FinalRanges[*FinalRangeCount - 1].PhysicalSize;\r
+ RangeToCompare->PhysicalSize -= FinalRanges[*FinalRangeCount - 1].PhysicalSize;\r
+ }\r
+ } else if ((ReservedRangeToCompare->SmramReservedStart >= RangeToCompare->CpuStart) &&\r
+ (ReservedRangeToCompare->SmramReservedStart < RangeToCompareEnd)) {\r
+ if (ReservedRangeToCompareEnd < RangeToCompareEnd) {\r
+ //\r
+ // RangeToCompare ReservedRangeToCompare\r
+ // ---- ---- --------------------------------------\r
+ // | | | | -> 1. RangeToCompare\r
+ // | | ---- |--| --------------------------------------\r
+ // | | | | | |\r
+ // | | | | | | -> 2. FinalRanges[*FinalRangeCount] and increment *FinalRangeCount\r
+ // | | | | | | ReservedRangeToCompare->SmramReservedSize = 0\r
+ // | | ---- |--| --------------------------------------\r
+ // | | | | -> 3. Ranges[*RangeCount] and increment *RangeCount\r
+ // ---- ---- --------------------------------------\r
+ //\r
+\r
+ //\r
+ // 1. Update RangeToCompare.\r
+ //\r
+ RangeToCompare->PhysicalSize = ReservedRangeToCompare->SmramReservedStart - RangeToCompare->CpuStart;\r
+ //\r
+ // 2. Update FinalRanges[FinalRangeCount] and increment *FinalRangeCount.\r
+ // ReservedRangeToCompare->SmramReservedSize = 0\r
+ //\r
+ FinalRanges[*FinalRangeCount].CpuStart = ReservedRangeToCompare->SmramReservedStart;\r
+ FinalRanges[*FinalRangeCount].PhysicalStart = RangeToCompare->PhysicalStart + RangeToCompare->PhysicalSize;\r
+ FinalRanges[*FinalRangeCount].RegionState = RangeToCompare->RegionState | EFI_ALLOCATED;\r
+ FinalRanges[*FinalRangeCount].PhysicalSize = ReservedRangeToCompare->SmramReservedSize;\r
+ *FinalRangeCount += 1;\r
+ ReservedRangeToCompare->SmramReservedSize = 0;\r
+ //\r
+ // 3. Update Ranges[*RangeCount] and increment *RangeCount.\r
+ //\r
+ Ranges[*RangeCount].CpuStart = FinalRanges[*FinalRangeCount - 1].CpuStart + FinalRanges[*FinalRangeCount - 1].PhysicalSize;\r
+ Ranges[*RangeCount].PhysicalStart = FinalRanges[*FinalRangeCount - 1].PhysicalStart + FinalRanges[*FinalRangeCount - 1].PhysicalSize;\r
+ Ranges[*RangeCount].RegionState = RangeToCompare->RegionState;\r
+ Ranges[*RangeCount].PhysicalSize = RangeToCompareEnd - ReservedRangeToCompareEnd;\r
+ *RangeCount += 1;\r
+ } else {\r
+ //\r
+ // RangeToCompare ReservedRangeToCompare\r
+ // ---- ---- --------------------------------------\r
+ // | | | | -> 1. RangeToCompare\r
+ // | | ---- |--| --------------------------------------\r
+ // | | | | | |\r
+ // | | | | | | -> 2. FinalRanges[*FinalRangeCount] and increment *FinalRangeCount\r
+ // | | | | | |\r
+ // ---- | | |--| --------------------------------------\r
+ // | | | | -> 3. ReservedRangeToCompare\r
+ // ---- ---- --------------------------------------\r
+ //\r
+\r
+ //\r
+ // 1. Update RangeToCompare.\r
+ //\r
+ RangeToCompare->PhysicalSize = ReservedRangeToCompare->SmramReservedStart - RangeToCompare->CpuStart;\r
+ //\r
+ // 2. Update FinalRanges[FinalRangeCount] and increment *FinalRangeCount.\r
+ // ReservedRangeToCompare->SmramReservedSize = 0\r
+ //\r
+ FinalRanges[*FinalRangeCount].CpuStart = ReservedRangeToCompare->SmramReservedStart;\r
+ FinalRanges[*FinalRangeCount].PhysicalStart = RangeToCompare->PhysicalStart + RangeToCompare->PhysicalSize;\r
+ FinalRanges[*FinalRangeCount].RegionState = RangeToCompare->RegionState | EFI_ALLOCATED;\r
+ FinalRanges[*FinalRangeCount].PhysicalSize = RangeToCompareEnd - ReservedRangeToCompare->SmramReservedStart;\r
+ *FinalRangeCount += 1;\r
+ //\r
+ // 3. Update ReservedRangeToCompare.\r
+ //\r
+ ReservedRangeToCompare->SmramReservedStart += FinalRanges[*FinalRangeCount - 1].PhysicalSize;\r
+ ReservedRangeToCompare->SmramReservedSize -= FinalRanges[*FinalRangeCount - 1].PhysicalSize;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Returns if SMRAM range and SMRAM reserved range are overlapped.\r
+\r
+ @param[in] RangeToCompare Pointer to EFI_SMRAM_DESCRIPTOR to compare.\r
+ @param[in] ReservedRangeToCompare Pointer to EFI_SMM_RESERVED_SMRAM_REGION to compare.\r
+\r
+ @retval TRUE There is overlap.\r
+ @retval FALSE There is no overlap.\r
+\r
+**/\r
+BOOLEAN\r
+SmmIsSmramOverlap (\r
+ IN EFI_SMRAM_DESCRIPTOR *RangeToCompare,\r
+ IN EFI_SMM_RESERVED_SMRAM_REGION *ReservedRangeToCompare\r
+ )\r
+{\r
+ UINT64 RangeToCompareEnd;\r
+ UINT64 ReservedRangeToCompareEnd;\r
+\r
+ RangeToCompareEnd = RangeToCompare->CpuStart + RangeToCompare->PhysicalSize;\r
+ ReservedRangeToCompareEnd = ReservedRangeToCompare->SmramReservedStart + ReservedRangeToCompare->SmramReservedSize;\r
+\r
+ if ((RangeToCompare->CpuStart >= ReservedRangeToCompare->SmramReservedStart) &&\r
+ (RangeToCompare->CpuStart < ReservedRangeToCompareEnd)) {\r
+ return TRUE;\r
+ } else if ((ReservedRangeToCompare->SmramReservedStart >= RangeToCompare->CpuStart) &&\r
+ (ReservedRangeToCompare->SmramReservedStart < RangeToCompareEnd)) {\r
+ return TRUE;\r
}\r
+ return FALSE;\r
+}\r
\r
+/**\r
+ Get full SMRAM ranges.\r
+\r
+ It will get SMRAM ranges from SmmAccess protocol and SMRAM reserved ranges from\r
+ SmmConfiguration protocol, split the entries if there is overlap between them.\r
+ It will also reserve one entry for SMM core.\r
+\r
+ @param[out] FullSmramRangeCount Output pointer to full SMRAM range count.\r
+\r
+ @return Pointer to full SMRAM ranges.\r
+\r
+**/\r
+EFI_SMRAM_DESCRIPTOR *\r
+GetFullSmramRanges (\r
+ OUT UINTN *FullSmramRangeCount\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SMM_CONFIGURATION_PROTOCOL *SmmConfiguration;\r
+ UINTN Size;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ EFI_SMRAM_DESCRIPTOR *FullSmramRanges;\r
+ UINTN TempSmramRangeCount;\r
+ EFI_SMRAM_DESCRIPTOR *TempSmramRanges;\r
+ UINTN SmramRangeCount;\r
+ EFI_SMRAM_DESCRIPTOR *SmramRanges;\r
+ UINTN SmramReservedCount;\r
+ EFI_SMM_RESERVED_SMRAM_REGION *SmramReservedRanges;\r
+ UINTN MaxCount;\r
+ BOOLEAN Rescan;\r
+\r
+ //\r
+ // Get SMM Configuration Protocol if it is present.\r
//\r
- // Always free memory allocted by GetFileBufferByFilePath ()\r
+ SmmConfiguration = NULL;\r
+ Status = gBS->LocateProtocol (&gEfiSmmConfigurationProtocolGuid, NULL, (VOID **) &SmmConfiguration);\r
+\r
//\r
- FreePool (SourceBuffer);\r
+ // Get SMRAM information.\r
+ //\r
+ Size = 0;\r
+ Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, NULL);\r
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
\r
- return Status;\r
+ SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
+\r
+ //\r
+ // Get SMRAM reserved region count.\r
+ //\r
+ SmramReservedCount = 0;\r
+ if (SmmConfiguration != NULL) {\r
+ while (SmmConfiguration->SmramReservedRegions[SmramReservedCount].SmramReservedSize != 0) {\r
+ SmramReservedCount++;\r
+ }\r
+ }\r
+\r
+ if (SmramReservedCount == 0) {\r
+ //\r
+ // No reserved SMRAM entry from SMM Configuration Protocol.\r
+ // Reserve one entry for SMM Core in the full SMRAM ranges.\r
+ //\r
+ *FullSmramRangeCount = SmramRangeCount + 1;\r
+ Size = (*FullSmramRangeCount) * sizeof (EFI_SMRAM_DESCRIPTOR);\r
+ FullSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);\r
+ ASSERT (FullSmramRanges != NULL);\r
+\r
+ Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, FullSmramRanges);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return FullSmramRanges;\r
+ }\r
+\r
+ //\r
+ // Why MaxCount = X + 2 * Y?\r
+ // Take Y = 1 as example below, Y > 1 case is just the iteration of Y = 1.\r
+ //\r
+ // X = 1 Y = 1 MaxCount = 3 = 1 + 2 * 1\r
+ // ---- ----\r
+ // | | ---- |--|\r
+ // | | | | -> | |\r
+ // | | ---- |--|\r
+ // ---- ----\r
+ //\r
+ // X = 2 Y = 1 MaxCount = 4 = 2 + 2 * 1\r
+ // ---- ----\r
+ // | | | |\r
+ // | | ---- |--|\r
+ // | | | | | |\r
+ // |--| | | -> |--|\r
+ // | | | | | |\r
+ // | | ---- |--|\r
+ // | | | |\r
+ // ---- ----\r
+ //\r
+ // X = 3 Y = 1 MaxCount = 5 = 3 + 2 * 1\r
+ // ---- ----\r
+ // | | | |\r
+ // | | ---- |--|\r
+ // |--| | | |--|\r
+ // | | | | -> | |\r
+ // |--| | | |--|\r
+ // | | ---- |--|\r
+ // | | | |\r
+ // ---- ----\r
+ //\r
+ // ......\r
+ //\r
+ MaxCount = SmramRangeCount + 2 * SmramReservedCount;\r
+\r
+ Size = MaxCount * sizeof (EFI_SMM_RESERVED_SMRAM_REGION);\r
+ SmramReservedRanges = (EFI_SMM_RESERVED_SMRAM_REGION *) AllocatePool (Size);\r
+ ASSERT (SmramReservedRanges != NULL);\r
+ for (Index = 0; Index < SmramReservedCount; Index++) {\r
+ CopyMem (&SmramReservedRanges[Index], &SmmConfiguration->SmramReservedRegions[Index], sizeof (EFI_SMM_RESERVED_SMRAM_REGION));\r
+ }\r
+\r
+ Size = MaxCount * sizeof (EFI_SMRAM_DESCRIPTOR);\r
+ TempSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);\r
+ ASSERT (TempSmramRanges != NULL);\r
+ TempSmramRangeCount = 0;\r
+\r
+ SmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);\r
+ ASSERT (SmramRanges != NULL);\r
+ Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, SmramRanges);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ do {\r
+ Rescan = FALSE;\r
+ for (Index = 0; (Index < SmramRangeCount) && !Rescan; Index++) {\r
+ //\r
+ // Skip zero size entry.\r
+ //\r
+ if (SmramRanges[Index].PhysicalSize != 0) {\r
+ for (Index2 = 0; (Index2 < SmramReservedCount) && !Rescan; Index2++) {\r
+ //\r
+ // Skip zero size entry.\r
+ //\r
+ if (SmramReservedRanges[Index2].SmramReservedSize != 0) {\r
+ if (SmmIsSmramOverlap (\r
+ &SmramRanges[Index],\r
+ &SmramReservedRanges[Index2]\r
+ )) {\r
+ //\r
+ // There is overlap, need to split entry and then rescan.\r
+ //\r
+ SmmSplitSmramEntry (\r
+ &SmramRanges[Index],\r
+ &SmramReservedRanges[Index2],\r
+ SmramRanges,\r
+ &SmramRangeCount,\r
+ SmramReservedRanges,\r
+ &SmramReservedCount,\r
+ TempSmramRanges,\r
+ &TempSmramRangeCount\r
+ );\r
+ Rescan = TRUE;\r
+ }\r
+ }\r
+ }\r
+ if (!Rescan) {\r
+ //\r
+ // No any overlap, copy the entry to the temp SMRAM ranges.\r
+ // Zero SmramRanges[Index].PhysicalSize = 0;\r
+ //\r
+ CopyMem (&TempSmramRanges[TempSmramRangeCount++], &SmramRanges[Index], sizeof (EFI_SMRAM_DESCRIPTOR));\r
+ SmramRanges[Index].PhysicalSize = 0;\r
+ }\r
+ }\r
+ }\r
+ } while (Rescan);\r
+ ASSERT (TempSmramRangeCount <= MaxCount);\r
+\r
+ //\r
+ // Sort the entries,\r
+ // and reserve one entry for SMM Core in the full SMRAM ranges.\r
+ //\r
+ FullSmramRanges = AllocatePool ((TempSmramRangeCount + 1) * sizeof (EFI_SMRAM_DESCRIPTOR));\r
+ ASSERT (FullSmramRanges != NULL);\r
+ *FullSmramRangeCount = 0;\r
+ do {\r
+ for (Index = 0; Index < TempSmramRangeCount; Index++) {\r
+ if (TempSmramRanges[Index].PhysicalSize != 0) {\r
+ break;\r
+ }\r
+ }\r
+ ASSERT (Index < TempSmramRangeCount);\r
+ for (Index2 = 0; Index2 < TempSmramRangeCount; Index2++) {\r
+ if ((Index2 != Index) && (TempSmramRanges[Index2].PhysicalSize != 0) && (TempSmramRanges[Index2].CpuStart < TempSmramRanges[Index].CpuStart)) {\r
+ Index = Index2;\r
+ }\r
+ }\r
+ CopyMem (&FullSmramRanges[*FullSmramRangeCount], &TempSmramRanges[Index], sizeof (EFI_SMRAM_DESCRIPTOR));\r
+ *FullSmramRangeCount += 1;\r
+ TempSmramRanges[Index].PhysicalSize = 0;\r
+ } while (*FullSmramRangeCount < TempSmramRangeCount);\r
+ ASSERT (*FullSmramRangeCount == TempSmramRangeCount);\r
+ *FullSmramRangeCount += 1;\r
+\r
+ FreePool (SmramRanges);\r
+ FreePool (SmramReservedRanges);\r
+ FreePool (TempSmramRanges);\r
+\r
+ return FullSmramRanges;\r
}\r
\r
/**\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_SMM_CONFIGURATION_PROTOCOL *SmmConfiguration;\r
- UINTN Size;\r
UINTN Index;\r
- EFI_SMM_RESERVED_SMRAM_REGION *SmramResRegion;\r
UINT64 MaxSize;\r
VOID *Registration;\r
UINT64 SmmCodeSize;\r
Status = gBS->LocateProtocol (&gEfiSmmControl2ProtocolGuid, NULL, (VOID **)&mSmmControl2);\r
ASSERT_EFI_ERROR (Status);\r
\r
- //\r
- // Get SMM Configuration Protocol if it is present\r
- //\r
- SmmConfiguration = NULL;\r
- Status = gBS->LocateProtocol (&gEfiSmmConfigurationProtocolGuid, NULL, (VOID **) &SmmConfiguration);\r
-\r
- //\r
- // Get SMRAM information\r
- //\r
- Size = 0;\r
- Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, NULL);\r
- ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
-\r
- gSmmCorePrivate->SmramRanges = (EFI_SMRAM_DESCRIPTOR *)AllocatePool (Size);\r
- ASSERT (gSmmCorePrivate->SmramRanges != NULL);\r
-\r
- Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, gSmmCorePrivate->SmramRanges);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- gSmmCorePrivate->SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
-\r
- //\r
- // Save a full copy\r
- //\r
- gSmmCorePrivate->FullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;\r
- gSmmCorePrivate->FullSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);\r
- ASSERT (gSmmCorePrivate->FullSmramRanges != NULL);\r
- CopyMem (gSmmCorePrivate->FullSmramRanges, gSmmCorePrivate->SmramRanges, Size);\r
+ gSmmCorePrivate->SmramRanges = GetFullSmramRanges (&gSmmCorePrivate->SmramRangeCount);\r
\r
//\r
// Open all SMRAM ranges\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
- // Subtract SMRAM any reserved SMRAM regions.\r
- //\r
- if (SmmConfiguration != NULL) {\r
- SmramResRegion = SmmConfiguration->SmramReservedRegions;\r
- while (SmramResRegion->SmramReservedSize != 0) {\r
- for (Index = 0; Index < gSmmCorePrivate->SmramRangeCount; Index ++) {\r
- if ((SmramResRegion->SmramReservedStart >= gSmmCorePrivate->SmramRanges[Index].CpuStart) && \\r
- ((SmramResRegion->SmramReservedStart + SmramResRegion->SmramReservedSize) <= \\r
- (gSmmCorePrivate->SmramRanges[Index].CpuStart + gSmmCorePrivate->SmramRanges[Index].PhysicalSize))) {\r
- //\r
- // This range has reserved area, calculate the left free size\r
- //\r
- gSmmCorePrivate->SmramRanges[Index].PhysicalSize = SmramResRegion->SmramReservedStart - gSmmCorePrivate->SmramRanges[Index].CpuStart;\r
- }\r
- }\r
- SmramResRegion++;\r
- }\r
- }\r
\r
//\r
// Find the largest SMRAM range between 1MB and 4GB that is at least 256KB - 4K in size\r
//\r
// Load SMM Core into SMRAM and execute it from SMRAM\r
//\r
- Status = ExecuteSmmCoreFromSmram (mCurrentSmramRange, gSmmCorePrivate);\r
+ Status = ExecuteSmmCoreFromSmram (\r
+ mCurrentSmramRange,\r
+ &gSmmCorePrivate->SmramRanges[gSmmCorePrivate->SmramRangeCount - 1],\r
+ gSmmCorePrivate\r
+ );\r
if (EFI_ERROR (Status)) {\r
//\r
// Print error message that the SMM Core failed to be loaded and executed.\r
// Free all allocated resources\r
//\r
FreePool (gSmmCorePrivate->SmramRanges);\r
- FreePool (gSmmCorePrivate->FullSmramRanges);\r
\r
return EFI_UNSUPPORTED;\r
}\r