]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
MdeModule cleanup for PI:
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
index 6923181475a549a9e235f8cbffab26b978e517d4..73a6245b7e9001d8cc88e4092147afeccc35b5f9 100644 (file)
@@ -23,6 +23,11 @@ Revision History
 \r
 #include <PeiMain.h>\r
 \r
+typedef struct {\r
+  EFI_STATUS_CODE_DATA  DataHeader;\r
+  EFI_HANDLE            Handle;\r
+} PEIM_FILE_HANDLE_EXTENDED_DATA;\r
+\r
 STATIC\r
 VOID\r
 InvokePeiCore (\r
@@ -30,7 +35,6 @@ InvokePeiCore (
   VOID          *Context2\r
   );\r
 \r
-\r
 VOID\r
 DiscoverPeimsAndOrderWithApriori (\r
   IN  PEI_CORE_INSTANCE    *Private,\r
@@ -224,7 +228,7 @@ Returns:
   UINTN                               PeimCount;\r
   UINT32                              AuthenticationState;\r
   EFI_PHYSICAL_ADDRESS                EntryPoint;\r
-  EFI_PEIM_ENTRY_POINT                PeimEntryPoint;\r
+  EFI_PEIM_ENTRY_POINT2               PeimEntryPoint;\r
   BOOLEAN                             PeimNeedingDispatch;\r
   BOOLEAN                             PeimDispatchOnThisPass;\r
   UINTN                               SaveCurrentPeimCount;\r
@@ -232,12 +236,14 @@ Returns:
   EFI_PEI_FILE_HANDLE                 SaveCurrentFileHandle;\r
   VOID                                *TopOfStack;\r
   PEI_CORE_PARAMETERS                 PeiCoreParameters;\r
-  EFI_DEVICE_HANDLE_EXTENDED_DATA     ExtendedData;\r
+  PEIM_FILE_HANDLE_EXTENDED_DATA      ExtendedData;\r
+  EFI_FV_FILE_INFO                    FvFileInfo;\r
 \r
 \r
   PeiServices = &Private->PS;\r
   PeimEntryPoint = NULL;\r
   PeimFileHandle = NULL;\r
+  EntryPoint     = 0;\r
 \r
   if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
     //\r
@@ -269,10 +275,10 @@ Returns:
             //\r
             // Call the PEIM entry point\r
             //\r
-            PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint;\r
+            PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
             \r
             PERF_START (0, "PEIM", NULL, 0);\r
-            PeimEntryPoint(PeimFileHandle, &Private->PS);\r
+            PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS);\r
             PERF_END (0, "PEIM", NULL, 0);\r
           } \r
           \r
@@ -327,16 +333,28 @@ Returns:
           if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {\r
             PeimNeedingDispatch = TRUE;\r
           } else {\r
-            Status = PeiLoadImage (\r
-                       PeiServices, \r
-                       PeimFileHandle,  \r
-                       &EntryPoint, \r
-                       &AuthenticationState\r
-                       );\r
+            Status = PeiFfsGetFileInfo (PeimFileHandle, &FvFileInfo);\r
+            ASSERT_EFI_ERROR (Status);\r
+            if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
+              //\r
+              // For Fv type file, Produce new FV PPI and FV hob\r
+              //\r
+              Status = ProcessFvFile (PeiServices, PeimFileHandle, &AuthenticationState);\r
+            } else {\r
+              //\r
+              // For PEIM driver, Load its entry point\r
+              //\r
+              Status = PeiLoadImage (\r
+                         PeiServices, \r
+                         PeimFileHandle,  \r
+                         &EntryPoint, \r
+                         &AuthenticationState\r
+                         );\r
+            }\r
+\r
             if ((Status == EFI_SUCCESS)) {\r
               //\r
-              // The PEIM has its dependencies satisfied, and its entry point\r
-              // has been found, so invoke it.\r
+              // The PEIM has its dependencies satisfied, and is processed.\r
               //\r
               PERF_START (0, "PEIM", NULL, 0);\r
 \r
@@ -344,7 +362,7 @@ Returns:
 \r
               REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
                 EFI_PROGRESS_CODE,\r
-                EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN,\r
+                FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
                 (VOID *)(&ExtendedData),\r
                 sizeof (ExtendedData)\r
                 );\r
@@ -355,23 +373,32 @@ Returns:
                 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
                 //\r
                 Private->Fv[FvCount].PeimState[PeimCount]++;\r
+                \r
+                if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
+                  //\r
+                  // Call the PEIM entry point for PEIM driver\r
+                  //\r
+                  PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
+                  PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
+                }\r
 \r
-                //\r
-                // Call the PEIM entry point\r
-                //\r
-                PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint;\r
-                PeimEntryPoint (PeimFileHandle, PeiServices);\r
                 PeimDispatchOnThisPass = TRUE;\r
               }\r
 \r
               REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
                 EFI_PROGRESS_CODE,\r
-                EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END,\r
+                FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
                 (VOID *)(&ExtendedData),\r
                 sizeof (ExtendedData)\r
                 );\r
               PERF_END (0, "PEIM", NULL, 0);\r
 \r
+            } else {\r
+              //\r
+              // If PeiLoadImage fails, the section extraction PPI or Decompress PPI may not be ready,\r
+              // we flag that more Peims need to be dispatched.\r
+              //\r
+              PeimNeedingDispatch = TRUE;\r
             }\r
 \r
             //\r
@@ -445,7 +472,7 @@ Returns:
 \r
               PeiSwitchStacks (\r
                 InvokePeiCore,\r
-                (VOID*) (UINTN) PeiCore,\r
+                (VOID*) ((UINTN) EntryPoint + ((UINTN) PeiCore - (UINTN) _ModuleEntryPoint)),\r
                 (VOID*) &PeiCoreParameters,  \r
                 TopOfStack,\r
                 (VOID*)(UINTN)Private->StackBase\r
@@ -459,7 +486,7 @@ Returns:
               // 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
-              PeimEntryPoint (PeimFileHandle, PeiServices);\r
+              PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
               //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);\r
               \r
               //\r
@@ -566,8 +593,8 @@ Returns:
 \r
 --*/\r
 {\r
-  EFI_STATUS  Status;\r
-  VOID        *DepexData;\r
+  EFI_STATUS           Status;\r
+  VOID                 *DepexData;\r
 \r
   if (PeimCount < Private->AprioriCount) {\r
     //\r
@@ -575,8 +602,16 @@ Returns:
     //\r
     return TRUE;\r
   }\r
+  \r
+  //\r
+  // Depex section not in the encapsulated section. \r
+  //\r
+  Status = PeiServicesFfsFindSectionData (\r
+              EFI_SECTION_PEI_DEPEX,\r
+              FileHandle, \r
+              (VOID **)&DepexData\r
+              );\r
 \r
-  Status = PeiServicesFfsFindSectionData (EFI_SECTION_PEI_DEPEX, FileHandle, (VOID **) &DepexData);\r
   if (EFI_ERROR (Status)) {\r
     //\r
     // If there is no DEPEX, assume the module can be executed\r
@@ -666,5 +701,122 @@ InvokePeiCore (
   //\r
   // Never returns\r
   //\r
-  ASSERT_EFI_ERROR (FALSE);\r
+  ASSERT (FALSE);\r
+  CpuDeadLoop ();\r
+}\r
+\r
+/**\r
+  Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob.\r
+\r
+       @param PeiServices          Pointer to the PEI Core Services Table.\r
+       @param FileHandle               File handle of a Fv type file.\r
+  @param AuthenticationState  Pointer to attestation authentication state of image.\r
+\r
+  \r
+  @retval EFI_NOT_FOUND                                FV image can't be found.\r
+  @retval EFI_SUCCESS                                          Successfully to process it.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessFvFile (\r
+  IN  EFI_PEI_SERVICES      **PeiServices,\r
+  IN  EFI_PEI_FILE_HANDLE   FvFileHandle,\r
+  OUT UINT32                *AuthenticationState\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_PEI_FV_HANDLE     FvImageHandle;\r
+  EFI_FV_INFO           FvImageInfo;\r
+  UINT32                FvAlignment;\r
+  VOID                  *FvBuffer;\r
+  EFI_PEI_HOB_POINTERS  HobFv2;\r
+  \r
+  FvBuffer             = NULL;\r
+  *AuthenticationState = 0;\r
+\r
+  //\r
+  // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already \r
+  // been extracted.\r
+  //\r
+  HobFv2.Raw = GetHobList ();\r
+  while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {\r
+    if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name), &HobFv2.FirmwareVolume2->FileName)) {\r
+      //\r
+      // this FILE has been dispatched, it will not be dispatched again.\r
+      //\r
+      return EFI_SUCCESS;\r
+    }\r
+    HobFv2.Raw = GET_NEXT_HOB (HobFv2);\r
+  }\r
+  \r
+  //\r
+  // Find FvImage in FvFile\r
+  //\r
+  Status = PeiFfsFindSectionData (\r
+             (CONST EFI_PEI_SERVICES **) PeiServices,\r
+             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
+             FvFileHandle,\r
+             (VOID **)&FvImageHandle\r
+             );\r
+  \r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Collect FvImage Info.\r
+  //\r
+  Status = PeiFfsGetVolumeInfo (FvImageHandle, &FvImageInfo);\r
+  ASSERT_EFI_ERROR (Status);\r
+  //\r
+  // FvAlignment must be more than 8 bytes required by FvHeader structure.\r
+  //\r
+  FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16);\r
+  if (FvAlignment < 8) {\r
+    FvAlignment = 8;\r
+  }\r
+  // \r
+  // Check FvImage\r
+  //\r
+  if ((UINTN) FvImageInfo.FvStart % FvAlignment != 0) {\r
+    FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvImageInfo.FvSize), FvAlignment);\r
+    if (FvBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN) FvImageInfo.FvSize);\r
+    //\r
+    // Update FvImageInfo after reload FvImage to new aligned memory\r
+    //\r
+    PeiFfsGetVolumeInfo ((EFI_PEI_FV_HANDLE) FvBuffer, &FvImageInfo);\r
+  }\r
+  \r
+  //\r
+  // Install FvPpi and Build FvHob\r
+  //\r
+  PiLibInstallFvInfoPpi (\r
+    NULL,\r
+    FvImageInfo.FvStart,\r
+    (UINT32) FvImageInfo.FvSize,\r
+    &(FvImageInfo.FvName),\r
+    &(((EFI_FFS_FILE_HEADER*)FvFileHandle)->Name)\r
+    );\r
+\r
+  //\r
+  // Inform HOB consumer phase, i.e. DXE core, the existance of this FV\r
+  //\r
+  BuildFvHob (\r
+    (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,\r
+    FvImageInfo.FvSize\r
+  );\r
+  //\r
+  // Makes the encapsulated volume show up in DXE phase to skip processing of\r
+  // encapsulated file again.\r
+  //\r
+  BuildFv2Hob (\r
+    (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,\r
+    FvImageInfo.FvSize,\r
+    &FvImageInfo.FvName,\r
+    &(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name)\r
+    );\r
+    \r
+  return EFI_SUCCESS;\r
 }\r