]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
MdeModulePkg/PeiCore: Remove MigrateSecModulesInFv()
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
index 4c2eac1384e8e29b2578d3659b55beed3573a8c0..61d4b67c64b9ae3298f74c3ac7638ef22d8c1959 100644 (file)
@@ -952,6 +952,341 @@ PeiCheckAndSwitchStack (
   }\r
 }\r
 \r
+/**\r
+  Migrate a PEIM from temporary RAM to permanent memory.\r
+\r
+  @param PeimFileHandle       Pointer to the FFS file header of the image.\r
+  @param MigratedFileHandle   Pointer to the FFS file header of the migrated image.\r
+\r
+  @retval EFI_SUCCESS         Sucessfully migrated the PEIM to permanent memory.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MigratePeim (\r
+  IN  EFI_PEI_FILE_HANDLE     FileHandle,\r
+  IN  EFI_PEI_FILE_HANDLE     MigratedFileHandle\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_FFS_FILE_HEADER       *FileHeader;\r
+  VOID                      *Pe32Data;\r
+  VOID                      *ImageAddress;\r
+  CHAR8                     *AsciiString;\r
+  UINTN                     Index;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  FileHeader = (EFI_FFS_FILE_HEADER *) FileHandle;\r
+  ASSERT (!IS_FFS_FILE2 (FileHeader));\r
+\r
+  ImageAddress = NULL;\r
+  PeiGetPe32Data (MigratedFileHandle, &ImageAddress);\r
+  if (ImageAddress != NULL) {\r
+    DEBUG_CODE_BEGIN ();\r
+    AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress);\r
+    for (Index = 0; AsciiString[Index] != 0; Index++) {\r
+      if (AsciiString[Index] == '\\' || AsciiString[Index] == '/') {\r
+        AsciiString = AsciiString + Index + 1;\r
+        Index = 0;\r
+      } else if (AsciiString[Index] == '.') {\r
+        AsciiString[Index] = 0;\r
+      }\r
+    }\r
+    DEBUG ((DEBUG_INFO, "%a", AsciiString));\r
+    DEBUG_CODE_END ();\r
+\r
+    Pe32Data = (VOID *) ((UINTN) ImageAddress - (UINTN) MigratedFileHandle + (UINTN) FileHandle);\r
+    Status = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Migrate Status Code Callback function pointers inside an FV from temporary memory to permanent memory.\r
+\r
+  @param OrgFvHandle      Address of FV handle in temporary memory.\r
+  @param FvHandle         Address of FV handle in permanent memory.\r
+  @param FvSize           Size of the FV.\r
+\r
+**/\r
+VOID\r
+ConvertStatusCodeCallbacks (\r
+  IN  UINTN                   OrgFvHandle,\r
+  IN  UINTN                   FvHandle,\r
+  IN  UINTN                   FvSize\r
+  )\r
+{\r
+  EFI_PEI_HOB_POINTERS    Hob;\r
+  UINTN                   *NumberOfEntries;\r
+  UINTN                   *CallbackEntry;\r
+  UINTN                   Index;\r
+\r
+  Hob.Raw  = GetFirstGuidHob (&gStatusCodeCallbackGuid);\r
+  while (Hob.Raw != NULL) {\r
+    NumberOfEntries = GET_GUID_HOB_DATA (Hob);\r
+    CallbackEntry   = NumberOfEntries + 1;\r
+    for (Index = 0; Index < *NumberOfEntries; Index++) {\r
+      if (((VOID *) CallbackEntry[Index]) != NULL) {\r
+        if ((CallbackEntry[Index] >= OrgFvHandle) && (CallbackEntry[Index] < (OrgFvHandle + FvSize))) {\r
+          DEBUG ((\r
+            DEBUG_INFO,\r
+            "Migrating CallbackEntry[%Lu] from 0x%0*Lx to ",\r
+            (UINT64)Index,\r
+            (sizeof CallbackEntry[Index]) * 2,\r
+            (UINT64)CallbackEntry[Index]\r
+            ));\r
+          if (OrgFvHandle > FvHandle) {\r
+            CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - FvHandle);\r
+          } else {\r
+            CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - OrgFvHandle);\r
+          }\r
+          DEBUG ((\r
+            DEBUG_INFO,\r
+            "0x%0*Lx\n",\r
+            (sizeof CallbackEntry[Index]) * 2,\r
+            (UINT64)CallbackEntry[Index]\r
+            ));\r
+        }\r
+      }\r
+    }\r
+    Hob.Raw = GET_NEXT_HOB (Hob);\r
+    Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw);\r
+  }\r
+}\r
+\r
+/**\r
+  Migrates PEIMs in the given firmware volume.\r
+\r
+  @param Private          Pointer to the PeiCore's private data structure.\r
+  @param FvIndex          The firmware volume index to migrate.\r
+  @param OrgFvHandle      The handle to the firmware volume in temporary memory.\r
+  @param FvHandle         The handle to the firmware volume in permanent memory.\r
+\r
+  @retval   EFI_SUCCESS           The PEIMs in the FV were migrated successfully\r
+  @retval   EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MigratePeimsInFv (\r
+  IN PEI_CORE_INSTANCE    *Private,\r
+  IN  UINTN               FvIndex,\r
+  IN  UINTN               OrgFvHandle,\r
+  IN  UINTN               FvHandle\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  volatile UINTN          FileIndex;\r
+  EFI_PEI_FILE_HANDLE     MigratedFileHandle;\r
+  EFI_PEI_FILE_HANDLE     FileHandle;\r
+\r
+  if (Private == NULL || FvIndex >= Private->FvCount) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Private->Fv[FvIndex].ScanFv) {\r
+    for (FileIndex = 0; FileIndex < Private->Fv[FvIndex].PeimCount; FileIndex++) {\r
+      if (Private->Fv[FvIndex].FvFileHandles[FileIndex] != NULL) {\r
+        FileHandle = Private->Fv[FvIndex].FvFileHandles[FileIndex];\r
+\r
+        MigratedFileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) FileHandle - OrgFvHandle + FvHandle);\r
+\r
+        DEBUG ((DEBUG_VERBOSE, "    Migrating FileHandle %2d ", FileIndex));\r
+        Status = MigratePeim (FileHandle, MigratedFileHandle);\r
+        DEBUG ((DEBUG_VERBOSE, "\n"));\r
+        ASSERT_EFI_ERROR (Status);\r
+\r
+        if (!EFI_ERROR (Status)) {\r
+          Private->Fv[FvIndex].FvFileHandles[FileIndex] = MigratedFileHandle;\r
+          if (FvIndex == Private->CurrentPeimFvCount) {\r
+            Private->CurrentFvFileHandles[FileIndex] = MigratedFileHandle;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Migrate FVs out of temporary RAM before the cache is flushed.\r
+\r
+  @param Private         PeiCore's private data structure\r
+  @param SecCoreData     Points to a data structure containing information about the PEI core's operating\r
+                         environment, such as the size and location of temporary RAM, the stack location and\r
+                         the BFV location.\r
+\r
+  @retval EFI_SUCCESS           Succesfully migrated installed FVs from temporary RAM to permanent memory.\r
+  @retval EFI_OUT_OF_RESOURCES  Insufficient memory exists to allocate needed pages.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EvacuateTempRam (\r
+  IN PEI_CORE_INSTANCE            *Private,\r
+  IN CONST EFI_SEC_PEI_HAND_OFF   *SecCoreData\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  volatile UINTN                FvIndex;\r
+  volatile UINTN                FvChildIndex;\r
+  UINTN                         ChildFvOffset;\r
+  EFI_FIRMWARE_VOLUME_HEADER    *FvHeader;\r
+  EFI_FIRMWARE_VOLUME_HEADER    *ChildFvHeader;\r
+  EFI_FIRMWARE_VOLUME_HEADER    *MigratedFvHeader;\r
+  EFI_FIRMWARE_VOLUME_HEADER    *RawDataFvHeader;\r
+  EFI_FIRMWARE_VOLUME_HEADER    *MigratedChildFvHeader;\r
+\r
+  PEI_CORE_FV_HANDLE            PeiCoreFvHandle;\r
+  EFI_PEI_CORE_FV_LOCATION_PPI  *PeiCoreFvLocationPpi;\r
+  EDKII_MIGRATED_FV_INFO        MigratedFvInfo;\r
+\r
+  ASSERT (Private->PeiMemoryInstalled);\r
+\r
+  DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary RAM.\n"));\r
+\r
+  //\r
+  // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory.\r
+  //\r
+  Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **) &Private->Ps, &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **) &PeiCoreFvLocationPpi);\r
+  if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) {\r
+    PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) PeiCoreFvLocationPpi->PeiCoreFvLocation;\r
+  } else {\r
+    PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) SecCoreData->BootFirmwareVolumeBase;\r
+  }\r
+  for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {\r
+    if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) {\r
+      CopyMem (&PeiCoreFvHandle, &Private->Fv[FvIndex], sizeof (PEI_CORE_FV_HANDLE));\r
+      break;\r
+    }\r
+  }\r
+  Status = EFI_SUCCESS;\r
+\r
+  ConvertPeiCorePpiPointers (Private, &PeiCoreFvHandle);\r
+\r
+  for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {\r
+    FvHeader = Private->Fv[FvIndex].FvHeader;\r
+    ASSERT (FvHeader != NULL);\r
+    ASSERT (FvIndex < Private->FvCount);\r
+\r
+    DEBUG ((DEBUG_VERBOSE, "FV[%02d] at 0x%x.\n", FvIndex, (UINTN) FvHeader));\r
+    if (\r
+      !(\r
+        ((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader >= Private->PhysicalMemoryBegin) &&\r
+        (((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop)\r
+        )\r
+      ) {\r
+      //\r
+      // Allocate page to save the rebased PEIMs, the PEIMs will get dispatched later.\r
+      //\r
+      Status =  PeiServicesAllocatePages (\r
+                  EfiBootServicesCode,\r
+                  EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),\r
+                  (EFI_PHYSICAL_ADDRESS *) &MigratedFvHeader\r
+                  );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      //\r
+      // Allocate pool to save the raw PEIMs, which is used to keep consistent context across\r
+      // multiple boot and PCR0 will keep the same no matter if the address of allocated page is changed.\r
+      //\r
+      Status =  PeiServicesAllocatePages (\r
+                  EfiBootServicesCode,\r
+                  EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),\r
+                  (EFI_PHYSICAL_ADDRESS *) &RawDataFvHeader\r
+                  );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      DEBUG ((\r
+        DEBUG_VERBOSE,\r
+        "  Migrating FV[%d] from 0x%08X to 0x%08X\n",\r
+        FvIndex,\r
+        (UINTN) FvHeader,\r
+        (UINTN) MigratedFvHeader\r
+        ));\r
+\r
+      //\r
+      // Copy the context to the rebased pages and raw pages, and create hob to save the\r
+      // information. The MigratedFvInfo HOB will never be produced when\r
+      // PcdMigrateTemporaryRamFirmwareVolumes is FALSE, because the PCD control the\r
+      // feature.\r
+      //\r
+      CopyMem (MigratedFvHeader, FvHeader, (UINTN) FvHeader->FvLength);\r
+      CopyMem (RawDataFvHeader, MigratedFvHeader, (UINTN) FvHeader->FvLength);\r
+      MigratedFvInfo.FvOrgBase  = (UINT32) (UINTN) FvHeader;\r
+      MigratedFvInfo.FvNewBase  = (UINT32) (UINTN) MigratedFvHeader;\r
+      MigratedFvInfo.FvDataBase = (UINT32) (UINTN) RawDataFvHeader;\r
+      MigratedFvInfo.FvLength   = (UINT32) (UINTN) FvHeader->FvLength;\r
+      BuildGuidDataHob (&gEdkiiMigratedFvInfoGuid, &MigratedFvInfo, sizeof (MigratedFvInfo));\r
+\r
+      //\r
+      // Migrate any children for this FV now\r
+      //\r
+      for (FvChildIndex = FvIndex; FvChildIndex < Private->FvCount; FvChildIndex++) {\r
+        ChildFvHeader = Private->Fv[FvChildIndex].FvHeader;\r
+        if (\r
+          ((UINTN) ChildFvHeader > (UINTN) FvHeader) &&\r
+          (((UINTN) ChildFvHeader + ChildFvHeader->FvLength) < ((UINTN) FvHeader) + FvHeader->FvLength)\r
+          ) {\r
+          DEBUG ((DEBUG_VERBOSE, "    Child FV[%02d] is being migrated.\n", FvChildIndex));\r
+          ChildFvOffset = (UINTN) ChildFvHeader - (UINTN) FvHeader;\r
+          DEBUG ((DEBUG_VERBOSE, "    Child FV offset = 0x%x.\n", ChildFvOffset));\r
+          MigratedChildFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) MigratedFvHeader + ChildFvOffset);\r
+          Private->Fv[FvChildIndex].FvHeader = MigratedChildFvHeader;\r
+          Private->Fv[FvChildIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedChildFvHeader;\r
+          DEBUG ((DEBUG_VERBOSE, "    Child migrated FV header at 0x%x.\n", (UINTN) MigratedChildFvHeader));\r
+\r
+          Status =  MigratePeimsInFv (Private, FvChildIndex, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);\r
+          ASSERT_EFI_ERROR (Status);\r
+\r
+          ConvertPpiPointersFv (\r
+            Private,\r
+            (UINTN) ChildFvHeader,\r
+            (UINTN) MigratedChildFvHeader,\r
+            (UINTN) ChildFvHeader->FvLength - 1\r
+            );\r
+\r
+          ConvertStatusCodeCallbacks (\r
+            (UINTN) ChildFvHeader,\r
+            (UINTN) MigratedChildFvHeader,\r
+            (UINTN) ChildFvHeader->FvLength - 1\r
+            );\r
+\r
+          ConvertFvHob (Private, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);\r
+        }\r
+      }\r
+      Private->Fv[FvIndex].FvHeader = MigratedFvHeader;\r
+      Private->Fv[FvIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedFvHeader;\r
+\r
+      Status = MigratePeimsInFv (Private, FvIndex, (UINTN) FvHeader, (UINTN) MigratedFvHeader);\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      ConvertPpiPointersFv (\r
+        Private,\r
+        (UINTN) FvHeader,\r
+        (UINTN) MigratedFvHeader,\r
+        (UINTN) FvHeader->FvLength - 1\r
+        );\r
+\r
+      ConvertStatusCodeCallbacks (\r
+        (UINTN) FvHeader,\r
+        (UINTN) MigratedFvHeader,\r
+        (UINTN) FvHeader->FvLength - 1\r
+        );\r
+\r
+      ConvertFvHob (Private, (UINTN) FvHeader, (UINTN) MigratedFvHeader);\r
+    }\r
+  }\r
+\r
+  RemoveFvHobsInTemporaryMemory (Private);\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Conduct PEIM dispatch.\r
 \r
@@ -988,7 +1323,11 @@ PeiDispatcher (
   PeimFileHandle = NULL;\r
   EntryPoint     = 0;\r
 \r
-  if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {\r
+  if ((Private->PeiMemoryInstalled) &&\r
+      (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||\r
+       (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||\r
+       PcdGetBool (PcdShadowPeimOnS3Boot))\r
+    ) {\r
     //\r
     // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile\r
     // update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE.\r
@@ -1187,13 +1526,17 @@ PeiDispatcher (
             PeiCheckAndSwitchStack (SecCoreData, Private);\r
 \r
             if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW) &&   \\r
-                (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {\r
+                (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||\r
+                 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||\r
+                 PcdGetBool (PcdShadowPeimOnS3Boot))\r
+              ) {\r
               //\r
               // If memory is available we shadow images by default for performance reasons.\r
               // We call the entry point a 2nd time so the module knows it's shadowed.\r
               //\r
               //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);\r
-              if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot)) {\r
+              if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot) &&\r
+                  !PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {\r
                 //\r
                 // Load PEIM into Memory for Register for shadow PEIM.\r
                 //\r