]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
Enable PeiCore to dispatch the encapsulated fv images with depex expression. This...
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
index 7294d85c6ce10ccc0eefe663052d1e5bb32ea3ed..5a140ed7bdfd16abdc625809a1d21fef0e48b278 100644 (file)
@@ -30,7 +30,6 @@ InvokePeiCore (
   VOID          *Context2\r
   );\r
 \r
-\r
 VOID\r
 DiscoverPeimsAndOrderWithApriori (\r
   IN  PEI_CORE_INSTANCE    *Private,\r
@@ -55,15 +54,15 @@ Returns:
 {\r
   EFI_STATUS                          Status;\r
   EFI_PEI_FV_HANDLE                   FileHandle;\r
-  EFI_PEI_FV_HANDLE                   AprioriFileHandle;\r
+  EFI_PEI_FILE_HANDLE                 AprioriFileHandle;\r
   EFI_GUID                            *Apriori;\r
   UINTN                               Index;\r
   UINTN                               Index2;\r
   UINTN                               PeimIndex;\r
   UINTN                               PeimCount;\r
   EFI_GUID                            *Guid;\r
-  EFI_PEI_FV_HANDLE                   TempFileHandles[PEI_CORE_MAX_PEIM_PER_FV];\r
-  EFI_GUID                            FileGuid[PEI_CORE_MAX_PEIM_PER_FV];\r
+  EFI_PEI_FV_HANDLE                   TempFileHandles[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
+  EFI_GUID                            FileGuid[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
 \r
   //\r
   // Walk the FV and find all the PEIMs and the Apriori file.\r
@@ -84,7 +83,7 @@ Returns:
   //\r
   // Go ahead to scan this Fv, and cache FileHandles within it.\r
   //\r
-  for (PeimCount = 0; PeimCount < PEI_CORE_MAX_PEIM_PER_FV; PeimCount++) {\r
+  for (PeimCount = 0; PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {\r
     Status = PeiFindFileEx (\r
                 VolumeHandle, \r
                 NULL, \r
@@ -104,7 +103,7 @@ Returns:
     //\r
     // Read the Apriori file\r
     //\r
-    Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, &AprioriFileHandle, (VOID **) &Apriori);\r
+    Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);\r
     if (!EFI_ERROR (Status)) {\r
       //\r
       // Calculate the number of PEIMs in the A Priori list\r
@@ -233,11 +232,13 @@ Returns:
   VOID                                *TopOfStack;\r
   PEI_CORE_PARAMETERS                 PeiCoreParameters;\r
   EFI_DEVICE_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
@@ -249,7 +250,7 @@ Returns:
     SaveCurrentFileHandle =  Private->CurrentFileHandle;\r
 \r
     for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {\r
-      for (Index2 = 0; (Index2 < PEI_CORE_MAX_PEIM_PER_FV) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {\r
+      for (Index2 = 0; (Index2 < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {\r
         if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {\r
           PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];  \r
           Status = PeiLoadImage (\r
@@ -318,7 +319,7 @@ Returns:
       // Start to dispatch all modules within the current Fv.\r
       //\r
       for (PeimCount = Private->CurrentPeimCount; \r
-           (PeimCount < PEI_CORE_MAX_PEIM_PER_FV) && (Private->CurrentFvFileHandles[PeimCount] != NULL); \r
+           (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL); \r
            PeimCount++) {\r
         Private->CurrentPeimCount  = PeimCount;\r
         PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];\r
@@ -327,16 +328,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
@@ -355,12 +368,17 @@ Returns:
                 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
                 //\r
                 Private->Fv[FvCount].PeimState[PeimCount]++;\r
-\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_POINT)(UINTN)EntryPoint;\r
+                  PeimEntryPoint (PeimFileHandle, PeiServices);\r
+                }\r
                 //\r
-                // Call the PEIM entry point\r
+                // One module has been dispatched.\r
                 //\r
-                PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint;\r
-                PeimEntryPoint (PeimFileHandle, PeiServices);\r
                 PeimDispatchOnThisPass = TRUE;\r
               }\r
 \r
@@ -372,6 +390,12 @@ Returns:
                 );\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 +469,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
@@ -566,8 +590,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 +599,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 +698,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