]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Sample/Tools/Source/Common/FvLib.c
1) Sync EdkCompatibilityPkg with EDK 1.04. The changes includes:
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / Common / FvLib.c
index 4b2bf8114755f91409e07c103e2f9bf5cd5e5b44..d660c07f4b04303a72cc373a1c18d3e670a3b3da 100644 (file)
@@ -390,6 +390,91 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
+EFI_STATUS\r
+SearchSectionByType (\r
+  IN EFI_FILE_SECTION_POINTER  FirstSection,\r
+  IN UINT8                     *SearchEnd,\r
+  IN EFI_SECTION_TYPE          SectionType,\r
+  IN OUT UINTN                 *StartIndex,\r
+  IN UINTN                     Instance,\r
+  OUT EFI_FILE_SECTION_POINTER *Section\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Helper function to search a sequence of sections from the section pointed\r
+  by FirstSection to SearchEnd for the Instance-th section of type SectionType.\r
+  The current counter is saved in StartIndex and when the section is found, it's\r
+  saved in Section. GUID-defined sections, if special processing is not required,\r
+  are searched recursively in a depth-first manner.\r
+\r
+Arguments:\r
+\r
+  FirstSection The first section to start searching from.\r
+  SearchEnd    The end address to stop search.\r
+  SectionType  The type of section to search.\r
+  StartIndex   The current counter is saved.\r
+  Instance     The requested n-th section number.\r
+  Section      The found section returned.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             The function completed successfully.\r
+  EFI_NOT_FOUND           The section is not found.\r
+--*/\r
+{\r
+  EFI_FILE_SECTION_POINTER  CurrentSection;\r
+  EFI_FILE_SECTION_POINTER  InnerSection;\r
+  EFI_STATUS                Status;\r
+  UINTN                     SectionSize;\r
+\r
+  CurrentSection = FirstSection;\r
+\r
+  while ((UINTN) CurrentSection.CommonHeader < (UINTN) SearchEnd) {\r
+    if (CurrentSection.CommonHeader->Type == SectionType) {\r
+      (*StartIndex)++;\r
+    }\r
+\r
+    if (*StartIndex == Instance) {\r
+      *Section = CurrentSection;\r
+      return EFI_SUCCESS;\r
+    }\r
+    //\r
+    // If the requesting section is not GUID-defined and\r
+    // we find a GUID-defined section that doesn't need\r
+    // special processing, go ahead to search the requesting\r
+    // section inside the GUID-defined section.\r
+    //\r
+    if (SectionType != EFI_SECTION_GUID_DEFINED &&\r
+        CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED &&\r
+        !(CurrentSection.GuidDefinedSection->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) {\r
+      InnerSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *)\r
+        ((UINTN) CurrentSection.CommonHeader + CurrentSection.GuidDefinedSection->DataOffset);\r
+      SectionSize = CurrentSection.CommonHeader->Size[0] +\r
+        (CurrentSection.CommonHeader->Size[1] << 8) + \r
+        (CurrentSection.CommonHeader->Size[2] << 16);\r
+      Status = SearchSectionByType (\r
+                 InnerSection,\r
+                 (UINT8 *) ((UINTN) CurrentSection.CommonHeader + SectionSize),\r
+                 SectionType,\r
+                 StartIndex,\r
+                 Instance,\r
+                 Section\r
+                 );\r
+      if (!EFI_ERROR (Status)) {\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+    //\r
+    // Find next section (including compensating for alignment issues.\r
+    //\r
+    CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2));\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
 EFI_STATUS\r
 GetSectionByType (\r
   IN EFI_FFS_FILE_HEADER          *File,\r
@@ -403,7 +488,8 @@ Routine Description:
 \r
   Find a section in a file by type and instance.  An instance of 1 is the first \r
   instance.  The function will return NULL if a matching section cannot be found.\r
-  The function will not handle encapsulating sections.\r
+  GUID-defined sections, if special processing is not needed, are handled in a\r
+  depth-first manner.\r
 \r
 Arguments:\r
 \r
@@ -448,28 +534,24 @@ Returns:
   //\r
   CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + sizeof (EFI_FFS_FILE_HEADER));\r
 \r
-  //\r
-  // Loop as long as we have a valid file\r
-  //\r
-  while ((UINTN) CurrentSection.CommonHeader < (UINTN) File + GetLength (File->Size)) {\r
-    if (CurrentSection.CommonHeader->Type == SectionType) {\r
-      SectionCount++;\r
-    }\r
+  Status = SearchSectionByType (\r
+             CurrentSection,\r
+             (UINT8 *) ((UINTN) File + GetLength (File->Size)),\r
+             SectionType,\r
+             &SectionCount,\r
+             Instance,\r
+             Section\r
+             );\r
 \r
-    if (SectionCount == Instance) {\r
-      *Section = CurrentSection;\r
-      return EFI_SUCCESS;\r
-    }\r
+  if (!EFI_ERROR (Status)) {\r
+    return EFI_SUCCESS;\r
+  } else {\r
     //\r
-    // Find next section (including compensating for alignment issues.\r
+    // Section not found\r
     //\r
-    CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2));\r
+    (*Section).Code16Section = NULL;\r
+    return EFI_NOT_FOUND;\r
   }\r
-  //\r
-  // Section not found\r
-  //\r
-  (*Section).Code16Section = NULL;\r
-  return EFI_NOT_FOUND;\r
 }\r
 //\r
 // will not parse compressed sections\r