]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c
Add core FFS3 support, FwVolDxe and SectionExtraction.
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / FirmwareVolume / FwVolDxe / FwVolWrite.c
index 5c7e8abf75aa5c35aebdfd96cafe44c81452df06..7ca8f44b15f36b2bff62cf8719cfa7432bf1c880 100644 (file)
@@ -28,7 +28,6 @@ SetHeaderChecksum (
   )\r
 {\r
   EFI_FFS_FILE_STATE  State;\r
-  UINT8               HeaderChecksum;\r
   UINT8               FileChecksum;\r
 \r
   //\r
@@ -42,12 +41,17 @@ SetHeaderChecksum (
 \r
   FfsHeader->IntegrityCheck.Checksum.Header = 0;\r
 \r
-  HeaderChecksum = CalculateSum8 (\r
-    (UINT8 *)FfsHeader,\r
-    sizeof (EFI_FFS_FILE_HEADER)\r
-    );\r
-\r
-  FfsHeader->IntegrityCheck.Checksum.Header = (UINT8) (~HeaderChecksum + 1);\r
+  if (IS_FFS_FILE2 (FfsHeader)) {\r
+    FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 (\r
+      (UINT8 *) FfsHeader,\r
+      sizeof (EFI_FFS_FILE_HEADER2)\r
+      );\r
+  } else {\r
+    FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 (\r
+      (UINT8 *) FfsHeader,\r
+      sizeof (EFI_FFS_FILE_HEADER)\r
+      );\r
+  }\r
 \r
   FfsHeader->State                          = State;\r
   FfsHeader->IntegrityCheck.Checksum.File   = FileChecksum;\r
@@ -68,29 +72,21 @@ SetFileChecksum (
   IN UINTN               ActualFileSize\r
   )\r
 {\r
-  EFI_FFS_FILE_STATE  State;\r
-  UINT8               FileChecksum;\r
-\r
   if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) {\r
-    //\r
-    // The file state is not included\r
-    //\r
-    State = FfsHeader->State;\r
-    FfsHeader->State = 0;\r
 \r
     FfsHeader->IntegrityCheck.Checksum.File = 0;\r
 \r
-    //\r
-    // File checksum \r
-    //\r
-    FileChecksum = CalculateSum8 (\r
-      (UINT8 *)(FfsHeader + 1),\r
-               ActualFileSize - sizeof (EFI_FFS_FILE_HEADER)\r
-      );\r
-\r
-    FfsHeader->IntegrityCheck.Checksum.File = (UINT8) (~FileChecksum + 1);\r
-\r
-    FfsHeader->State                        = State;\r
+    if (IS_FFS_FILE2 (FfsHeader)) {\r
+      FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 (\r
+        (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2),\r
+        ActualFileSize - sizeof (EFI_FFS_FILE_HEADER2)\r
+        );\r
+    } else {\r
+      FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 (\r
+        (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER),\r
+        ActualFileSize - sizeof (EFI_FFS_FILE_HEADER)\r
+        );\r
+    }\r
 \r
   } else {\r
 \r
@@ -138,6 +134,7 @@ GetRequiredAlignment (
 \r
   @param FvDevice          Cached Firmware Volume.\r
   @param StartAddress      The starting address to write the FFS File.\r
+  @param BufferSize        The FFS File Buffer Size.\r
   @param RequiredAlignment FFS File Data alignment requirement.\r
 \r
   @return The required Pad File Size.\r
@@ -147,6 +144,7 @@ UINTN
 CaculatePadFileSize (\r
   IN FV_DEVICE            *FvDevice,\r
   IN EFI_PHYSICAL_ADDRESS StartAddress,\r
+  IN UINTN                BufferSize,\r
   IN UINTN                RequiredAlignment\r
   )\r
 {\r
@@ -154,7 +152,11 @@ CaculatePadFileSize (
   UINTN RelativePos;\r
   UINTN PadSize;\r
 \r
-  DataStartPos  = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER);\r
+  if (BufferSize > 0x00FFFFFF) {\r
+    DataStartPos  = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER2);\r
+  } else {\r
+    DataStartPos  = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER);\r
+  }\r
   RelativePos   = DataStartPos - (UINTN) FvDevice->CachedFv;\r
 \r
   PadSize       = 0;\r
@@ -331,6 +333,7 @@ FvLocateFreeSpaceEntry (
     PadFileSize = CaculatePadFileSize (\r
                     FvDevice,\r
                     (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceListEntry->StartingAddress,\r
+                    Size,\r
                     RequiredAlignment\r
                     );\r
     if (FreeSpaceListEntry->Length >= Size + PadFileSize) {\r
@@ -346,54 +349,6 @@ FvLocateFreeSpaceEntry (
 \r
 }\r
 \r
-/**\r
-  Locate a free space that can hold this file.\r
-\r
-  @param FvDevice           Cached Firmware Volume.\r
-  @param Size               On input, it is the required size.\r
-                            On output, it is the actual size of free space.\r
-  @param RequiredAlignment  FFS File Data alignment requirement.\r
-  @param PadSize            Pointer to the size of leading Pad File.\r
-  @param StartingAddress    The starting address of the Free Space Entry\r
-                            that meets the requirement.\r
-\r
-  @retval EFI_SUCCESS     The free space is found.\r
-  @retval EFI_NOT_FOUND   The free space can't be found.\r
-\r
-**/\r
-EFI_STATUS\r
-FvLocateFreeSpace (\r
-  IN  FV_DEVICE             *FvDevice,\r
-  IN  OUT UINTN             *Size,\r
-  IN  UINTN                 RequiredAlignment,\r
-  OUT UINTN                 *PadSize,\r
-  OUT EFI_PHYSICAL_ADDRESS  *StartingAddress\r
-  )\r
-{\r
-  EFI_STATUS        Status;\r
-  FREE_SPACE_ENTRY  *FreeSpaceEntry;\r
-\r
-  //\r
-  // First find the free space entry\r
-  //\r
-  Status = FvLocateFreeSpaceEntry (\r
-            FvDevice,\r
-            *Size,\r
-            RequiredAlignment,\r
-            PadSize,\r
-            &FreeSpaceEntry\r
-            );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  *Size             = FreeSpaceEntry->Length;\r
-  *StartingAddress  = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
 /**\r
   Locate Pad File for writing, this is got from FV Cache.\r
 \r
@@ -419,9 +374,9 @@ FvLocatePadFile (
   FFS_FILE_LIST_ENTRY *FileEntry;\r
   EFI_FFS_FILE_STATE  FileState;\r
   EFI_FFS_FILE_HEADER *FileHeader;\r
-  UINTN               FileLength;\r
   UINTN               PadAreaLength;\r
   UINTN               PadFileSize;\r
+  UINTN               HeaderSize;\r
 \r
   FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;\r
 \r
@@ -437,12 +392,18 @@ FvLocatePadFile (
       //\r
       // we find one valid pad file, check its free area length\r
       //\r
-      FileLength    = *(UINT32 *) FileHeader->Size & 0x00FFFFFF;\r
-      PadAreaLength = FileLength - sizeof (EFI_FFS_FILE_HEADER);\r
+      if (IS_FFS_FILE2 (FileHeader)) {\r
+        HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+        PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize;\r
+      } else {\r
+        HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
+        PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize;\r
+      }\r
 \r
       PadFileSize = CaculatePadFileSize (\r
                       FvDevice,\r
-                      (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + sizeof (EFI_FFS_FILE_HEADER),\r
+                      (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize,\r
+                      Size,\r
                       RequiredAlignment\r
                       );\r
       if (PadAreaLength >= (Size + PadFileSize)) {\r
@@ -487,10 +448,10 @@ FvSearchSuitablePadFile (
   FFS_FILE_LIST_ENTRY *FileEntry;\r
   EFI_FFS_FILE_STATE  FileState;\r
   EFI_FFS_FILE_HEADER *FileHeader;\r
-  UINTN               FileLength;\r
   UINTN               PadAreaLength;\r
   UINTN               TotalSize;\r
   UINTN               Index;\r
+  UINTN               HeaderSize;\r
 \r
   FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;\r
 \r
@@ -506,14 +467,20 @@ FvSearchSuitablePadFile (
       //\r
       // we find one valid pad file, check its length\r
       //\r
-      FileLength    = *(UINT32 *) FileHeader->Size & 0x00FFFFFF;\r
-      PadAreaLength = FileLength - sizeof (EFI_FFS_FILE_HEADER);\r
+      if (IS_FFS_FILE2 (FileHeader)) {\r
+        HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+        PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize;\r
+      } else {\r
+        HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
+        PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize;\r
+      }\r
       TotalSize     = 0;\r
 \r
       for (Index = 0; Index < NumOfFiles; Index++) {\r
         PadSize[Index] = CaculatePadFileSize (\r
                       FvDevice,\r
-                      (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + sizeof (EFI_FFS_FILE_HEADER) + TotalSize,\r
+                      (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize + TotalSize,\r
+                      BufferSize[Index],\r
                       RequiredAlignment[Index]\r
                       );\r
         TotalSize += PadSize[Index];\r
@@ -589,6 +556,7 @@ FvSearchSuitableFreeSpace (
       PadSize[Index] = CaculatePadFileSize (\r
                     FvDevice,\r
                     (EFI_PHYSICAL_ADDRESS) (UINTN) StartAddr + TotalSize,\r
+                    BufferSize[Index],\r
                     RequiredAlignment[Index]\r
                     );\r
 \r
@@ -803,6 +771,7 @@ FvCreateNewFile (
   FFS_FILE_LIST_ENTRY                 *PadFileEntry;\r
   EFI_FFS_FILE_ATTRIBUTES             TmpFileAttribute;\r
   FFS_FILE_LIST_ENTRY                 *FfsFileEntry;\r
+  UINTN                               HeaderSize;\r
 \r
   //\r
   // File Type: 0x0E~0xE0 are reserved\r
@@ -869,6 +838,11 @@ FvCreateNewFile (
   // Write Name, IntegrityCheck.Header, Type, Attributes, and Size\r
   //\r
   FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer;\r
+  if (ActualFileSize > 0x00FFFFFF) {\r
+    HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+  } else {\r
+    HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
+  }\r
   SetFileState (EFI_FILE_HEADER_CONSTRUCTION, FileHeader);\r
 \r
   Offset          = (UINTN) (BufferPtr - FvDevice->CachedFv);\r
@@ -890,14 +864,14 @@ FvCreateNewFile (
   CopyMem (\r
     (UINT8 *) (UINTN) BufferPtr,\r
     FileHeader,\r
-    sizeof (EFI_FFS_FILE_HEADER)\r
+    HeaderSize\r
     );\r
 \r
   //\r
-  // update Free Space Entry, now need to substract the EFI_FFS_FILE_HEADER\r
+  // update Free Space Entry, now need to substract the file header length\r
   //\r
-  FreeSpaceEntry->StartingAddress += sizeof (EFI_FFS_FILE_HEADER);\r
-  FreeSpaceEntry->Length -= sizeof (EFI_FFS_FILE_HEADER);\r
+  FreeSpaceEntry->StartingAddress += HeaderSize;\r
+  FreeSpaceEntry->Length -= HeaderSize;\r
 \r
   CopyGuid (&FileHeader->Name, FileName);\r
   FileHeader->Type = FileType;\r
@@ -912,14 +886,20 @@ FvCreateNewFile (
   //\r
   // File size is including the FFS File Header.\r
   //\r
-  *(UINT32 *) FileHeader->Size &= 0xFF000000;\r
-  *(UINT32 *) FileHeader->Size |= ActualFileSize;\r
+  if (ActualFileSize > 0x00FFFFFF) {\r
+    ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize;\r
+    *(UINT32 *) FileHeader->Size &= 0xFF000000;\r
+    FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;\r
+  } else {\r
+    *(UINT32 *) FileHeader->Size &= 0xFF000000;\r
+    *(UINT32 *) FileHeader->Size |= ActualFileSize;\r
+  }\r
 \r
   SetHeaderChecksum (FileHeader);\r
 \r
   Offset          = (UINTN) (BufferPtr - FvDevice->CachedFv);\r
 \r
-  NumBytesWritten = sizeof (EFI_FFS_FILE_HEADER);\r
+  NumBytesWritten = HeaderSize;\r
   Status = FvcWrite (\r
             FvDevice,\r
             Offset,\r
@@ -935,7 +915,7 @@ FvCreateNewFile (
   CopyMem (\r
     (UINT8 *) (UINTN) BufferPtr,\r
     FileHeader,\r
-    sizeof (EFI_FFS_FILE_HEADER)\r
+    HeaderSize\r
     );\r
 \r
   //\r
@@ -966,14 +946,14 @@ FvCreateNewFile (
   CopyMem (\r
     (UINT8 *) (UINTN) BufferPtr,\r
     FileHeader,\r
-    sizeof (EFI_FFS_FILE_HEADER)\r
+    HeaderSize\r
     );\r
 \r
   //\r
   // update Free Space Entry, now need to substract the file data length\r
   //\r
-  FreeSpaceEntry->StartingAddress += (BufferSize - sizeof (EFI_FFS_FILE_HEADER));\r
-  FreeSpaceEntry->Length -= (BufferSize - sizeof (EFI_FFS_FILE_HEADER));\r
+  FreeSpaceEntry->StartingAddress += (BufferSize - HeaderSize);\r
+  FreeSpaceEntry->Length -= (BufferSize - HeaderSize);\r
 \r
   //\r
   // Caculate File Checksum\r
@@ -1025,7 +1005,7 @@ FvCreateNewFile (
   CopyMem (\r
     (UINT8 *) (UINTN) BufferPtr,\r
     FileHeader,\r
-    sizeof (EFI_FFS_FILE_HEADER)\r
+    HeaderSize\r
     );\r
 \r
   //\r
@@ -1381,6 +1361,7 @@ FvWriteFile (
   UINTN                               NumDelete;\r
   EFI_FV_ATTRIBUTES                   FvAttributes;\r
   UINT32                              AuthenticationStatus;\r
+  UINTN                               HeaderSize;\r
 \r
   if (NumberOfFiles > MAX_FILES) {\r
     return EFI_UNSUPPORTED;\r
@@ -1416,6 +1397,15 @@ FvWriteFile (
   //\r
   NumDelete = 0;\r
   for (Index1 = 0; Index1 < NumberOfFiles; Index1++) {\r
+\r
+    if ((FileData[Index1].BufferSize + sizeof (EFI_FFS_FILE_HEADER) > 0x00FFFFFF) && !FvDevice->IsFfs3Fv) {\r
+      //\r
+      // Found a file needs a FFS3 formatted file to store it, but it is in a non-FFS3 formatted FV.\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "FFS3 formatted file can't be written in a non-FFS3 formatted FV.\n"));\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
     if (FileData[Index1].BufferSize == 0) {\r
       //\r
       // Here we will delete this file\r
@@ -1525,7 +1515,12 @@ FvWriteFile (
     //\r
     // Making Buffersize QWORD boundry, and add file tail.\r
     //\r
-    ActualSize  = FileData[Index1].BufferSize + sizeof (EFI_FFS_FILE_HEADER);\r
+    HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
+    ActualSize = FileData[Index1].BufferSize + HeaderSize;\r
+    if (ActualSize > 0x00FFFFFF) {\r
+      HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+      ActualSize = FileData[Index1].BufferSize + HeaderSize;\r
+    }\r
     BufferSize  = ActualSize;\r
 \r
     while ((BufferSize & 0x07) != 0) {\r
@@ -1540,7 +1535,7 @@ FvWriteFile (
     // Copy File Data into FileBuffer\r
     //\r
     CopyMem (\r
-      FileBuffer + sizeof (EFI_FFS_FILE_HEADER),\r
+      FileBuffer + HeaderSize,\r
       FileData[Index1].Buffer,\r
       FileData[Index1].BufferSize\r
       );\r
@@ -1549,7 +1544,7 @@ FvWriteFile (
       //\r
       // Fill the file header and padding byte with Erase Byte\r
       //\r
-      for (Index2 = 0; Index2 < sizeof (EFI_FFS_FILE_HEADER); Index2++) {\r
+      for (Index2 = 0; Index2 < HeaderSize; Index2++) {\r
         FileBuffer[Index2] = (UINT8)~FileBuffer[Index2];\r
       }\r
 \r