]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFfs/GenFfs.c
BaseTools/VolInfo: Update EFI FV FILETYPES for new MM types.
[mirror_edk2.git] / BaseTools / Source / C / GenFfs / GenFfs.c
index 433b608cb956d460f1c4115deb5641789b17c2c4..eb40c30ea7b523152d3e22c3cdf49f5de93b089c 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 This file contains functions required to generate a Firmware File System file.\r
 \r
-Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>\r
 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
@@ -12,6 +12,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 **/\r
 \r
+#ifndef __GNUC__\r
+#include <windows.h>\r
+#include <io.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#endif\r
+\r
 #include <stdio.h>\r
 #include <stdlib.h>\r
 #include <string.h>\r
@@ -24,6 +31,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "CommonLib.h"\r
 #include "ParseInf.h"\r
 #include "EfiUtilityMsgs.h"\r
+#include "FvLib.h"\r
+#include "PeCoffLib.h"\r
 \r
 #define UTILITY_NAME            "GenFfs"\r
 #define UTILITY_MAJOR_VERSION   0\r
@@ -43,19 +52,24 @@ STATIC CHAR8 *mFfsFileType[] = {
   "EFI_FV_FILETYPE_SMM",                  // 0x0A\r
   "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE",// 0x0B\r
   "EFI_FV_FILETYPE_COMBINED_SMM_DXE",     // 0x0C\r
-  "EFI_FV_FILETYPE_SMM_CORE"              // 0x0D\r
- };\r
+  "EFI_FV_FILETYPE_SMM_CORE",             // 0x0D\r
+  "EFI_FV_FILETYPE_MM_STANDALONE",        // 0x0E\r
+  "EFI_FV_FILETYPE_MM_CORE_STANDALONE"    // 0x0F\r
+};\r
 \r
 STATIC CHAR8 *mAlignName[] = {\r
   "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",\r
-  "1K", "2K", "4K", "8K", "16K", "32K", "64K"\r
+  "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K",\r
+  "512K", "1M", "2M", "4M", "8M", "16M"\r
  };\r
 \r
 STATIC CHAR8 *mFfsValidAlignName[] = {\r
-  "8", "16", "128", "512", "1K", "4K", "32K", "64K"\r
+  "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K","256K",\r
+  "512K", "1M", "2M", "4M", "8M", "16M"\r
  };\r
 \r
-STATIC UINT32 mFfsValidAlign[] = {0, 8, 16, 128, 512, 1024, 4096, 32768, 65536};\r
+STATIC UINT32 mFfsValidAlign[] = {0, 8, 16, 128, 512, 1024, 4096, 32768, 65536, 131072, 262144,\r
+                                  524288, 1048576, 2097152, 4194304, 8388608, 16777216};\r
 \r
 STATIC EFI_GUID mZeroGuid = {0};\r
 \r
@@ -114,7 +128,7 @@ Returns:
   //\r
   // Copyright declaration\r
   // \r
-  fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");\r
+  fprintf (stdout, "Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.\n\n");\r
 \r
   //\r
   // Details Option\r
@@ -130,6 +144,8 @@ Returns:
                         EFI_FV_FILETYPE_DRIVER, EFI_FV_FILETYPE_APPLICATION,\n\\r
                         EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,\n\\r
                         EFI_FV_FILETYPE_SMM, EFI_FV_FILETYPE_SMM_CORE,\n\\r
+                        EFI_FV_FILETYPE_MM_STANDALONE,\n\\r
+                        EFI_FV_FILETYPE_MM_CORE_STANDALONE,\n\\r
                         EFI_FV_FILETYPE_COMBINED_SMM_DXE, \n\\r
                         EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE.\n");\r
   fprintf (stdout, "  -g FileGuid, --fileguid FileGuid\n\\r
@@ -140,13 +156,16 @@ Returns:
   fprintf (stdout, "  -s, --checksum        Indicates to calculate file checksum.\n");\r
   fprintf (stdout, "  -a FileAlign, --align FileAlign\n\\r
                         FileAlign points to file alignment, which only support\n\\r
-                        the following align: 1,2,4,8,16,128,512,1K,4K,32K,64K\n");\r
+                        the following align: 1,2,4,8,16,128,512,1K,4K,32K,64K\n\\r
+                        128K,256K,512K,1M,2M,4M,8M,16M\n");\r
   fprintf (stdout, "  -i SectionFile, --sectionfile SectionFile\n\\r
                         Section file will be contained in this FFS file.\n");\r
   fprintf (stdout, "  -n SectionAlign, --sectionalign SectionAlign\n\\r
                         SectionAlign points to section alignment, which support\n\\r
-                        the alignment scope 1~64K. It is specified together\n\\r
-                        with sectionfile to point its alignment in FFS file.\n");\r
+                        the alignment scope 0~16M. If SectionAlign is specified\n\\r
+                        as 0, tool get alignment value from SectionFile. It is\n\\r
+                        specified together with sectionfile to point its\n\\r
+                        alignment in FFS file.\n");\r
   fprintf (stdout, "  -v, --verbose         Turn on verbose output with informational messages.\n");\r
   fprintf (stdout, "  -q, --quiet           Disable all messages except key message and fatal error\n");\r
   fprintf (stdout, "  -d, --debug level     Enable debug messages, at input debug level.\n");\r
@@ -164,7 +183,7 @@ StringtoAlignment (
 \r
 Routine Description:\r
 \r
-  Converts Align String to align value (1~64K). \r
+  Converts Align String to align value (1~16M).\r
 \r
 Arguments:\r
 \r
@@ -449,6 +468,103 @@ Returns:
   }\r
 }\r
 \r
+EFI_STATUS\r
+FfsRebaseImageRead (\r
+    IN      VOID    *FileHandle,\r
+    IN      UINTN   FileOffset,\r
+    IN OUT  UINT32  *ReadSize,\r
+    OUT     VOID    *Buffer\r
+    )\r
+  /*++\r
+\r
+    Routine Description:\r
+\r
+    Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
+\r
+    Arguments:\r
+\r
+   FileHandle - The handle to the PE/COFF file\r
+\r
+   FileOffset - The offset, in bytes, into the file to read\r
+\r
+   ReadSize   - The number of bytes to read from the file starting at FileOffset\r
+\r
+   Buffer     - A pointer to the buffer to read the data into.\r
+\r
+   Returns:\r
+\r
+   EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
+\r
+   --*/\r
+{\r
+  CHAR8   *Destination8;\r
+  CHAR8   *Source8;\r
+  UINT32  Length;\r
+\r
+  Destination8  = Buffer;\r
+  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
+  Length        = *ReadSize;\r
+  while (Length--) {\r
+    *(Destination8++) = *(Source8++);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+GetAlignmentFromFile(char *InFile, UINT32 *Alignment)\r
+  /*++\r
+    InFile is input file for getting alignment\r
+    return the alignment\r
+    --*/\r
+{\r
+  FILE                           *InFileHandle;\r
+  UINT8                          *PeFileBuffer;\r
+  UINTN                          PeFileSize;\r
+  UINT32                         CurSecHdrSize;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT   ImageContext;\r
+  EFI_COMMON_SECTION_HEADER      *CommonHeader;\r
+  EFI_STATUS                     Status;\r
+\r
+  InFileHandle        = NULL;\r
+  PeFileBuffer        = NULL;\r
+  *Alignment          = 0;\r
+\r
+  memset (&ImageContext, 0, sizeof (ImageContext));\r
+\r
+  InFileHandle = fopen(LongFilePath(InFile), "rb");\r
+  if (InFileHandle == NULL){\r
+    Error (NULL, 0, 0001, "Error opening file", InFile);\r
+    return EFI_ABORTED;\r
+  }\r
+  PeFileSize = _filelength (fileno(InFileHandle));\r
+  PeFileBuffer = (UINT8 *) malloc (PeFileSize);\r
+  if (PeFileBuffer == NULL) {\r
+    fclose (InFileHandle);\r
+    Error(NULL, 0, 4001, "Resource", "memory cannot be allocated  of %s", InFileHandle);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  fread (PeFileBuffer, sizeof (UINT8), PeFileSize, InFileHandle);\r
+  fclose (InFileHandle);\r
+  CommonHeader = (EFI_COMMON_SECTION_HEADER *) PeFileBuffer;\r
+  CurSecHdrSize = GetSectionHeaderLength(CommonHeader);\r
+  ImageContext.Handle = (VOID *) ((UINTN)PeFileBuffer + CurSecHdrSize);\r
+  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)FfsRebaseImageRead;\r
+  Status               = PeCoffLoaderGetImageInfo(&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and return status is %x", InFile, (int) Status);\r
+    return Status;\r
+   }\r
+  *Alignment = ImageContext.SectionAlignment;\r
+  // Free the allocated memory resource\r
+  if (PeFileBuffer != NULL) {\r
+    free (PeFileBuffer);\r
+    PeFileBuffer = NULL;\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 int\r
 main (\r
   int   argc,\r
@@ -489,6 +605,13 @@ Returns:
   UINT64                  LogLevel;\r
   UINT8                   PeSectionNum;\r
   UINT32                  HeaderSize;\r
+  UINT32                  Alignment;\r
+  //\r
+  // Workaround for static code checkers.\r
+  // Ensures the size of 'AlignmentBuffer' can hold all the digits of an\r
+  // unsigned 32-bit integer plus the size unit character.\r
+  //\r
+  CHAR8                   AlignmentBuffer[16];\r
   \r
   //\r
   // Init local variables\r
@@ -682,7 +805,27 @@ Returns:
       // Section File alignment requirement\r
       //\r
       if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--sectionalign") == 0)) {\r
-        Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileNum]));\r
+        if ((argv[1] != NULL) && (stricmp("0", argv[1]) == 0)) {\r
+          Status = GetAlignmentFromFile(InputFileName[InputFileNum], &Alignment);\r
+          if (EFI_ERROR(Status)) {\r
+            Error (NULL, 0, 1003, "Fail to get Alignment from %s", InputFileName[InputFileNum]);\r
+            goto Finish;\r
+          }\r
+          if (Alignment < 0x400){\r
+            sprintf (AlignmentBuffer, "%d", Alignment);\r
+          }\r
+          else if (Alignment >= 0x400) {\r
+            if (Alignment >= 0x100000) {\r
+              sprintf (AlignmentBuffer, "%dM", Alignment/0x100000);\r
+            } else {\r
+              sprintf (AlignmentBuffer, "%dK", Alignment/0x400);\r
+            }\r
+          }\r
+          Status = StringtoAlignment (AlignmentBuffer, &(InputFileAlign[InputFileNum]));\r
+        }\r
+        else {\r
+          Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileNum]));\r
+        }\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
           goto Finish;\r
@@ -732,14 +875,14 @@ Returns:
       continue;\r
     }\r
 \r
-    Error (NULL, 0, 1000, "Unknown option", argv[0]);\r
+    Error (NULL, 0, 1000, "Unknown option", "%s", argv[0]);\r
     goto Finish;\r
   }\r
 \r
   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
 \r
   //\r
-  // Check the complete input paramters.\r
+  // Check the complete input parameters.\r
   //\r
   if (FfsFiletype == EFI_FV_FILETYPE_ALL) {\r
     Error (NULL, 0, 1001, "Missing option", "filetype");\r
@@ -845,6 +988,11 @@ Returns:
   if (EFI_ERROR (Status)) {\r
     goto Finish;\r
   }\r
+\r
+  if (FileBuffer == NULL && FileSize != 0) {\r
+    Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+    goto Finish;\r
+  }\r
   \r
   //\r
   // Create Ffs file header.\r
@@ -884,7 +1032,12 @@ Returns:
   }\r
   VerboseMsg ("the size of the generated FFS file is %u bytes", (unsigned) FileSize);\r
 \r
-  FfsFileHeader.Attributes = (EFI_FFS_FILE_ATTRIBUTES) (FfsAttrib | (FfsAlign << 3));\r
+  //FfsAlign larger than 7, set FFS_ATTRIB_DATA_ALIGNMENT2\r
+  if (FfsAlign < 8) {\r
+    FfsFileHeader.Attributes = (EFI_FFS_FILE_ATTRIBUTES) (FfsAttrib | (FfsAlign << 3));\r
+  } else {\r
+    FfsFileHeader.Attributes = (EFI_FFS_FILE_ATTRIBUTES) (FfsAttrib | ((FfsAlign & 0x7) << 3) | FFS_ATTRIB_DATA_ALIGNMENT2);\r
+  }\r
 \r
   //\r
   // Fill in checksums and state, these must be zero for checksumming\r
@@ -915,22 +1068,26 @@ Returns:
   //\r
   // Open output file to write ffs data.\r
   //\r
-  remove(OutputFileName);\r
-  FfsFile = fopen (LongFilePath (OutputFileName), "wb");\r
-  if (FfsFile == NULL) {\r
-    Error (NULL, 0, 0001, "Error opening file", OutputFileName);\r
-    goto Finish;\r
-  }\r
-  //\r
-  // write header\r
-  //\r
-  fwrite (&FfsFileHeader, 1, HeaderSize, FfsFile);\r
-  //\r
-  // write data\r
-  //\r
-  fwrite (FileBuffer, 1, FileSize - HeaderSize, FfsFile);\r
+  if (OutputFileName != NULL) {\r
+    remove(OutputFileName);\r
+    FfsFile = fopen (LongFilePath (OutputFileName), "wb");\r
+    if (FfsFile == NULL) {\r
+      Error (NULL, 0, 0001, "Error opening file", OutputFileName);\r
+      goto Finish;\r
+    }\r
+    //\r
+    // write header\r
+    //\r
+    fwrite (&FfsFileHeader, 1, HeaderSize, FfsFile);\r
+    //\r
+    // write data\r
+    //\r
+    if (FileBuffer != NULL) {\r
+      fwrite (FileBuffer, 1, FileSize - HeaderSize, FfsFile);\r
+    }\r
 \r
-  fclose (FfsFile);\r
+    fclose (FfsFile);\r
+  }\r
 \r
 Finish:\r
   if (InputFileName != NULL) {\r