]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/FwVol/FwVol.c
Enable PeiCore to dispatch the encapsulated fv images with depex expression. This...
[mirror_edk2.git] / MdeModulePkg / Core / Pei / FwVol / FwVol.c
index 57b45d0fe082be24e5e0b2c3c11fe940cfbd326a..621fb16f185ceaea5ebb5c59b4057e4296f1a336 100644 (file)
@@ -258,7 +258,8 @@ Returns:
         }\r
       } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) {\r
         if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || \r
-            (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) { \r
+            (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) ||\r
+            (FfsFileHeader->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE)) { \r
           \r
           *FileHeader = FfsFileHeader;\r
           return EFI_SUCCESS;\r
@@ -366,8 +367,15 @@ Returns:
   UINT8                                 FvCount;\r
   EFI_PEI_FIRMWARE_VOLUME_INFO_PPI      *Fv;\r
   PEI_CORE_INSTANCE                     *PrivateData;\r
+  EFI_PEI_FILE_HANDLE                   FileHandle;\r
+  VOID                                  *DepexData;\r
+  UINT32                                AuthenticationStatus;\r
+  EFI_STATUS                            Status;\r
   \r
-  PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
+  FileHandle   = NULL;\r
+  DepexData    = NULL;\r
+  Status       = EFI_SUCCESS;\r
+  PrivateData  = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
 \r
   if (PrivateData->FvCount >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
     ASSERT (FALSE);\r
@@ -375,19 +383,53 @@ Returns:
 \r
   Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi;\r
 \r
-   if (CompareGuid (&Fv->FvFormat, &gEfiFirmwareFileSystem2Guid)) {\r
-     for (FvCount = 0; FvCount < PrivateData->FvCount; FvCount ++) {\r
-       if ((UINTN)PrivateData->Fv[FvCount].FvHeader == (UINTN)Fv->FvInfo) {\r
-         return EFI_SUCCESS;\r
-       }\r
-     }\r
+  if (CompareGuid (&Fv->FvFormat, &gEfiFirmwareFileSystem2Guid)) {\r
+    for (FvCount = 0; FvCount < PrivateData->FvCount; FvCount ++) {\r
+      if ((UINTN)PrivateData->Fv[FvCount].FvHeader == (UINTN)Fv->FvInfo) {\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
     PrivateData->Fv[PrivateData->FvCount++].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv->FvInfo;\r
-  }\r
 \r
-  //\r
-  // Allways add to the All list\r
-  //\r
-  PrivateData->AllFv[PrivateData->AllFvCount++] = (EFI_PEI_FV_HANDLE)Fv->FvInfo;\r
+    //\r
+    // Only add FileSystem2 Fv to the All list\r
+    //\r
+    PrivateData->AllFv[PrivateData->AllFvCount++] = (EFI_PEI_FV_HANDLE)Fv->FvInfo;\r
+    \r
+    DEBUG ((EFI_D_INFO, "The %dth FvImage start address is 0x%10p and size is 0x%08x\n", PrivateData->AllFvCount, (VOID *) Fv->FvInfo, Fv->FvInfoSize));\r
+    //\r
+    // Preprocess all FV type files in this new FileSystem2 Fv image\r
+    //\r
+    do {\r
+      Status = PeiFindFileEx (\r
+                 (EFI_PEI_FV_HANDLE)Fv->FvInfo, \r
+                 NULL, \r
+                 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, \r
+                 &FileHandle, \r
+                 NULL\r
+                 );\r
+      if (!EFI_ERROR (Status)) {\r
+        Status = PeiFfsFindSectionData (\r
+                    (CONST EFI_PEI_SERVICES **) PeiServices,\r
+                    EFI_SECTION_PEI_DEPEX,\r
+                    FileHandle, \r
+                    (VOID **)&DepexData\r
+                    );\r
+        if (!EFI_ERROR (Status)) {\r
+          if (!PeimDispatchReadiness (PeiServices, DepexData)) {\r
+            //\r
+            // Dependency is not satisfied.\r
+            //\r
+            continue;\r
+          }\r
+        }\r
+        //\r
+        // Process FvFile to install FvInfo ppi and build FvHob\r
+        // \r
+        ProcessFvFile (PeiServices, FileHandle, &AuthenticationStatus);\r
+      }\r
+    } while (FileHandle != NULL);\r
+  }\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -398,25 +440,21 @@ PeiFfsProcessSection (
   IN EFI_SECTION_TYPE           SectionType,\r
   IN EFI_COMMON_SECTION_HEADER  *Section,\r
   IN UINTN                      SectionSize,\r
-  OUT VOID                      **OutputBuffer,\r
-  OUT UINTN                     *OutputSize,\r
-  OUT UINT32                    *Authentication\r
+  OUT VOID                      **OutputBuffer\r
   )\r
 /*++\r
 \r
 Routine Description:\r
 \r
   Go through the file to search SectionType section,\r
-  when meeting an encapsuled section, search recursively\r
+  when meeting an encapsuled section. \r
   \r
 Arguments:\r
-  PeiServices  - Pointer to the PEI Core Services Table.\r
+  PeiServices  - General purpose services available to every PEIM.\r
   SearchType   - Filter to find only section of this type.\r
   Section      - From where to search.\r
   SectionSize  - The file size to search.\r
   OutputBuffer - Pointer to the section to search.\r
-  OutputSize   - The size of the section to search.\r
-  Authentication -  Authenticate the section.\r
 \r
 Returns:\r
   EFI_STATUS\r
@@ -426,58 +464,95 @@ Returns:
   EFI_STATUS                              Status;\r
   UINT32                                  SectionLength;\r
   UINT32                                  ParsedLength;\r
-  EFI_GUID_DEFINED_SECTION                *GuidSection; \r
   EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI   *GuidSectionPpi;\r
-  EFI_COMPRESSION_SECTION                 *CompressionSection;\r
   EFI_PEI_DECOMPRESS_PPI                  *DecompressPpi;\r
   VOID                                    *PpiOutput;\r
   UINTN                                   PpiOutputSize;\r
+  UINTN                                   Index;\r
+  UINT32                                  Authentication;\r
+  PEI_CORE_INSTANCE                       *PrivateData;\r
 \r
+  PrivateData   = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
   *OutputBuffer = NULL;\r
-  ParsedLength = 0;\r
+  ParsedLength  = 0;\r
+  Index         = 0;\r
+  Status        = EFI_NOT_FOUND;\r
+  PpiOutput     = NULL;\r
+  PpiOutputSize = 0;\r
   while (ParsedLength < SectionSize) {\r
     if (Section->Type == SectionType) {\r
       *OutputBuffer = (VOID *)(Section + 1);\r
       return EFI_SUCCESS;\r
-    } else if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
-      GuidSection = (EFI_GUID_DEFINED_SECTION *)Section;\r
-      Status = PeiServicesLocatePpi (&GuidSection->SectionDefinitionGuid, 0, NULL, (VOID **) &GuidSectionPpi);\r
-      if (!EFI_ERROR (Status)) {\r
-        Status = GuidSectionPpi->ExtractSection (\r
-                                  GuidSectionPpi,\r
-                                  Section,\r
-                                  &PpiOutput,\r
-                                  &PpiOutputSize,\r
-                                  Authentication\r
-                                  );\r
-        if (!EFI_ERROR (Status)) {\r
+    } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) {\r
+      //\r
+      // Check the encapsulated section is extracted into the cache data.\r
+      //\r
+      for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index ++) {\r
+        if (Section == PrivateData->CacheSection.Section[Index]) {\r
+          PpiOutput     = PrivateData->CacheSection.SectionData[Index];\r
+          PpiOutputSize = PrivateData->CacheSection.SectionSize[Index];\r
+          //\r
+          // Search section directly from the cache data.\r
+          //\r
           return PeiFfsProcessSection (\r
                   PeiServices,\r
                   SectionType, \r
                   PpiOutput, \r
                   PpiOutputSize, \r
-                  OutputBuffer, \r
-                  OutputSize, \r
-                  Authentication\r
+                  OutputBuffer \r
                   );\r
         }\r
       }\r
-    } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
-      CompressionSection = (EFI_COMPRESSION_SECTION *)Section;\r
-      Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi);\r
-      if (!EFI_ERROR (Status)) {\r
-        Status = DecompressPpi->Decompress (\r
-                                  DecompressPpi,\r
-                                  CompressionSection,\r
-                                  &PpiOutput,\r
-                                  &PpiOutputSize\r
-                                  );\r
+      \r
+      Status = EFI_NOT_FOUND;\r
+      if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
+        Status = PeiServicesLocatePpi (\r
+                   &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid, \r
+                   0, \r
+                   NULL, \r
+                   (VOID **) &GuidSectionPpi\r
+                   );\r
         if (!EFI_ERROR (Status)) {\r
-          return PeiFfsProcessSection (\r
-                  PeiServices, SectionType, PpiOutput, PpiOutputSize, OutputBuffer, OutputSize, Authentication\r
-                  );\r
+          Status = GuidSectionPpi->ExtractSection (\r
+                                    GuidSectionPpi,\r
+                                    Section,\r
+                                    &PpiOutput,\r
+                                    &PpiOutputSize,\r
+                                    &Authentication\r
+                                    );\r
+        }\r
+      } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
+        Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi);\r
+        if (!EFI_ERROR (Status)) {\r
+          Status = DecompressPpi->Decompress (\r
+                                    DecompressPpi,\r
+                                    (CONST EFI_COMPRESSION_SECTION*) Section,\r
+                                    &PpiOutput,\r
+                                    &PpiOutputSize\r
+                                    );\r
         }\r
       }\r
+      \r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Update cache section data.\r
+        //\r
+        if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) {\r
+          PrivateData->CacheSection.AllSectionCount ++;\r
+        }\r
+        PrivateData->CacheSection.Section [PrivateData->CacheSection.SectionIndex]     = Section;\r
+        PrivateData->CacheSection.SectionData [PrivateData->CacheSection.SectionIndex] = PpiOutput;\r
+        PrivateData->CacheSection.SectionSize [PrivateData->CacheSection.SectionIndex] = PpiOutputSize;\r
+        PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER;\r
+        \r
+        return PeiFfsProcessSection (\r
+                PeiServices,\r
+                SectionType, \r
+                PpiOutput, \r
+                PpiOutputSize, \r
+                OutputBuffer \r
+                );\r
+      }\r
     }\r
 \r
     //\r
@@ -526,9 +601,6 @@ Returns:
   EFI_FFS_FILE_HEADER                     *FfsFileHeader;\r
   UINT32                                  FileSize;\r
   EFI_COMMON_SECTION_HEADER               *Section;\r
-  UINTN                                   OutputSize;\r
-  UINT32                                  AuthenticationStatus;\r
-\r
 \r
   FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);\r
 \r
@@ -542,13 +614,11 @@ Returns:
   FileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
 \r
   return PeiFfsProcessSection (\r
-          PeiServices, \r
+          PeiServices,\r
           SectionType, \r
           Section, \r
           FileSize, \r
-          SectionData, \r
-          &OutputSize, \r
-          &AuthenticationStatus\r
+          SectionData\r
           );\r
 }\r
 \r
@@ -601,7 +671,7 @@ PeiFvFindNextVolume (
 \r
 Routine Description:\r
 \r
-  Return the BFV location\r
+  Return the firmware volumes.\r
 \r
   BugBug -- Move this to the location of this code to where the\r
   other FV and FFS support code lives.\r
@@ -761,21 +831,32 @@ Returns:
   \r
 --*/    \r
 {\r
-  EFI_FIRMWARE_VOLUME_HEADER             *FwVolHeader;\r
+  EFI_FIRMWARE_VOLUME_HEADER             FwVolHeader;\r
   EFI_FIRMWARE_VOLUME_EXT_HEADER         *FwVolExHeaderInfo;\r
 \r
   if (VolumeInfo == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+  \r
+  //\r
+  // VolumeHandle may not align at 8 byte, \r
+  // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte. \r
+  // So, Copy FvHeader into the local FvHeader structure.\r
+  //\r
+  CopyMem (&FwVolHeader, VolumeHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+  //\r
+  // Check Fv Image Signature\r
+  //\r
+  if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  VolumeInfo->FvAttributes = FwVolHeader.Attributes;\r
+  VolumeInfo->FvStart = (VOID *) VolumeHandle;\r
+  VolumeInfo->FvSize = FwVolHeader.FvLength;\r
+  CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));\r
 \r
-  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(VolumeHandle);\r
-  VolumeInfo->FvAttributes = FwVolHeader->Attributes;\r
-  VolumeInfo->FvStart = FwVolHeader;\r
-  VolumeInfo->FvSize = FwVolHeader->FvLength;\r
-  CopyMem (&VolumeInfo->FvFormat, &FwVolHeader->FileSystemGuid,sizeof(EFI_GUID));\r
-\r
-  if (FwVolHeader->ExtHeaderOffset != 0) {\r
-    FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset);\r
+  if (FwVolHeader.ExtHeaderOffset != 0) {\r
+    FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)VolumeHandle) + FwVolHeader.ExtHeaderOffset);\r
     CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));\r
   }\r
   return EFI_SUCCESS;\r