]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg PiSmmCore: Remove a hidden assumption of SMRAM reservation
authorStar Zeng <star.zeng@intel.com>
Sun, 26 Jul 2015 07:38:12 +0000 (07:38 +0000)
committerjljusten <jljusten@Edk2>
Sun, 26 Jul 2015 07:38:12 +0000 (07:38 +0000)
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

MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/MemoryAllocationLib.c
MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationServices.h

index c91f14907a8f8f1648a3b0f712f36705db082f90..55dcf31713e7f9bd56da9b74f24018cd0fb9c240 100644 (file)
@@ -523,10 +523,10 @@ SmmMain (
   //\r
   // Copy FullSmramRanges to SMRAM\r
   //\r
-  mFullSmramRangeCount = gSmmCorePrivate->FullSmramRangeCount;\r
+  mFullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;\r
   mFullSmramRanges = AllocatePool (mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));\r
   ASSERT (mFullSmramRanges != NULL);\r
-  CopyMem (mFullSmramRanges, gSmmCorePrivate->FullSmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));\r
+  CopyMem (mFullSmramRanges, gSmmCorePrivate->SmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));\r
 \r
   //\r
   // Register all SMI Handlers required by the SMM Core\r
index 9915669c6efdee61584edc5d627ee7ed59c8985e..8aec7a6568facc26f12ad7b99867a4b1835df66e 100644 (file)
@@ -120,9 +120,6 @@ typedef struct {
   EFI_PHYSICAL_ADDRESS            PiSmmCoreImageBase;\r
   UINT64                          PiSmmCoreImageSize;\r
   EFI_PHYSICAL_ADDRESS            PiSmmCoreEntryPoint;\r
-\r
-  UINTN                           FullSmramRangeCount;\r
-  EFI_SMRAM_DESCRIPTOR            *FullSmramRanges;\r
 } SMM_CORE_PRIVATE_DATA;\r
 \r
 #endif\r
index ebef741876b0b9a9753e8a06e5711c64ea8efae2..9b269779ea256b3002b82b7eae3f0f3b09cd1672 100644 (file)
@@ -861,17 +861,21 @@ GetPeCoffImageFixLoadingAssignedAddress(
 /**\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
@@ -879,7 +883,6 @@ ExecuteSmmCoreFromSmram (
   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
@@ -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\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
@@ -936,12 +939,15 @@ ExecuteSmmCoreFromSmram (
       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
@@ -954,12 +960,15 @@ ExecuteSmmCoreFromSmram (
     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
@@ -1006,20 +1015,424 @@ ExecuteSmmCoreFromSmram (
   }\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
@@ -1044,10 +1457,7 @@ SmmIplEntry (
   )\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
@@ -1074,34 +1484,7 @@ SmmIplEntry (
   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
@@ -1113,26 +1496,6 @@ SmmIplEntry (
   // 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
@@ -1214,7 +1577,11 @@ SmmIplEntry (
     //\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
@@ -1262,7 +1629,6 @@ SmmIplEntry (
     // Free all allocated resources\r
     //\r
     FreePool (gSmmCorePrivate->SmramRanges);\r
-    FreePool (gSmmCorePrivate->FullSmramRanges);\r
 \r
     return EFI_UNSUPPORTED;\r
   }\r
index 892ba0a040c9eb6fdce0167a0ce95d5a420232be..5e13a3eda2035232d7bf6bb806f13cb86cca80b0 100644 (file)
@@ -919,11 +919,11 @@ PiSmmCoreMemoryAllocationLibConstructor (
   //\r
   SmmInitializeMemoryServices (SmmCorePrivate->SmramRangeCount, SmmCorePrivate->SmramRanges);\r
 \r
-  mSmmCoreMemoryAllocLibSmramRangeCount = SmmCorePrivate->FullSmramRangeCount;\r
+  mSmmCoreMemoryAllocLibSmramRangeCount = SmmCorePrivate->SmramRangeCount;\r
   Size = mSmmCoreMemoryAllocLibSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR);\r
   mSmmCoreMemoryAllocLibSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);\r
   ASSERT (mSmmCoreMemoryAllocLibSmramRanges != NULL);\r
-  CopyMem (mSmmCoreMemoryAllocLibSmramRanges, SmmCorePrivate->FullSmramRanges, Size);\r
+  CopyMem (mSmmCoreMemoryAllocLibSmramRanges, SmmCorePrivate->SmramRanges, Size);\r
 \r
   return EFI_SUCCESS;\r
 }\r
index 6ae499b0dea4ebc9898df877731a015005fa8d3a..a2b89acf5de11c14895b50243e6386cb4442365b 100644 (file)
@@ -94,9 +94,6 @@ typedef struct {
   EFI_PHYSICAL_ADDRESS            PiSmmCoreImageBase;\r
   UINT64                          PiSmmCoreImageSize;\r
   EFI_PHYSICAL_ADDRESS            PiSmmCoreEntryPoint;\r
-\r
-  UINTN                           FullSmramRangeCount;\r
-  EFI_SMRAM_DESCRIPTOR            *FullSmramRanges;\r
 } SMM_CORE_PRIVATE_DATA;\r
 \r
 /**\r