]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/Common/FvLib.c
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / C / Common / FvLib.c
index dc50e877e64e3417c01b6665ac5bc06562300010..82dc557bb7db04eb8139814295cc8a9504235481 100644 (file)
@@ -1,21 +1,8 @@
 /** @file\r
+These functions assist in parsing and manipulating a Firmware Volume.\r
 \r
-Copyright (c) 2004 - 2008, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
-are licensed and made available under the terms and conditions of the BSD License         \r
-which accompanies this distribution.  The full text of the license may be found at        \r
-http://opensource.org/licenses/bsd-license.php                                            \r
-                                                                                          \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
-\r
-Module Name:\r
-\r
-  FvLib.c\r
-\r
-Abstract:\r
-\r
-  These functions assist in parsing and manipulating a Firmware Volume.\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -51,9 +38,9 @@ Arguments:
 \r
   Fv            Buffer containing the FV.\r
   FvLength      Length of the FV\r
-    \r
+\r
 Returns:\r
\r
+\r
   EFI_SUCCESS             Function Completed successfully.\r
   EFI_INVALID_PARAMETER   A required parameter was NULL.\r
 \r
@@ -87,9 +74,9 @@ Arguments:
 \r
   FvHeader      Pointer to the FV buffer.\r
   FvLength      Length of the FV\r
-    \r
+\r
 Returns:\r
\r
+\r
   EFI_SUCCESS             Function Completed successfully.\r
   EFI_INVALID_PARAMETER   A required parameter was NULL.\r
   EFI_ABORTED             The library needs to be initialized.\r
@@ -110,6 +97,7 @@ Returns:
   }\r
 \r
   *FvHeader = mFvHeader;\r
+  *FvLength = mFvLength;\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -123,16 +111,16 @@ GetNextFile (
 Routine Description:\r
 \r
   This function returns the next file.  If the current file is NULL, it returns\r
-  the first file in the FV.  If the function returns EFI_SUCCESS and the file \r
+  the first file in the FV.  If the function returns EFI_SUCCESS and the file\r
   pointer is NULL, then there are no more files in the FV.\r
 \r
 Arguments:\r
 \r
   CurrentFile   Pointer to the current file, must be within the current FV.\r
   NextFile      Pointer to the next file in the FV.\r
-    \r
+\r
 Returns:\r
\r
+\r
   EFI_SUCCESS             Function completed successfully.\r
   EFI_INVALID_PARAMETER   A required parameter was NULL or is out of range.\r
   EFI_ABORTED             The library needs to be initialized.\r
@@ -180,7 +168,7 @@ Returns:
       //\r
       // Verify file is in this FV.\r
       //\r
-      if ((UINTN) CurrentFile + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength) {\r
+      if ((UINTN) CurrentFile + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength) {\r
         *NextFile = NULL;\r
         return EFI_SUCCESS;\r
       }\r
@@ -193,20 +181,20 @@ Returns:
   // Verify current file is in range\r
   //\r
   if (((UINTN) CurrentFile < (UINTN) mFvHeader + mFvHeader->HeaderLength) ||\r
-      ((UINTN) CurrentFile + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength)\r
+      ((UINTN) CurrentFile + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength)\r
      ) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   //\r
   // Get next file, compensate for 8 byte alignment if necessary.\r
   //\r
-  *NextFile = (EFI_FFS_FILE_HEADER *) (((UINTN) CurrentFile + GetLength (CurrentFile->Size) + 0x07) & (-1 << 3));\r
+  *NextFile = (EFI_FFS_FILE_HEADER *) ((((UINTN) CurrentFile - (UINTN) mFvHeader + GetFfsFileLength(CurrentFile) + 0x07) & (~(UINTN) 7)) + (UINT8 *) mFvHeader);\r
 \r
   //\r
   // Verify file is in this FV.\r
   //\r
-  if (((UINTN) *NextFile + sizeof (EFI_FFS_FILE_HEADER) >= (UINTN) mFvHeader + mFvLength) ||\r
-      ((UINTN) *NextFile + GetLength ((*NextFile)->Size) > (UINTN) mFvHeader + mFvLength)\r
+  if (((UINTN) *NextFile + GetFfsHeaderLength(*NextFile) >= (UINTN) mFvHeader + mFvLength) ||\r
+      ((UINTN) *NextFile + GetFfsFileLength (*NextFile) > (UINTN) mFvHeader + mFvLength)\r
      ) {\r
     *NextFile = NULL;\r
     return EFI_SUCCESS;\r
@@ -324,7 +312,7 @@ Routine Description:
 Arguments:\r
 \r
   FileType    Type of file to search for.\r
-  Instance    Instace of the file type to return.\r
+  Instance    Instance of the file type to return.\r
   File        Return pointer.  In the case of an error, contents are undefined.\r
 \r
 Returns:\r
@@ -433,7 +421,11 @@ Returns:
   EFI_FILE_SECTION_POINTER  InnerSection;\r
   EFI_STATUS                Status;\r
   UINTN                     SectionSize;\r
+  UINT16                    GuidSecAttr;\r
+  UINT16                    GuidDataOffset;\r
 \r
+  GuidSecAttr = 0;\r
+  GuidDataOffset = 0;\r
   CurrentSection = FirstSection;\r
 \r
   while ((UINTN) CurrentSection.CommonHeader < (UINTN) SearchEnd) {\r
@@ -451,14 +443,21 @@ Returns:
     // special processing, go ahead to search the requesting\r
     // section inside the GUID-defined section.\r
     //\r
+    if (CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED) {\r
+      if (GetLength(CurrentSection.CommonHeader->Size) == 0xffffff) {\r
+        GuidSecAttr = CurrentSection.GuidDefinedSection2->Attributes;\r
+        GuidDataOffset = CurrentSection.GuidDefinedSection2->DataOffset;\r
+      } else {\r
+        GuidSecAttr = CurrentSection.GuidDefinedSection->Attributes;\r
+        GuidDataOffset = CurrentSection.GuidDefinedSection->DataOffset;\r
+      }\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
+        !(GuidSecAttr & 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
+        ((UINTN) CurrentSection.CommonHeader + GuidDataOffset);\r
+      SectionSize = GetSectionFileLength(CurrentSection.CommonHeader);\r
       Status = SearchSectionByType (\r
                  InnerSection,\r
                  (UINT8 *) ((UINTN) CurrentSection.CommonHeader + SectionSize),\r
@@ -474,7 +473,7 @@ Returns:
     //\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
+    CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetSectionFileLength(CurrentSection.CommonHeader) + 0x03) & (~(UINTN) 3));\r
   }\r
 \r
   return EFI_NOT_FOUND;\r
@@ -491,7 +490,7 @@ GetSectionByType (
 \r
 Routine Description:\r
 \r
-  Find a section in a file by type and instance.  An instance of 1 is the first \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
   GUID-defined sections, if special processing is not needed, are handled in a\r
   depth-first manner.\r
@@ -500,7 +499,7 @@ Arguments:
 \r
   File        The file to search.\r
   SectionType Type of file to search for.\r
-  Instance    Instace of the section to return.\r
+  Instance    Instance of the section to return.\r
   Section     Return pointer.  In the case of an error, contents are undefined.\r
 \r
 Returns:\r
@@ -537,14 +536,14 @@ Returns:
   //\r
   // Get the first section\r
   //\r
-  CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + sizeof (EFI_FFS_FILE_HEADER));\r
-  \r
+  CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + GetFfsHeaderLength(File));\r
+\r
   //\r
   // Depth-first manner to find section file.\r
   //\r
   Status = SearchSectionByType (\r
              CurrentSection,\r
-             (UINT8 *) ((UINTN) File + GetLength (File->Size)),\r
+             (UINT8 *) ((UINTN) File + GetFfsFileLength (File)),\r
              SectionType,\r
              &SectionCount,\r
              Instance,\r
@@ -638,12 +637,14 @@ Returns:
 {\r
   BOOLEAN             ErasePolarity;\r
   EFI_STATUS          Status;\r
-  EFI_FFS_FILE_HEADER BlankHeader;\r
+  EFI_FFS_FILE_HEADER2 BlankHeader;\r
   UINT8               Checksum;\r
   UINT32              FileLength;\r
   UINT8               SavedChecksum;\r
   UINT8               SavedState;\r
   UINT8               FileGuidString[80];\r
+  UINT32              FfsHeaderSize;\r
+\r
   //\r
   // Verify library has been initialized.\r
   //\r
@@ -664,16 +665,18 @@ Returns:
   if (EFI_ERROR (Status)) {\r
     return EFI_ABORTED;\r
   }\r
+\r
+  FfsHeaderSize = GetFfsHeaderLength(FfsHeader);\r
   //\r
   // Check if we have free space\r
   //\r
   if (ErasePolarity) {\r
-    memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER));\r
+    memset (&BlankHeader, -1, FfsHeaderSize);\r
   } else {\r
-    memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER));\r
+    memset (&BlankHeader, 0, FfsHeaderSize);\r
   }\r
 \r
-  if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) {\r
+  if (memcmp (&BlankHeader, FfsHeader, FfsHeaderSize) == 0) {\r
     return EFI_NOT_FOUND;\r
   }\r
   //\r
@@ -688,7 +691,7 @@ Returns:
   FfsHeader->State = 0;\r
   SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File;\r
   FfsHeader->IntegrityCheck.Checksum.File = 0;\r
-  Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));\r
+  Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FfsHeaderSize);\r
   FfsHeader->State = SavedState;\r
   FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum;\r
   if (Checksum != 0) {\r
@@ -702,8 +705,8 @@ Returns:
     //\r
     // Verify file data checksum\r
     //\r
-    FileLength          = GetLength (FfsHeader->Size);\r
-    Checksum            = CalculateSum8 ((UINT8 *) (FfsHeader + 1), FileLength - sizeof (EFI_FFS_FILE_HEADER));\r
+    FileLength          = GetFfsFileLength (FfsHeader);\r
+    Checksum            = CalculateSum8 ((UINT8 *) ((UINT8 *)FfsHeader + FfsHeaderSize), FileLength - FfsHeaderSize);\r
     Checksum            = Checksum + FfsHeader->IntegrityCheck.Checksum.File;\r
     if (Checksum != 0) {\r
       Error (NULL, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString);\r
@@ -723,6 +726,80 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
+UINT32\r
+GetFfsHeaderLength(\r
+   IN EFI_FFS_FILE_HEADER *FfsHeader\r
+   )\r
+{\r
+  if (FfsHeader == NULL) {\r
+    return 0;\r
+  }\r
+  if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {\r
+    return sizeof(EFI_FFS_FILE_HEADER2);\r
+  }\r
+  return sizeof(EFI_FFS_FILE_HEADER);\r
+}\r
+\r
+UINT32\r
+GetSectionHeaderLength(\r
+   IN EFI_COMMON_SECTION_HEADER *SectionHeader\r
+   )\r
+{\r
+  if (SectionHeader == NULL) {\r
+    return 0;\r
+  }\r
+  if (GetLength(SectionHeader->Size) == 0xffffff) {\r
+    return sizeof(EFI_COMMON_SECTION_HEADER2);\r
+  }\r
+  return sizeof(EFI_COMMON_SECTION_HEADER);\r
+}\r
+\r
+UINT32\r
+GetFfsFileLength (\r
+  EFI_FFS_FILE_HEADER *FfsHeader\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Get FFS file length including FFS header.\r
+\r
+Arguments:\r
+\r
+  FfsHeader   Pointer to EFI_FFS_FILE_HEADER.\r
+\r
+Returns:\r
+\r
+  UINT32      Length of FFS file header.\r
+\r
+--*/\r
+{\r
+  if (FfsHeader == NULL) {\r
+    return 0;\r
+  }\r
+  if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {\r
+    return (UINT32) ((EFI_FFS_FILE_HEADER2 *)FfsHeader)->ExtendedSize;\r
+  } else {\r
+    return GetLength(FfsHeader->Size);\r
+  }\r
+}\r
+\r
+UINT32\r
+GetSectionFileLength (\r
+  EFI_COMMON_SECTION_HEADER *SectionHeader\r
+  )\r
+{\r
+  UINT32 Length;\r
+  if (SectionHeader == NULL) {\r
+    return 0;\r
+  }\r
+  Length = GetLength(SectionHeader->Size);\r
+  if (Length == 0xffffff) {\r
+    Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;\r
+  }\r
+  return Length;\r
+}\r
+\r
 UINT32\r
 GetLength (\r
   UINT8     *ThreeByteLength\r
@@ -775,7 +852,7 @@ Returns:
   EFI_SUCCESS              The function completed successfully.\r
   EFI_INVALID_PARAMETER    One of the input parameters was invalid.\r
   EFI_ABORTED              Operation aborted.\r
-  \r
+\r
 --*/\r
 {\r
   EFI_STATUS  Status;\r
@@ -822,7 +899,7 @@ Routine Description:
   It in no way validate the FFS file.\r
 \r
 Arguments:\r
-  \r
+\r
   ErasePolarity The erase polarity for the file state bits.\r
   FfsHeader     Pointer to a FFS file.\r
 \r