]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
MdeModulePkg: Fix use-after-free error in InstallConfigurationTable()
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / PiSmmIpl.c
index 50c3b34dfd34d65819ea6a5e6eaf47b55ace8784..2601275ab85fce7a6179e382b2b1252915a9f6dc 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   SMM IPL that produces SMM related runtime protocols and load the SMM Core into SMRAM\r
 \r
-  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\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
@@ -38,6 +38,7 @@
 #include <Library/UefiLib.h>\r
 #include <Library/UefiRuntimeLib.h>\r
 #include <Library/PcdLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
 \r
 #include "PiSmmCorePrivateData.h"\r
 \r
@@ -162,6 +163,20 @@ SmmIplGuidedEventNotify (
   IN VOID       *Context\r
   );\r
 \r
+/**\r
+  Event notification that is fired when EndOfDxe Event Group is signaled.\r
+\r
+  @param  Event                 The Event that is being processed, not used.\r
+  @param  Context               Event Context, not used.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmIplEndOfDxeEventNotify (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  );\r
+\r
 /**\r
   Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.\r
 \r
@@ -243,17 +258,19 @@ EFI_SMM_CONTROL2_PROTOCOL  *mSmmControl2;
 EFI_SMM_ACCESS2_PROTOCOL   *mSmmAccess;\r
 EFI_SMRAM_DESCRIPTOR       *mCurrentSmramRange;\r
 BOOLEAN                    mSmmLocked = FALSE;\r
+BOOLEAN                    mEndOfDxe  = FALSE;\r
 EFI_PHYSICAL_ADDRESS       mSmramCacheBase;\r
 UINT64                     mSmramCacheSize;\r
 \r
 EFI_SMM_COMMUNICATE_HEADER mCommunicateHeader;\r
+EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE    *mLMFAConfigurationTable = NULL;\r
 \r
 //\r
 // Table of Protocol notification and GUIDed Event notifications that the SMM IPL requires\r
 //\r
 SMM_IPL_EVENT_NOTIFICATION  mSmmIplEvents[] = {\r
   //\r
-  // Declare protocol notification on the SMM Configuration protocol.  When this notification is etablished, \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
   // SMM Configuration Protocol will be found if it is already in the handle database.\r
   //\r
@@ -265,12 +282,16 @@ SMM_IPL_EVENT_NOTIFICATION  mSmmIplEvents[] = {
   //\r
   { TRUE,  TRUE,  &gEfiDxeSmmReadyToLockProtocolGuid, SmmIplReadyToLockEventNotify,      &gEfiDxeSmmReadyToLockProtocolGuid, TPL_CALLBACK, NULL },\r
   //\r
-  // Declare event notification on EndOfDxe event.  When this notification is etablished, \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
   // 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
+  // Declare event notification on EndOfDxe event.  This is used to set EndOfDxe event signaled flag.\r
+  //\r
+  { FALSE, TRUE,  &gEfiEndOfDxeEventGroupGuid,        SmmIplEndOfDxeEventNotify,         &gEfiEndOfDxeEventGroupGuid,        TPL_CALLBACK, NULL },\r
+  //\r
   // Declare event notification on the DXE Dispatch Event Group.  This event is signaled by the DXE Core\r
   // each time the DXE Core dispatcher has completed its work.  When this event is signalled, the SMM Core\r
   // if notified, so the SMM Core can dispatch SMM drivers.\r
@@ -501,7 +522,7 @@ SmmCommunicationCommunicate (
   gSmmCorePrivate->InSmm = TRUE;\r
 \r
   //\r
-  // Already in SMM and before SetVirtualAddressMap(), so call SmiManage() directly.\r
+  // Before SetVirtualAddressMap(), we are in SMM or SMRAM is open and unlocked, call SmiManage() directly.\r
   //\r
   CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommBuffer;\r
   *CommSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
@@ -556,6 +577,23 @@ SmmIplGuidedEventNotify (
   SmmCommunicationCommunicate (&mSmmCommunication, &mCommunicateHeader, &Size);\r
 }\r
 \r
+/**\r
+  Event notification that is fired when EndOfDxe Event Group is signaled.\r
+\r
+  @param  Event                 The Event that is being processed, not used.\r
+  @param  Context               Event Context, not used.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmIplEndOfDxeEventNotify (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  )\r
+{\r
+  mEndOfDxe = TRUE;\r
+}\r
+\r
 /**\r
   Event notification that is fired when DxeDispatch Event Group is signaled.\r
 \r
@@ -711,6 +749,15 @@ SmmIplReadyToLockEventNotify (
     DEBUG ((DEBUG_WARN, "SMM IPL!  DXE SMM Ready To Lock Protocol not installed before Ready To Boot signal\n"));\r
   }\r
 \r
+  if (!mEndOfDxe) {\r
+    DEBUG ((DEBUG_ERROR, "EndOfDxe Event must be signaled before DxeSmmReadyToLock Protocol installation!\n"));\r
+    REPORT_STATUS_CODE (\r
+      EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED,\r
+      (EFI_SOFTWARE_SMM_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)\r
+      );\r
+    ASSERT (FALSE);\r
+  }\r
+\r
   //\r
   // Lock the SMRAM (Note: Locking SMRAM may not be supported on all platforms)\r
   //\r
@@ -764,13 +811,13 @@ SmmIplSetVirtualAddressNotify (
 }\r
 \r
 /**\r
-  Get the fixed loadding address from image header assigned by build tool. This function only be called\r
+  Get the fixed loading address from image header assigned by build tool. This function only be called\r
   when Loading module at Fixed address feature enabled.\r
 \r
   @param  ImageContext              Pointer to the image context structure that describes the PE/COFF\r
                                     image that needs to be examined by this function.\r
   @retval EFI_SUCCESS               An fixed loading address is assigned to this image by build tools .\r
-  @retval EFI_NOT_FOUND             The image has no assigned fixed loadding address.\r
+  @retval EFI_NOT_FOUND             The image has no assigned fixed loading address.\r
 **/\r
 EFI_STATUS\r
 GetPeCoffImageFixLoadingAssignedAddress(\r
@@ -781,7 +828,7 @@ GetPeCoffImageFixLoadingAssignedAddress(
    EFI_STATUS                         Status;\r
    EFI_IMAGE_SECTION_HEADER           SectionHeader;\r
    EFI_IMAGE_OPTIONAL_HEADER_UNION    *ImgHdr;\r
-   EFI_PHYSICAL_ADDRESS               FixLoaddingAddress;\r
+   EFI_PHYSICAL_ADDRESS               FixLoadingAddress;\r
    UINT16                             Index;\r
    UINTN                              Size;\r
    UINT16                             NumberOfSections;\r
@@ -793,19 +840,17 @@ GetPeCoffImageFixLoadingAssignedAddress(
    //\r
    SmmCodeSize = EFI_PAGES_TO_SIZE (PcdGet32(PcdLoadFixAddressSmmCodePageNumber));\r
  \r
-   FixLoaddingAddress = 0;\r
+   FixLoadingAddress = 0;\r
    Status = EFI_NOT_FOUND;\r
-   SmramBase = mCurrentSmramRange->CpuStart;\r
+   SmramBase = mLMFAConfigurationTable->SmramBase;\r
    //\r
    // Get PeHeader pointer\r
    //\r
    ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset);\r
-   SectionHeaderOffset = (UINTN)(\r
-                                 ImageContext->PeCoffHeaderOffset +\r
-                                 sizeof (UINT32) +\r
-                                 sizeof (EFI_IMAGE_FILE_HEADER) +\r
-                                 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
-                                 );\r
+   SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +\r
+                         sizeof (UINT32) +\r
+                         sizeof (EFI_IMAGE_FILE_HEADER) +\r
+                         ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;\r
    NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
 \r
    //\r
@@ -833,21 +878,21 @@ GetPeCoffImageFixLoadingAssignedAddress(
        // Build tool saves the offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields in the\r
        // first section header that doesn't point to code section in image header. And there is an assumption that when the\r
        // feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers\r
-       // fields should NOT be Zero, or else, these 2 fileds should be set to Zero\r
+       // fields should NOT be Zero, or else, these 2 fields should be set to Zero\r
        //\r
        ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);\r
        if (ValueInSectionHeader != 0) {\r
          //\r
-         // Found first section header that doesn't point to code section in which uild tool saves the\r
+         // Found first section header that doesn't point to code section in which build tool saves the\r
          // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields\r
          //\r
-         FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(SmramBase + (INT64)ValueInSectionHeader);\r
+         FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(SmramBase + (INT64)ValueInSectionHeader);\r
 \r
-         if (SmramBase + SmmCodeSize > FixLoaddingAddress && SmramBase <=  FixLoaddingAddress) {\r
+         if (SmramBase + SmmCodeSize > FixLoadingAddress && SmramBase <=  FixLoadingAddress) {\r
            //\r
-           // The assigned address is valid. Return the specified loadding address\r
+           // The assigned address is valid. Return the specified loading address\r
            //\r
-           ImageContext->ImageAddress = FixLoaddingAddress;\r
+           ImageContext->ImageAddress = FixLoadingAddress;\r
            Status = EFI_SUCCESS;\r
          }\r
        }\r
@@ -855,7 +900,7 @@ GetPeCoffImageFixLoadingAssignedAddress(
      }\r
      SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
    }\r
-   DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r \n", FixLoaddingAddress, Status));\r
+   DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r \n", FixLoadingAddress, Status));\r
    return Status;\r
 }\r
 /**\r
@@ -927,6 +972,10 @@ 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
+      //\r
+      // Reserved Smram Region for SmmCore is not used, and remove it from SmramRangeCount.\r
+      //\r
+      gSmmCorePrivate->SmramRangeCount --;\r
     } else {\r
       DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR: Loading module at fixed address at address failed\n"));\r
       //\r
@@ -972,7 +1021,7 @@ ExecuteSmmCoreFromSmram (
   }\r
   \r
   ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
-  ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)(ImageContext.SectionAlignment - 1));\r
+  ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);\r
 \r
   //\r
   // Print debug message showing SMM Core load address.\r
@@ -1253,6 +1302,7 @@ GetFullSmramRanges (
   UINTN                             Index2;\r
   EFI_SMRAM_DESCRIPTOR              *FullSmramRanges;\r
   UINTN                             TempSmramRangeCount;\r
+  UINTN                             AdditionSmramRangeCount;\r
   EFI_SMRAM_DESCRIPTOR              *TempSmramRanges;\r
   UINTN                             SmramRangeCount;\r
   EFI_SMRAM_DESCRIPTOR              *SmramRanges;\r
@@ -1286,12 +1336,22 @@ GetFullSmramRanges (
     }\r
   }\r
 \r
+  //\r
+  // Reserve one entry for SMM Core in the full SMRAM ranges.\r
+  //\r
+  AdditionSmramRangeCount = 1;\r
+  if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+    //\r
+    // Reserve two entries for all SMM drivers and SMM Core in the full SMRAM ranges.\r
+    //\r
+    AdditionSmramRangeCount = 2;\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
+    *FullSmramRangeCount = SmramRangeCount + AdditionSmramRangeCount;\r
     Size = (*FullSmramRangeCount) * sizeof (EFI_SMRAM_DESCRIPTOR);\r
     FullSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocateZeroPool (Size);\r
     ASSERT (FullSmramRanges != NULL);\r
@@ -1403,10 +1463,9 @@ GetFullSmramRanges (
   ASSERT (TempSmramRangeCount <= MaxCount);\r
 \r
   //\r
-  // Sort the entries,\r
-  // and reserve one entry for SMM Core in the full SMRAM ranges.\r
+  // Sort the entries\r
   //\r
-  FullSmramRanges = AllocateZeroPool ((TempSmramRangeCount + 1) * sizeof (EFI_SMRAM_DESCRIPTOR));\r
+  FullSmramRanges = AllocateZeroPool ((TempSmramRangeCount + AdditionSmramRangeCount) * sizeof (EFI_SMRAM_DESCRIPTOR));\r
   ASSERT (FullSmramRanges != NULL);\r
   *FullSmramRangeCount = 0;\r
   do {\r
@@ -1426,7 +1485,7 @@ GetFullSmramRanges (
     TempSmramRanges[Index].PhysicalSize = 0;\r
   } while (*FullSmramRangeCount < TempSmramRangeCount);\r
   ASSERT (*FullSmramRangeCount == TempSmramRangeCount);\r
-  *FullSmramRangeCount += 1;\r
+  *FullSmramRangeCount += AdditionSmramRangeCount;\r
 \r
   FreePool (SmramRanges);\r
   FreePool (SmramReservedRanges);\r
@@ -1461,9 +1520,9 @@ SmmIplEntry (
   UINT64                          MaxSize;\r
   VOID                            *Registration;\r
   UINT64                          SmmCodeSize;\r
-  EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE    *LMFAConfigurationTable;\r
   EFI_CPU_ARCH_PROTOCOL           *CpuArch;\r
   EFI_STATUS                      SetAttrStatus;\r
+  EFI_SMRAM_DESCRIPTOR            *SmramRangeSmmDriver;\r
 \r
   //\r
   // Fill in the image handle of the SMM IPL so the SMM Core can use this as the \r
@@ -1510,7 +1569,7 @@ SmmIplEntry (
     }\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].CpuStart + gSmmCorePrivate->SmramRanges[Index].PhysicalSize - 1) <= MAX_ADDRESS) {\r
         if (gSmmCorePrivate->SmramRanges[Index].PhysicalSize >= MaxSize) {\r
           MaxSize = gSmmCorePrivate->SmramRanges[Index].PhysicalSize;\r
           mCurrentSmramRange = &gSmmCorePrivate->SmramRanges[Index];\r
@@ -1564,15 +1623,28 @@ SmmIplEntry (
       //\r
       Status = EfiGetSystemConfigurationTable (\r
                 &gLoadFixedAddressConfigurationTableGuid,\r
-               (VOID **) &LMFAConfigurationTable\r
+               (VOID **) &mLMFAConfigurationTable\r
                );\r
-      if (!EFI_ERROR (Status) && LMFAConfigurationTable != NULL) {\r
-        LMFAConfigurationTable->SmramBase = mCurrentSmramRange->CpuStart;\r
+      if (!EFI_ERROR (Status) && mLMFAConfigurationTable != NULL) {\r
+        mLMFAConfigurationTable->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
+        DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: TSEG BASE is %x. \n", mLMFAConfigurationTable->SmramBase));\r
       }\r
+\r
+      //\r
+      // Fill the Smram range for all SMM code\r
+      //\r
+      SmramRangeSmmDriver = &gSmmCorePrivate->SmramRanges[gSmmCorePrivate->SmramRangeCount - 2];\r
+      SmramRangeSmmDriver->CpuStart      = mCurrentSmramRange->CpuStart;\r
+      SmramRangeSmmDriver->PhysicalStart = mCurrentSmramRange->PhysicalStart;\r
+      SmramRangeSmmDriver->RegionState   = mCurrentSmramRange->RegionState | EFI_ALLOCATED;\r
+      SmramRangeSmmDriver->PhysicalSize  = SmmCodeSize;\r
+\r
+      mCurrentSmramRange->PhysicalSize  -= SmmCodeSize;\r
+      mCurrentSmramRange->CpuStart       = mCurrentSmramRange->CpuStart + SmmCodeSize;\r
+      mCurrentSmramRange->PhysicalStart  = mCurrentSmramRange->PhysicalStart + SmmCodeSize;\r
     }\r
     //\r
     // Load SMM Core into SMRAM and execute it from SMRAM\r