]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenSec/GenSec.c
BaseTools: argument genfds-multi-thread create GenSec command issue
[mirror_edk2.git] / BaseTools / Source / C / GenSec / GenSec.c
index f9370d35645f6019f6c5116e9d7b27c8fb3d8a64..46149762586ef0d7b849b3fa7333f462d5d40a3f 100644 (file)
@@ -1,6 +1,7 @@
 /** @file\r
+Creates output file that is a properly formed section per the PI spec.\r
 \r
-Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2018, 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
@@ -9,15 +10,13 @@ http://opensource.org/licenses/bsd-license.php
 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
-  GenSection.c\r
-\r
-Abstract:\r
-\r
-  Creates output file that is a properly formed section per the PI spec.\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
@@ -34,6 +33,8 @@ Abstract:
 #include "Crc32.h"\r
 #include "EfiUtilityMsgs.h"\r
 #include "ParseInf.h"\r
+#include "FvLib.h"\r
+#include "PeCoffLib.h"\r
 \r
 //\r
 // GenSec Tool Information\r
@@ -81,7 +82,8 @@ STATIC CHAR8      *mGUIDedSectionAttribue[]  = { "NONE", "PROCESSING_REQUIRED",
 \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
 //\r
@@ -153,7 +155,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
@@ -191,8 +193,12 @@ Returns:
                         used in Ver section.\n");\r
   fprintf (stdout, "  --sectionalign SectionAlign\n\\r
                         SectionAlign points to section alignment, which support\n\\r
-                        the alignment scope 1~64K. It is specified in same\n\\r
-                        order that the section file is input.\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 in same order that the section file is input.\n");\r
+  fprintf (stdout, "  --dummy dummyfile\n\\r
+                        compare dummpyfile with input_file to decide whether\n\\r
+                        need to set PROCESSING_REQUIRED attribute.\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
@@ -274,10 +280,10 @@ Returns:
   STATUS                    Status;\r
 \r
   if (InputFileNum > 1) {\r
-    Error (NULL, 0, 2000, "Invalid paramter", "more than one input file specified");\r
+    Error (NULL, 0, 2000, "Invalid parameter", "more than one input file specified");\r
     return STATUS_ERROR;\r
   } else if (InputFileNum < 1) {\r
-    Error (NULL, 0, 2000, "Invalid paramter", "no input file specified");\r
+    Error (NULL, 0, 2000, "Invalid parameter", "no input file specified");\r
     return STATUS_ERROR;\r
   }\r
   //\r
@@ -303,7 +309,7 @@ Returns:
   // Size must fit in 3 bytes\r
   //\r
   //if (TotalLength >= MAX_SECTION_SIZE) {\r
-  //  Error (NULL, 0, 2000, "Invalid paramter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20);\r
+  //  Error (NULL, 0, 2000, "Invalid parameter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20);\r
   //  goto Done;\r
   //}\r
   HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER);\r
@@ -363,7 +369,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
@@ -443,12 +449,12 @@ Returns:
   UINT32                     HeaderSize;\r
 \r
   if (InputFileNum < 1) {\r
-    Error (NULL, 0, 2000, "Invalid paramter", "must specify at least one input file");\r
+    Error (NULL, 0, 2000, "Invalid parameter", "must specify at least one input file");\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   if (BufferLength == NULL) {\r
-    Error (NULL, 0, 2000, "Invalid paramter", "BufferLength can't be NULL");\r
+    Error (NULL, 0, 2000, "Invalid parameter", "BufferLength can't be NULL");\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -674,6 +680,10 @@ Returns:
     return Status;\r
   }\r
 \r
+  if (FileBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
   CompressFunction = NULL;\r
 \r
   //\r
@@ -705,7 +715,7 @@ Returns:
     break;\r
 \r
   default:\r
-    Error (NULL, 0, 2000, "Invalid paramter", "unknown compression type");\r
+    Error (NULL, 0, 2000, "Invalid parameter", "unknown compression type");\r
     free (FileBuffer);\r
     return EFI_ABORTED;\r
   }\r
@@ -738,13 +748,17 @@ Returns:
 \r
       return Status;\r
     }\r
+\r
+    if (FileBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
   }\r
 \r
   DebugMsg (NULL, 0, 9, "comprss file size", \r
             "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);\r
 \r
   //if (TotalLength >= MAX_SECTION_SIZE) {\r
-  //  Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);\r
+  //  Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);\r
   //  if (FileBuffer != NULL) {\r
   //    free (FileBuffer);\r
   //  }\r
@@ -897,10 +911,21 @@ Returns:
   }\r
 \r
   if (InputLength == 0) {\r
+    if (FileBuffer != NULL) {\r
+      free (FileBuffer);\r
+    }\r
     Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
+  //\r
+  // InputLength != 0, but FileBuffer == NULL means out of resources.\r
+  //\r
+  if (FileBuffer == NULL) {\r
+    Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
   //\r
   // Now data is in FileBuffer + Offset\r
   //\r
@@ -969,6 +994,103 @@ Returns:
   return EFI_SUCCESS;\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
@@ -1015,6 +1137,13 @@ Returns:
   UINT32                    *InputFileAlign;\r
   UINT32                    InputFileAlignNum;\r
   EFI_COMMON_SECTION_HEADER *SectionHeader;\r
+  CHAR8                     *DummyFileName;\r
+  FILE                      *DummyFile;\r
+  UINTN                     DummyFileSize;\r
+  UINT8                     *DummyFileBuffer;\r
+  FILE                      *InFile;\r
+  UINT8                     *InFileBuffer;\r
+  UINTN                     InFileSize;\r
 \r
   InputFileAlign        = NULL;\r
   InputFileAlignNum     = 0;\r
@@ -1036,6 +1165,13 @@ Returns:
   SectGuidHeaderLength  = 0;\r
   VersionSect           = NULL;\r
   UiSect                = NULL;\r
+  DummyFileSize         = 0;\r
+  DummyFileName         = NULL;\r
+  DummyFile             = NULL;\r
+  DummyFileBuffer       = NULL;\r
+  InFile                = NULL;\r
+  InFileSize            = 0;\r
+  InFileBuffer          = NULL;\r
   \r
   SetUtilityName (UTILITY_NAME);\r
   \r
@@ -1106,8 +1242,22 @@ Returns:
       argv += 2;\r
       continue;\r
     }\r
+    if (stricmp (argv[0], "--dummy") == 0) {\r
+      DummyFileName = argv[1];\r
+      if (DummyFileName == NULL) {\r
+        Error (NULL, 0, 1003, "Invalid option value", "Dummy file can't be NULL");\r
+        goto Finish;\r
+      }\r
+      argc -= 2;\r
+      argv += 2;\r
+      continue;\r
+    }\r
 \r
     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {\r
+      if (argv[1] == NULL) {\r
+        Error (NULL, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL");\r
+        goto Finish;\r
+      }\r
       if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {\r
         SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
       } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {\r
@@ -1210,7 +1360,7 @@ Returns:
         InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
         if (InputFileAlign == NULL) {\r
           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
-          return 1;\r
+          goto Finish;\r
         }\r
         memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
       } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
@@ -1221,15 +1371,18 @@ Returns:
 \r
         if (InputFileAlign == NULL) {\r
           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
-          return 1;\r
+          goto Finish;\r
         }\r
         memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));\r
       }\r
-      \r
-      Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));\r
-      if (EFI_ERROR (Status)) {\r
-        Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
-        goto Finish;\r
+      if (stricmp(argv[1], "0") == 0) {\r
+        InputFileAlign[InputFileAlignNum] = 0;\r
+      } else {\r
+        Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));\r
+        if (EFI_ERROR (Status)) {\r
+          Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
+          goto Finish;\r
+        }\r
       }\r
       argc -= 2;\r
       argv += 2;\r
@@ -1244,7 +1397,7 @@ Returns:
       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
       if (InputFileName == NULL) {\r
         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
-        return 1;\r
+        goto Finish;\r
       }\r
       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
@@ -1258,7 +1411,7 @@ Returns:
 \r
       if (InputFileName == NULL) {\r
         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
-        return 1;\r
+        goto Finish;\r
       }\r
       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
     }\r
@@ -1272,9 +1425,83 @@ Returns:
     Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");\r
     goto Finish;\r
   }\r
+  for (Index = 0; Index < InputFileAlignNum; Index++)\r
+  {\r
+    if (InputFileAlign[Index] == 0) {\r
+      Status = GetAlignmentFromFile(InputFileName[Index], &(InputFileAlign[Index]));\r
+      if (EFI_ERROR(Status)) {\r
+        Error (NULL, 0, 1003, "Fail to get Alignment from %s", InputFileName[InputFileNum]);\r
+        goto Finish;\r
+      }\r
+    }\r
+  }\r
 \r
   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
 \r
+  if (DummyFileName != NULL) {\r
+      //\r
+      // Open file and read contents\r
+      //\r
+      DummyFile = fopen (LongFilePath (DummyFileName), "rb");\r
+      if (DummyFile == NULL) {\r
+        Error (NULL, 0, 0001, "Error opening file", DummyFileName);\r
+        goto Finish;\r
+      }\r
+\r
+      fseek (DummyFile, 0, SEEK_END);\r
+      DummyFileSize = ftell (DummyFile);\r
+      fseek (DummyFile, 0, SEEK_SET);\r
+      DummyFileBuffer = (UINT8 *) malloc (DummyFileSize);\r
+      if (DummyFileBuffer == NULL) {\r
+        fclose(DummyFile);\r
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
+        goto Finish;\r
+      }\r
+\r
+      fread(DummyFileBuffer, 1, DummyFileSize, DummyFile);\r
+      fclose(DummyFile);\r
+      DebugMsg (NULL, 0, 9, "Dummy files", "the dummy file name is %s and the size is %u bytes", DummyFileName, (unsigned) DummyFileSize);\r
+\r
+      if (InputFileName == NULL) {\r
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
+        goto Finish;\r
+      }\r
+      InFile = fopen(LongFilePath(InputFileName[0]), "rb");\r
+      if (InFile == NULL) {\r
+        Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);\r
+        goto Finish;\r
+      }\r
+\r
+      fseek (InFile, 0, SEEK_END);\r
+      InFileSize = ftell (InFile);\r
+      fseek (InFile, 0, SEEK_SET);\r
+      InFileBuffer = (UINT8 *) malloc (InFileSize);\r
+      if (InFileBuffer == NULL) {\r
+        fclose(InFile);\r
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
+        goto Finish;\r
+      }\r
+\r
+      fread(InFileBuffer, 1, InFileSize, InFile);\r
+      fclose(InFile);\r
+      DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[0], (unsigned) InFileSize);\r
+      if (InFileSize > DummyFileSize){\r
+        if (stricmp((CHAR8 *)DummyFileBuffer, (CHAR8 *)(InFileBuffer + (InFileSize - DummyFileSize))) == 0){\r
+          SectGuidHeaderLength = InFileSize - DummyFileSize;\r
+        }\r
+      }\r
+      if (SectGuidHeaderLength == 0) {\r
+        SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
+      }\r
+      if (DummyFileBuffer != NULL) {\r
+        free (DummyFileBuffer);\r
+        DummyFileBuffer = NULL;\r
+      }\r
+      if (InFileBuffer != NULL) {\r
+        free (InFileBuffer);\r
+      }\r
+    }\r
+\r
   //\r
   // Parse all command line parameters to get the corresponding section type.\r
   //\r
@@ -1372,7 +1599,9 @@ Returns:
   //\r
   // GuidValue is only required by Guided section.\r
   //\r
-  if ((SectType != EFI_SECTION_GUID_DEFINED) && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
+  if ((SectType != EFI_SECTION_GUID_DEFINED) &&\r
+    (SectionName != NULL) &&\r
+    (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
     fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);\r
   }\r
   \r
@@ -1577,7 +1806,11 @@ Finish:
   if (OutFile != NULL) {\r
     fclose (OutFile);\r
   }\r
-  \r
+\r
+  if (DummyFileBuffer != NULL) {\r
+    free (DummyFileBuffer);\r
+  }\r
+\r
   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
 \r
   return GetUtilityStatus ();\r