diff options
author | Star Zeng <star.zeng@intel.com> | 2015-07-26 07:38:12 +0000 |
---|---|---|
committer | jljusten <jljusten@Edk2> | 2015-07-26 07:38:12 +0000 |
commit | c03beb762a7f1a08c0c91ccd8968500b2ccf5959 (patch) | |
tree | 9577254bde02a9b5ea76ae05181d04cd882985d8 /MdeModulePkg/Core | |
parent | 387e7c15f5e3a047de0a7a5edb5700e90a1c6c78 (diff) | |
download | edk2-platforms-c03beb762a7f1a08c0c91ccd8968500b2ccf5959.tar.xz |
MdeModulePkg PiSmmCore: Remove a hidden assumption of SMRAM reservation
that assumes the SMRAM reserved range is only at the end of the SMRAM descriptor.
//
// This range has reserved area, calculate the left free size
//
gSmmCorePrivate->SmramRanges[Index].PhysicalSize = SmramResRegion->SmramReservedStart - gSmmCorePrivate->SmramRanges[Index].CpuStart;
Imagine the following scenario where we just reserve the first page of the SMRAM range:
SMRAM Descriptor:
Start: 0x80000000
Size: 0x02000000
Reserved Range:
Start: 0x80000000
Size: 0x00001000
In this case the adjustment to the SMRAM range size yields zero: ReservedStart - SMRAM Start is 0x80000000 - 0x80000000 = 0.
So even though most of the range is still free the IPL code decides its unusable.
The problem comes from the email thread: [edk2] PiSmmIpl SMRAM Reservation Logic.
http://thread.gmane.org/gmane.comp.bios.tianocore.devel/15268
Also to follow the idea in the email thread, the patch is to
1. Keep only one copy of full SMRAM ranges in gSmmCorePrivate->SmramRanges,
split record for SmmConfiguration->SmramReservedRegions and SMM Core that
will be marked to be EFI_ALLOCATED in gSmmCorePrivate->SmramRanges.
2. Handle SmmConfiguration->SmramReservedRegions at beginning of, at end of,
in the middle of, or cross multiple SmramRanges.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18031 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Core')
-rw-r--r-- | MdeModulePkg/Core/PiSmmCore/PiSmmCore.c | 4 | ||||
-rw-r--r-- | MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h | 3 | ||||
-rw-r--r-- | MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c | 514 |
3 files changed, 442 insertions, 79 deletions
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c index c91f14907a..55dcf31713 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c @@ -523,10 +523,10 @@ SmmMain ( //
// Copy FullSmramRanges to SMRAM
//
- mFullSmramRangeCount = gSmmCorePrivate->FullSmramRangeCount;
+ mFullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;
mFullSmramRanges = AllocatePool (mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
ASSERT (mFullSmramRanges != NULL);
- CopyMem (mFullSmramRanges, gSmmCorePrivate->FullSmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
+ CopyMem (mFullSmramRanges, gSmmCorePrivate->SmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
//
// Register all SMI Handlers required by the SMM Core
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h b/MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h index 9915669c6e..8aec7a6568 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h @@ -120,9 +120,6 @@ typedef struct { EFI_PHYSICAL_ADDRESS PiSmmCoreImageBase;
UINT64 PiSmmCoreImageSize;
EFI_PHYSICAL_ADDRESS PiSmmCoreEntryPoint;
-
- UINTN FullSmramRangeCount;
- EFI_SMRAM_DESCRIPTOR *FullSmramRanges;
} SMM_CORE_PRIVATE_DATA;
#endif
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c index ebef741876..9b269779ea 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c @@ -861,17 +861,21 @@ GetPeCoffImageFixLoadingAssignedAddress( /**
Load the SMM Core image into SMRAM and executes the SMM Core from SMRAM.
- @param[in] SmramRange Descriptor for the range of SMRAM to reload the
- currently executing image.
- @param[in] Context Context to pass into SMM Core
+ @param[in, out] SmramRange Descriptor for the range of SMRAM to reload the
+ currently executing image, the rang of SMRAM to
+ hold SMM Core will be excluded.
+ @param[in, out] SmramRangeSmmCore Descriptor for the range of SMRAM to hold SMM Core.
+
+ @param[in] Context Context to pass into SMM Core
@return EFI_STATUS
**/
EFI_STATUS
ExecuteSmmCoreFromSmram (
- IN EFI_SMRAM_DESCRIPTOR *SmramRange,
- IN VOID *Context
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramRange,
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramRangeSmmCore,
+ IN VOID *Context
)
{
EFI_STATUS Status;
@@ -879,7 +883,6 @@ ExecuteSmmCoreFromSmram ( UINTN SourceSize;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
UINTN PageCount;
- EFI_PHYSICAL_ADDRESS DestinationBuffer;
EFI_IMAGE_ENTRY_POINT EntryPoint;
//
@@ -924,7 +927,7 @@ ExecuteSmmCoreFromSmram ( // Since the memory range to load SMM CORE will be cut out in SMM core, so no need to allocate and free this range
//
PageCount = 0;
- } else {
+ } else {
DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR: Loading module at fixed address at address failed\n"));
//
// Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR
@@ -936,12 +939,15 @@ ExecuteSmmCoreFromSmram ( ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));
SmramRange->PhysicalSize -= EFI_PAGES_TO_SIZE (PageCount);
- DestinationBuffer = SmramRange->CpuStart + SmramRange->PhysicalSize;
+ SmramRangeSmmCore->CpuStart = SmramRange->CpuStart + SmramRange->PhysicalSize;
+ SmramRangeSmmCore->PhysicalStart = SmramRange->PhysicalStart + SmramRange->PhysicalSize;
+ SmramRangeSmmCore->RegionState = SmramRange->RegionState | EFI_ALLOCATED;
+ SmramRangeSmmCore->PhysicalSize = EFI_PAGES_TO_SIZE (PageCount);
//
- // Align buffer on section boundry
+ // Align buffer on section boundary
//
- ImageContext.ImageAddress = DestinationBuffer;
+ ImageContext.ImageAddress = SmramRangeSmmCore->CpuStart;
}
} else {
//
@@ -954,12 +960,15 @@ ExecuteSmmCoreFromSmram ( ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));
SmramRange->PhysicalSize -= EFI_PAGES_TO_SIZE (PageCount);
- DestinationBuffer = SmramRange->CpuStart + SmramRange->PhysicalSize;
+ SmramRangeSmmCore->CpuStart = SmramRange->CpuStart + SmramRange->PhysicalSize;
+ SmramRangeSmmCore->PhysicalStart = SmramRange->PhysicalStart + SmramRange->PhysicalSize;
+ SmramRangeSmmCore->RegionState = SmramRange->RegionState | EFI_ALLOCATED;
+ SmramRangeSmmCore->PhysicalSize = EFI_PAGES_TO_SIZE (PageCount);
//
- // Align buffer on section boundry
+ // Align buffer on section boundary
//
- ImageContext.ImageAddress = DestinationBuffer;
+ ImageContext.ImageAddress = SmramRangeSmmCore->CpuStart;
}
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
@@ -1006,20 +1015,424 @@ ExecuteSmmCoreFromSmram ( }
//
- // If the load operation, relocate operation, or the image execution return an
- // error, then free memory allocated from the EFI_SRAM_DESCRIPTOR specified by
- // SmramRange
+ // Always free memory allocted by GetFileBufferByFilePath ()
//
- if (EFI_ERROR (Status)) {
- SmramRange->PhysicalSize += EFI_PAGES_TO_SIZE (PageCount);
+ FreePool (SourceBuffer);
+
+ return Status;
+}
+
+/**
+ SMM split SMRAM entry.
+
+ @param[in, out] RangeToCompare Pointer to EFI_SMRAM_DESCRIPTOR to compare.
+ @param[in, out] ReservedRangeToCompare Pointer to EFI_SMM_RESERVED_SMRAM_REGION to compare.
+ @param[out] Ranges Output pointer to hold split EFI_SMRAM_DESCRIPTOR entry.
+ @param[in, out] RangeCount Pointer to range count.
+ @param[out] ReservedRanges Output pointer to hold split EFI_SMM_RESERVED_SMRAM_REGION entry.
+ @param[in, out] ReservedRangeCount Pointer to reserved range count.
+ @param[out] FinalRanges Output pointer to hold split final EFI_SMRAM_DESCRIPTOR entry
+ that no need to be split anymore.
+ @param[in, out] FinalRangeCount Pointer to final range count.
+
+**/
+VOID
+SmmSplitSmramEntry (
+ IN OUT EFI_SMRAM_DESCRIPTOR *RangeToCompare,
+ IN OUT EFI_SMM_RESERVED_SMRAM_REGION *ReservedRangeToCompare,
+ OUT EFI_SMRAM_DESCRIPTOR *Ranges,
+ IN OUT UINTN *RangeCount,
+ OUT EFI_SMM_RESERVED_SMRAM_REGION *ReservedRanges,
+ IN OUT UINTN *ReservedRangeCount,
+ OUT EFI_SMRAM_DESCRIPTOR *FinalRanges,
+ IN OUT UINTN *FinalRangeCount
+ )
+{
+ UINT64 RangeToCompareEnd;
+ UINT64 ReservedRangeToCompareEnd;
+
+ RangeToCompareEnd = RangeToCompare->CpuStart + RangeToCompare->PhysicalSize;
+ ReservedRangeToCompareEnd = ReservedRangeToCompare->SmramReservedStart + ReservedRangeToCompare->SmramReservedSize;
+
+ if ((RangeToCompare->CpuStart >= ReservedRangeToCompare->SmramReservedStart) &&
+ (RangeToCompare->CpuStart < ReservedRangeToCompareEnd)) {
+ if (RangeToCompareEnd < ReservedRangeToCompareEnd) {
+ //
+ // RangeToCompare ReservedRangeToCompare
+ // ---- ---- --------------------------------------
+ // | | | | -> 1. ReservedRangeToCompare
+ // ---- | | |--| --------------------------------------
+ // | | | | | |
+ // | | | | | | -> 2. FinalRanges[*FinalRangeCount] and increment *FinalRangeCount
+ // | | | | | | RangeToCompare->PhysicalSize = 0
+ // ---- | | |--| --------------------------------------
+ // | | | | -> 3. ReservedRanges[*ReservedRangeCount] and increment *ReservedRangeCount
+ // ---- ---- --------------------------------------
+ //
+
+ //
+ // 1. Update ReservedRangeToCompare.
+ //
+ ReservedRangeToCompare->SmramReservedSize = RangeToCompare->CpuStart - ReservedRangeToCompare->SmramReservedStart;
+ //
+ // 2. Update FinalRanges[FinalRangeCount] and increment *FinalRangeCount.
+ // Zero RangeToCompare->PhysicalSize.
+ //
+ FinalRanges[*FinalRangeCount].CpuStart = RangeToCompare->CpuStart;
+ FinalRanges[*FinalRangeCount].PhysicalStart = RangeToCompare->PhysicalStart;
+ FinalRanges[*FinalRangeCount].RegionState = RangeToCompare->RegionState | EFI_ALLOCATED;
+ FinalRanges[*FinalRangeCount].PhysicalSize = RangeToCompare->PhysicalSize;
+ *FinalRangeCount += 1;
+ RangeToCompare->PhysicalSize = 0;
+ //
+ // 3. Update ReservedRanges[*ReservedRangeCount] and increment *ReservedRangeCount.
+ //
+ ReservedRanges[*ReservedRangeCount].SmramReservedStart = FinalRanges[*FinalRangeCount - 1].CpuStart + FinalRanges[*FinalRangeCount - 1].PhysicalSize;
+ ReservedRanges[*ReservedRangeCount].SmramReservedSize = ReservedRangeToCompareEnd - RangeToCompareEnd;
+ *ReservedRangeCount += 1;
+ } else {
+ //
+ // RangeToCompare ReservedRangeToCompare
+ // ---- ---- --------------------------------------
+ // | | | | -> 1. ReservedRangeToCompare
+ // ---- | | |--| --------------------------------------
+ // | | | | | |
+ // | | | | | | -> 2. FinalRanges[*FinalRangeCount] and increment *FinalRangeCount
+ // | | | | | |
+ // | | ---- |--| --------------------------------------
+ // | | | | -> 3. RangeToCompare
+ // ---- ---- --------------------------------------
+ //
+
+ //
+ // 1. Update ReservedRangeToCompare.
+ //
+ ReservedRangeToCompare->SmramReservedSize = RangeToCompare->CpuStart - ReservedRangeToCompare->SmramReservedStart;
+ //
+ // 2. Update FinalRanges[FinalRangeCount] and increment *FinalRangeCount.
+ //
+ FinalRanges[*FinalRangeCount].CpuStart = RangeToCompare->CpuStart;
+ FinalRanges[*FinalRangeCount].PhysicalStart = RangeToCompare->PhysicalStart;
+ FinalRanges[*FinalRangeCount].RegionState = RangeToCompare->RegionState | EFI_ALLOCATED;
+ FinalRanges[*FinalRangeCount].PhysicalSize = ReservedRangeToCompareEnd - RangeToCompare->CpuStart;
+ *FinalRangeCount += 1;
+ //
+ // 3. Update RangeToCompare.
+ //
+ RangeToCompare->CpuStart += FinalRanges[*FinalRangeCount - 1].PhysicalSize;
+ RangeToCompare->PhysicalStart += FinalRanges[*FinalRangeCount - 1].PhysicalSize;
+ RangeToCompare->PhysicalSize -= FinalRanges[*FinalRangeCount - 1].PhysicalSize;
+ }
+ } else if ((ReservedRangeToCompare->SmramReservedStart >= RangeToCompare->CpuStart) &&
+ (ReservedRangeToCompare->SmramReservedStart < RangeToCompareEnd)) {
+ if (ReservedRangeToCompareEnd < RangeToCompareEnd) {
+ //
+ // RangeToCompare ReservedRangeToCompare
+ // ---- ---- --------------------------------------
+ // | | | | -> 1. RangeToCompare
+ // | | ---- |--| --------------------------------------
+ // | | | | | |
+ // | | | | | | -> 2. FinalRanges[*FinalRangeCount] and increment *FinalRangeCount
+ // | | | | | | ReservedRangeToCompare->SmramReservedSize = 0
+ // | | ---- |--| --------------------------------------
+ // | | | | -> 3. Ranges[*RangeCount] and increment *RangeCount
+ // ---- ---- --------------------------------------
+ //
+
+ //
+ // 1. Update RangeToCompare.
+ //
+ RangeToCompare->PhysicalSize = ReservedRangeToCompare->SmramReservedStart - RangeToCompare->CpuStart;
+ //
+ // 2. Update FinalRanges[FinalRangeCount] and increment *FinalRangeCount.
+ // ReservedRangeToCompare->SmramReservedSize = 0
+ //
+ FinalRanges[*FinalRangeCount].CpuStart = ReservedRangeToCompare->SmramReservedStart;
+ FinalRanges[*FinalRangeCount].PhysicalStart = RangeToCompare->PhysicalStart + RangeToCompare->PhysicalSize;
+ FinalRanges[*FinalRangeCount].RegionState = RangeToCompare->RegionState | EFI_ALLOCATED;
+ FinalRanges[*FinalRangeCount].PhysicalSize = ReservedRangeToCompare->SmramReservedSize;
+ *FinalRangeCount += 1;
+ ReservedRangeToCompare->SmramReservedSize = 0;
+ //
+ // 3. Update Ranges[*RangeCount] and increment *RangeCount.
+ //
+ Ranges[*RangeCount].CpuStart = FinalRanges[*FinalRangeCount - 1].CpuStart + FinalRanges[*FinalRangeCount - 1].PhysicalSize;
+ Ranges[*RangeCount].PhysicalStart = FinalRanges[*FinalRangeCount - 1].PhysicalStart + FinalRanges[*FinalRangeCount - 1].PhysicalSize;
+ Ranges[*RangeCount].RegionState = RangeToCompare->RegionState;
+ Ranges[*RangeCount].PhysicalSize = RangeToCompareEnd - ReservedRangeToCompareEnd;
+ *RangeCount += 1;
+ } else {
+ //
+ // RangeToCompare ReservedRangeToCompare
+ // ---- ---- --------------------------------------
+ // | | | | -> 1. RangeToCompare
+ // | | ---- |--| --------------------------------------
+ // | | | | | |
+ // | | | | | | -> 2. FinalRanges[*FinalRangeCount] and increment *FinalRangeCount
+ // | | | | | |
+ // ---- | | |--| --------------------------------------
+ // | | | | -> 3. ReservedRangeToCompare
+ // ---- ---- --------------------------------------
+ //
+
+ //
+ // 1. Update RangeToCompare.
+ //
+ RangeToCompare->PhysicalSize = ReservedRangeToCompare->SmramReservedStart - RangeToCompare->CpuStart;
+ //
+ // 2. Update FinalRanges[FinalRangeCount] and increment *FinalRangeCount.
+ // ReservedRangeToCompare->SmramReservedSize = 0
+ //
+ FinalRanges[*FinalRangeCount].CpuStart = ReservedRangeToCompare->SmramReservedStart;
+ FinalRanges[*FinalRangeCount].PhysicalStart = RangeToCompare->PhysicalStart + RangeToCompare->PhysicalSize;
+ FinalRanges[*FinalRangeCount].RegionState = RangeToCompare->RegionState | EFI_ALLOCATED;
+ FinalRanges[*FinalRangeCount].PhysicalSize = RangeToCompareEnd - ReservedRangeToCompare->SmramReservedStart;
+ *FinalRangeCount += 1;
+ //
+ // 3. Update ReservedRangeToCompare.
+ //
+ ReservedRangeToCompare->SmramReservedStart += FinalRanges[*FinalRangeCount - 1].PhysicalSize;
+ ReservedRangeToCompare->SmramReservedSize -= FinalRanges[*FinalRangeCount - 1].PhysicalSize;
+ }
+ }
+}
+
+/**
+ Returns if SMRAM range and SMRAM reserved range are overlapped.
+
+ @param[in] RangeToCompare Pointer to EFI_SMRAM_DESCRIPTOR to compare.
+ @param[in] ReservedRangeToCompare Pointer to EFI_SMM_RESERVED_SMRAM_REGION to compare.
+
+ @retval TRUE There is overlap.
+ @retval FALSE There is no overlap.
+
+**/
+BOOLEAN
+SmmIsSmramOverlap (
+ IN EFI_SMRAM_DESCRIPTOR *RangeToCompare,
+ IN EFI_SMM_RESERVED_SMRAM_REGION *ReservedRangeToCompare
+ )
+{
+ UINT64 RangeToCompareEnd;
+ UINT64 ReservedRangeToCompareEnd;
+
+ RangeToCompareEnd = RangeToCompare->CpuStart + RangeToCompare->PhysicalSize;
+ ReservedRangeToCompareEnd = ReservedRangeToCompare->SmramReservedStart + ReservedRangeToCompare->SmramReservedSize;
+
+ if ((RangeToCompare->CpuStart >= ReservedRangeToCompare->SmramReservedStart) &&
+ (RangeToCompare->CpuStart < ReservedRangeToCompareEnd)) {
+ return TRUE;
+ } else if ((ReservedRangeToCompare->SmramReservedStart >= RangeToCompare->CpuStart) &&
+ (ReservedRangeToCompare->SmramReservedStart < RangeToCompareEnd)) {
+ return TRUE;
}
+ return FALSE;
+}
+/**
+ Get full SMRAM ranges.
+
+ It will get SMRAM ranges from SmmAccess protocol and SMRAM reserved ranges from
+ SmmConfiguration protocol, split the entries if there is overlap between them.
+ It will also reserve one entry for SMM core.
+
+ @param[out] FullSmramRangeCount Output pointer to full SMRAM range count.
+
+ @return Pointer to full SMRAM ranges.
+
+**/
+EFI_SMRAM_DESCRIPTOR *
+GetFullSmramRanges (
+ OUT UINTN *FullSmramRangeCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMM_CONFIGURATION_PROTOCOL *SmmConfiguration;
+ UINTN Size;
+ UINTN Index;
+ UINTN Index2;
+ EFI_SMRAM_DESCRIPTOR *FullSmramRanges;
+ UINTN TempSmramRangeCount;
+ EFI_SMRAM_DESCRIPTOR *TempSmramRanges;
+ UINTN SmramRangeCount;
+ EFI_SMRAM_DESCRIPTOR *SmramRanges;
+ UINTN SmramReservedCount;
+ EFI_SMM_RESERVED_SMRAM_REGION *SmramReservedRanges;
+ UINTN MaxCount;
+ BOOLEAN Rescan;
+
+ //
+ // Get SMM Configuration Protocol if it is present.
//
- // Always free memory allocted by GetFileBufferByFilePath ()
+ SmmConfiguration = NULL;
+ Status = gBS->LocateProtocol (&gEfiSmmConfigurationProtocolGuid, NULL, (VOID **) &SmmConfiguration);
+
//
- FreePool (SourceBuffer);
+ // Get SMRAM information.
+ //
+ Size = 0;
+ Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, NULL);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
- return Status;
+ SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
+
+ //
+ // Get SMRAM reserved region count.
+ //
+ SmramReservedCount = 0;
+ if (SmmConfiguration != NULL) {
+ while (SmmConfiguration->SmramReservedRegions[SmramReservedCount].SmramReservedSize != 0) {
+ SmramReservedCount++;
+ }
+ }
+
+ if (SmramReservedCount == 0) {
+ //
+ // No reserved SMRAM entry from SMM Configuration Protocol.
+ // Reserve one entry for SMM Core in the full SMRAM ranges.
+ //
+ *FullSmramRangeCount = SmramRangeCount + 1;
+ Size = (*FullSmramRangeCount) * sizeof (EFI_SMRAM_DESCRIPTOR);
+ FullSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);
+ ASSERT (FullSmramRanges != NULL);
+
+ Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, FullSmramRanges);
+ ASSERT_EFI_ERROR (Status);
+
+ return FullSmramRanges;
+ }
+
+ //
+ // Why MaxCount = X + 2 * Y?
+ // Take Y = 1 as example below, Y > 1 case is just the iteration of Y = 1.
+ //
+ // X = 1 Y = 1 MaxCount = 3 = 1 + 2 * 1
+ // ---- ----
+ // | | ---- |--|
+ // | | | | -> | |
+ // | | ---- |--|
+ // ---- ----
+ //
+ // X = 2 Y = 1 MaxCount = 4 = 2 + 2 * 1
+ // ---- ----
+ // | | | |
+ // | | ---- |--|
+ // | | | | | |
+ // |--| | | -> |--|
+ // | | | | | |
+ // | | ---- |--|
+ // | | | |
+ // ---- ----
+ //
+ // X = 3 Y = 1 MaxCount = 5 = 3 + 2 * 1
+ // ---- ----
+ // | | | |
+ // | | ---- |--|
+ // |--| | | |--|
+ // | | | | -> | |
+ // |--| | | |--|
+ // | | ---- |--|
+ // | | | |
+ // ---- ----
+ //
+ // ......
+ //
+ MaxCount = SmramRangeCount + 2 * SmramReservedCount;
+
+ Size = MaxCount * sizeof (EFI_SMM_RESERVED_SMRAM_REGION);
+ SmramReservedRanges = (EFI_SMM_RESERVED_SMRAM_REGION *) AllocatePool (Size);
+ ASSERT (SmramReservedRanges != NULL);
+ for (Index = 0; Index < SmramReservedCount; Index++) {
+ CopyMem (&SmramReservedRanges[Index], &SmmConfiguration->SmramReservedRegions[Index], sizeof (EFI_SMM_RESERVED_SMRAM_REGION));
+ }
+
+ Size = MaxCount * sizeof (EFI_SMRAM_DESCRIPTOR);
+ TempSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);
+ ASSERT (TempSmramRanges != NULL);
+ TempSmramRangeCount = 0;
+
+ SmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);
+ ASSERT (SmramRanges != NULL);
+ Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, SmramRanges);
+ ASSERT_EFI_ERROR (Status);
+
+ do {
+ Rescan = FALSE;
+ for (Index = 0; (Index < SmramRangeCount) && !Rescan; Index++) {
+ //
+ // Skip zero size entry.
+ //
+ if (SmramRanges[Index].PhysicalSize != 0) {
+ for (Index2 = 0; (Index2 < SmramReservedCount) && !Rescan; Index2++) {
+ //
+ // Skip zero size entry.
+ //
+ if (SmramReservedRanges[Index2].SmramReservedSize != 0) {
+ if (SmmIsSmramOverlap (
+ &SmramRanges[Index],
+ &SmramReservedRanges[Index2]
+ )) {
+ //
+ // There is overlap, need to split entry and then rescan.
+ //
+ SmmSplitSmramEntry (
+ &SmramRanges[Index],
+ &SmramReservedRanges[Index2],
+ SmramRanges,
+ &SmramRangeCount,
+ SmramReservedRanges,
+ &SmramReservedCount,
+ TempSmramRanges,
+ &TempSmramRangeCount
+ );
+ Rescan = TRUE;
+ }
+ }
+ }
+ if (!Rescan) {
+ //
+ // No any overlap, copy the entry to the temp SMRAM ranges.
+ // Zero SmramRanges[Index].PhysicalSize = 0;
+ //
+ CopyMem (&TempSmramRanges[TempSmramRangeCount++], &SmramRanges[Index], sizeof (EFI_SMRAM_DESCRIPTOR));
+ SmramRanges[Index].PhysicalSize = 0;
+ }
+ }
+ }
+ } while (Rescan);
+ ASSERT (TempSmramRangeCount <= MaxCount);
+
+ //
+ // Sort the entries,
+ // and reserve one entry for SMM Core in the full SMRAM ranges.
+ //
+ FullSmramRanges = AllocatePool ((TempSmramRangeCount + 1) * sizeof (EFI_SMRAM_DESCRIPTOR));
+ ASSERT (FullSmramRanges != NULL);
+ *FullSmramRangeCount = 0;
+ do {
+ for (Index = 0; Index < TempSmramRangeCount; Index++) {
+ if (TempSmramRanges[Index].PhysicalSize != 0) {
+ break;
+ }
+ }
+ ASSERT (Index < TempSmramRangeCount);
+ for (Index2 = 0; Index2 < TempSmramRangeCount; Index2++) {
+ if ((Index2 != Index) && (TempSmramRanges[Index2].PhysicalSize != 0) && (TempSmramRanges[Index2].CpuStart < TempSmramRanges[Index].CpuStart)) {
+ Index = Index2;
+ }
+ }
+ CopyMem (&FullSmramRanges[*FullSmramRangeCount], &TempSmramRanges[Index], sizeof (EFI_SMRAM_DESCRIPTOR));
+ *FullSmramRangeCount += 1;
+ TempSmramRanges[Index].PhysicalSize = 0;
+ } while (*FullSmramRangeCount < TempSmramRangeCount);
+ ASSERT (*FullSmramRangeCount == TempSmramRangeCount);
+ *FullSmramRangeCount += 1;
+
+ FreePool (SmramRanges);
+ FreePool (SmramReservedRanges);
+ FreePool (TempSmramRanges);
+
+ return FullSmramRanges;
}
/**
@@ -1044,10 +1457,7 @@ SmmIplEntry ( )
{
EFI_STATUS Status;
- EFI_SMM_CONFIGURATION_PROTOCOL *SmmConfiguration;
- UINTN Size;
UINTN Index;
- EFI_SMM_RESERVED_SMRAM_REGION *SmramResRegion;
UINT64 MaxSize;
VOID *Registration;
UINT64 SmmCodeSize;
@@ -1074,34 +1484,7 @@ SmmIplEntry ( Status = gBS->LocateProtocol (&gEfiSmmControl2ProtocolGuid, NULL, (VOID **)&mSmmControl2);
ASSERT_EFI_ERROR (Status);
- //
- // Get SMM Configuration Protocol if it is present
- //
- SmmConfiguration = NULL;
- Status = gBS->LocateProtocol (&gEfiSmmConfigurationProtocolGuid, NULL, (VOID **) &SmmConfiguration);
-
- //
- // Get SMRAM information
- //
- Size = 0;
- Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, NULL);
- ASSERT (Status == EFI_BUFFER_TOO_SMALL);
-
- gSmmCorePrivate->SmramRanges = (EFI_SMRAM_DESCRIPTOR *)AllocatePool (Size);
- ASSERT (gSmmCorePrivate->SmramRanges != NULL);
-
- Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, gSmmCorePrivate->SmramRanges);
- ASSERT_EFI_ERROR (Status);
-
- gSmmCorePrivate->SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
-
- //
- // Save a full copy
- //
- gSmmCorePrivate->FullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;
- gSmmCorePrivate->FullSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);
- ASSERT (gSmmCorePrivate->FullSmramRanges != NULL);
- CopyMem (gSmmCorePrivate->FullSmramRanges, gSmmCorePrivate->SmramRanges, Size);
+ gSmmCorePrivate->SmramRanges = GetFullSmramRanges (&gSmmCorePrivate->SmramRangeCount);
//
// Open all SMRAM ranges
@@ -1113,26 +1496,6 @@ SmmIplEntry ( // Print debug message that the SMRAM window is now open.
//
DEBUG ((DEBUG_INFO, "SMM IPL opened SMRAM window\n"));
-
- //
- // Subtract SMRAM any reserved SMRAM regions.
- //
- if (SmmConfiguration != NULL) {
- SmramResRegion = SmmConfiguration->SmramReservedRegions;
- while (SmramResRegion->SmramReservedSize != 0) {
- for (Index = 0; Index < gSmmCorePrivate->SmramRangeCount; Index ++) {
- if ((SmramResRegion->SmramReservedStart >= gSmmCorePrivate->SmramRanges[Index].CpuStart) && \
- ((SmramResRegion->SmramReservedStart + SmramResRegion->SmramReservedSize) <= \
- (gSmmCorePrivate->SmramRanges[Index].CpuStart + gSmmCorePrivate->SmramRanges[Index].PhysicalSize))) {
- //
- // This range has reserved area, calculate the left free size
- //
- gSmmCorePrivate->SmramRanges[Index].PhysicalSize = SmramResRegion->SmramReservedStart - gSmmCorePrivate->SmramRanges[Index].CpuStart;
- }
- }
- SmramResRegion++;
- }
- }
//
// Find the largest SMRAM range between 1MB and 4GB that is at least 256KB - 4K in size
@@ -1214,7 +1577,11 @@ SmmIplEntry ( //
// Load SMM Core into SMRAM and execute it from SMRAM
//
- Status = ExecuteSmmCoreFromSmram (mCurrentSmramRange, gSmmCorePrivate);
+ Status = ExecuteSmmCoreFromSmram (
+ mCurrentSmramRange,
+ &gSmmCorePrivate->SmramRanges[gSmmCorePrivate->SmramRangeCount - 1],
+ gSmmCorePrivate
+ );
if (EFI_ERROR (Status)) {
//
// Print error message that the SMM Core failed to be loaded and executed.
@@ -1262,7 +1629,6 @@ SmmIplEntry ( // Free all allocated resources
//
FreePool (gSmmCorePrivate->SmramRanges);
- FreePool (gSmmCorePrivate->FullSmramRanges);
return EFI_UNSUPPORTED;
}
|