]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenSec/GenSec.c
There is a limitation on WINDOWS OS for the length of entire file path can’t be large...
[mirror_edk2.git] / BaseTools / Source / C / GenSec / GenSec.c
index 32b8cfd5a0c5ad40cba785abf648a8828180025b..f9370d35645f6019f6c5116e9d7b27c8fb3d8a64 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 \r
-Copyright (c) 2004 - 2008, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
+Copyright (c) 2004 - 2014, 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
 http://opensource.org/licenses/bsd-license.php                                            \r
@@ -27,6 +27,7 @@ Abstract:
 #include <Common/UefiBaseTypes.h>\r
 #include <Common/PiFirmwareFile.h>\r
 #include <Protocol/GuidedSectionExtraction.h>\r
+#include <IndustryStandard/PeImage.h>\r
 \r
 #include "CommonLib.h"\r
 #include "Compress.h"\r
@@ -41,8 +42,6 @@ Abstract:
 #define UTILITY_MAJOR_VERSION   0\r
 #define UTILITY_MINOR_VERSION   1\r
 \r
-#define MAX_SECTION_SIZE        0x1000000\r
-\r
 STATIC CHAR8      *mSectionTypeName[] = {\r
   NULL,                                 // 0x00 - reserved\r
   "EFI_SECTION_COMPRESSION",            // 0x01\r
@@ -80,6 +79,11 @@ STATIC CHAR8      *mCompressionTypeName[]    = { "PI_NONE", "PI_STD" };
 #define EFI_GUIDED_SECTION_NONE 0x80\r
 STATIC CHAR8      *mGUIDedSectionAttribue[]  = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};\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
+};\r
+\r
 //\r
 // Crc32 GUID section related definitions.\r
 //\r
@@ -88,6 +92,11 @@ typedef struct {
   UINT32                    CRC32Checksum;\r
 } CRC32_SECTION_HEADER;\r
 \r
+typedef struct {\r
+  EFI_GUID_DEFINED_SECTION2 GuidSectionHeader;\r
+  UINT32                    CRC32Checksum;\r
+} CRC32_SECTION_HEADER2;\r
+\r
 STATIC EFI_GUID  mZeroGuid                 = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
 STATIC EFI_GUID  mEfiCrc32SectionGuid      = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;\r
 \r
@@ -112,7 +121,7 @@ Returns:
   \r
 --*/ \r
 {\r
-  fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
+  fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
 }\r
 \r
 STATIC\r
@@ -144,7 +153,7 @@ Returns:
   //\r
   // Copyright declaration\r
   // \r
-  fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");\r
+  fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");\r
 \r
   //\r
   // Details Option\r
@@ -178,8 +187,12 @@ Returns:
   fprintf (stdout, "  -n String, --name String\n\\r
                         String is a NULL terminated string used in Ui section.\n");\r
   fprintf (stdout, "  -j Number, --buildnumber Number\n\\r
-                        Number is an integer value between 0000 and 9999\n\\r
+                        Number is an integer value between 0 and 65535\n\\r
                         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
   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
@@ -256,6 +269,7 @@ Returns:
   FILE                      *InFile;\r
   UINT8                     *Buffer;\r
   UINT32                    TotalLength;\r
+  UINT32                    HeaderLength;\r
   EFI_COMMON_SECTION_HEADER *CommonSect;\r
   STATUS                    Status;\r
 \r
@@ -269,7 +283,7 @@ Returns:
   //\r
   // Open the input file\r
   //\r
-  InFile = fopen (InputFileName[0], "rb");\r
+  InFile = fopen (LongFilePath (InputFileName[0]), "rb");\r
   if (InFile == NULL) {\r
     Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);\r
     return STATUS_ERROR;\r
@@ -288,9 +302,14 @@ Returns:
   //\r
   // 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
+  //  goto Done;\r
+  //}\r
+  HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER);\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
-    goto Done;\r
+    TotalLength = sizeof (EFI_COMMON_SECTION_HEADER2) + InputFileLength;\r
+    HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER2);\r
   }\r
   VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
   //\r
@@ -303,15 +322,20 @@ Returns:
   }\r
   CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer;\r
   CommonSect->Type     = SectionType;\r
-  CommonSect->Size[0]  = (UINT8) (TotalLength & 0xff);\r
-  CommonSect->Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
-  CommonSect->Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
+  if (TotalLength < MAX_SECTION_SIZE) {\r
+    CommonSect->Size[0]  = (UINT8) (TotalLength & 0xff);\r
+    CommonSect->Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
+    CommonSect->Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
+  } else {\r
+    memset(CommonSect->Size, 0xff, sizeof(UINT8) * 3);\r
+    ((EFI_COMMON_SECTION_HEADER2 *)CommonSect)->ExtendedSize = TotalLength;\r
+  }\r
   \r
   //\r
   // read data from the input file.\r
   //\r
   if (InputFileLength != 0) {\r
-    if (fread (Buffer + sizeof (EFI_COMMON_SECTION_HEADER), (size_t) InputFileLength, 1, InFile) != 1) {\r
+    if (fread (Buffer + HeaderLength, (size_t) InputFileLength, 1, InFile) != 1) {\r
       Error (NULL, 0, 0004, "Error reading file", InputFileName[0]);\r
       goto Done;\r
     }\r
@@ -329,9 +353,50 @@ Done:
   return Status;\r
 }\r
 \r
+STATIC\r
+EFI_STATUS\r
+StringtoAlignment (\r
+  IN  CHAR8  *AlignBuffer,\r
+  OUT UINT32 *AlignNumber\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Converts Align String to align value (1~64K). \r
+\r
+Arguments:\r
+\r
+  AlignBuffer    - Pointer to Align string.\r
+  AlignNumber    - Pointer to Align value.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Successfully convert align string to align value.\r
+  EFI_INVALID_PARAMETER   Align string is invalid or align value is not in scope.\r
+\r
+--*/\r
+{\r
+  UINT32 Index = 0;\r
+  //\r
+  // Check AlignBuffer\r
+  //\r
+  if (AlignBuffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) {\r
+    if (stricmp (AlignBuffer, mAlignName [Index]) == 0) {\r
+      *AlignNumber = 1 << Index;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
 EFI_STATUS\r
 GetSectionContents (\r
   CHAR8   **InputFileName,\r
+  UINT32  *InputFileAlign,\r
   UINT32  InputFileNum,\r
   UINT8   *FileBuffer,\r
   UINT32  *BufferLength\r
@@ -346,7 +411,9 @@ Routine Description:
 Arguments:\r
                \r
   InputFileName  - Name of the input file.\r
-                \r
+\r
+  InputFileAlign - Alignment required by the input file data.\r
+\r
   InputFileNum   - Number of input files. Should be at least 1.\r
 \r
   FileBuffer     - Output buffer to contain data\r
@@ -362,10 +429,18 @@ Returns:
   EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.\r
 --*/\r
 {\r
-  UINT32   Size;\r
-  UINT32   FileSize;\r
-  UINT32   Index;\r
-  FILE    *InFile;\r
+  UINT32                     Size;\r
+  UINT32                     Offset;\r
+  UINT32                     FileSize;\r
+  UINT32                     Index;\r
+  FILE                       *InFile;\r
+  EFI_COMMON_SECTION_HEADER  *SectHeader;\r
+  EFI_COMMON_SECTION_HEADER2 TempSectHeader;\r
+  EFI_TE_IMAGE_HEADER        TeHeader;\r
+  UINT32                     TeOffset;\r
+  EFI_GUID_DEFINED_SECTION   GuidSectHeader;\r
+  EFI_GUID_DEFINED_SECTION2  GuidSectHeader2;\r
+  UINT32                     HeaderSize;\r
 \r
   if (InputFileNum < 1) {\r
     Error (NULL, 0, 2000, "Invalid paramter", "must specify at least one input file");\r
@@ -377,7 +452,9 @@ Returns:
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Size = 0;\r
+  Size          = 0;\r
+  Offset        = 0;\r
+  TeOffset      = 0;\r
   //\r
   // Go through our array of file names and copy their contents\r
   // to the output buffer.\r
@@ -396,7 +473,7 @@ Returns:
     // \r
     // Open file and read contents\r
     //\r
-    InFile = fopen (InputFileName[Index], "rb");\r
+    InFile = fopen (LongFilePath (InputFileName[Index]), "rb");\r
     if (InFile == NULL) {\r
       Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);\r
       return EFI_ABORTED;\r
@@ -406,11 +483,84 @@ Returns:
     FileSize = ftell (InFile);\r
     fseek (InFile, 0, SEEK_SET);\r
     DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize); \r
+    //\r
+    // Adjust section buffer when section alignment is required.\r
+    //\r
+    if (InputFileAlign != NULL) {\r
+      //\r
+      // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.\r
+      //\r
+      TeOffset = 0;\r
+      //\r
+      // The section might be EFI_COMMON_SECTION_HEADER2\r
+      // But only Type needs to be checked\r
+      //\r
+      if (FileSize >= MAX_SECTION_SIZE) {\r
+        HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);\r
+      } else {\r
+        HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);\r
+      }\r
+      fread (&TempSectHeader, 1, HeaderSize, InFile);\r
+      if (TempSectHeader.Type == EFI_SECTION_TE) {\r
+        fread (&TeHeader, 1, sizeof (TeHeader), InFile);\r
+        if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+          TeOffset = TeHeader.StrippedSize - sizeof (TeHeader);\r
+        }\r
+      } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) {\r
+        fseek (InFile, 0, SEEK_SET);\r
+        if (FileSize >= MAX_SECTION_SIZE) {\r
+          fread (&GuidSectHeader2, 1, sizeof (GuidSectHeader2), InFile);\r
+          if ((GuidSectHeader2.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {\r
+            HeaderSize = GuidSectHeader2.DataOffset;\r
+          }\r
+        } else {\r
+          fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile);\r
+          if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {\r
+            HeaderSize = GuidSectHeader.DataOffset;\r
+          }\r
+        }\r
+      } \r
+\r
+      fseek (InFile, 0, SEEK_SET);\r
+\r
+      //\r
+      // Revert TeOffset to the converse value relative to Alignment\r
+      // This is to assure the original PeImage Header at Alignment.\r
+      //\r
+      if (TeOffset != 0) {\r
+        TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]);\r
+        TeOffset = TeOffset % InputFileAlign [Index];\r
+      }\r
+\r
+      //\r
+      // make sure section data meet its alignment requirement by adding one raw pad section.\r
+      //\r
+      if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) {\r
+        Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);\r
+        Offset = Offset - Size - HeaderSize - TeOffset;\r
+         \r
+        if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {\r
+          //\r
+          // The maximal alignment is 64K, the raw section size must be less than 0xffffff\r
+          //\r
+          memset (FileBuffer + Size, 0, Offset);\r
+          SectHeader          = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size);\r
+          SectHeader->Type    = EFI_SECTION_RAW;\r
+          SectHeader->Size[0] = (UINT8) (Offset & 0xff);\r
+          SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8);\r
+          SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);\r
+        }\r
+        DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset);\r
+\r
+        Size = Size + Offset;\r
+      }\r
+    }\r
+\r
     //\r
     // Now read the contents of the file into the buffer\r
     // Buffer must be enough to contain the file content.\r
     //\r
-    if (FileSize > 0 && FileBuffer != NULL && (Size + FileSize) <= *BufferLength) {\r
+    if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) {\r
       if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {\r
         Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);\r
         fclose (InFile);\r
@@ -437,6 +587,7 @@ Returns:
 EFI_STATUS\r
 GenSectionCompressionSection (\r
   CHAR8   **InputFileName,\r
+  UINT32  *InputFileAlign,\r
   UINT32  InputFileNum,\r
   UINT8   SectCompSubType,\r
   UINT8   **OutFileBuffer\r
@@ -453,7 +604,9 @@ Routine Description:
 Arguments:\r
                \r
   InputFileName  - Name of the input file.\r
-                \r
+\r
+  InputFileAlign - Alignment required by the input file data.\r
+\r
   InputFileNum   - Number of input files. Should be at least 1.\r
 \r
   SectCompSubType - Specify the compression algorithm requested. \r
@@ -471,22 +624,26 @@ Returns:
   UINT32                  TotalLength;\r
   UINT32                  InputLength;\r
   UINT32                  CompressedLength;\r
+  UINT32                  HeaderLength;\r
   UINT8                   *FileBuffer;\r
   UINT8                   *OutputBuffer;\r
   EFI_STATUS              Status;\r
   EFI_COMPRESSION_SECTION *CompressionSect;\r
+  EFI_COMPRESSION_SECTION2 *CompressionSect2;\r
   COMPRESS_FUNCTION       CompressFunction;\r
 \r
   InputLength       = 0;\r
   FileBuffer        = NULL;\r
   OutputBuffer      = NULL;\r
   CompressedLength  = 0;\r
+  TotalLength       = 0;\r
   //\r
   // read all input file contents into a buffer\r
   // first get the size of all file contents\r
   //\r
   Status = GetSectionContents (\r
             InputFileName,\r
+            InputFileAlign,\r
             InputFileNum,\r
             FileBuffer,\r
             &InputLength\r
@@ -503,6 +660,7 @@ Returns:
     //\r
     Status = GetSectionContents (\r
               InputFileName,\r
+              InputFileAlign,\r
               InputFileNum,\r
               FileBuffer,\r
               &InputLength\r
@@ -524,6 +682,22 @@ Returns:
   switch (SectCompSubType) {\r
   case EFI_NOT_COMPRESSED:\r
     CompressedLength = InputLength;\r
+    HeaderLength = sizeof (EFI_COMPRESSION_SECTION);\r
+    if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {\r
+      HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);\r
+    }\r
+    TotalLength = CompressedLength + HeaderLength;\r
+    //\r
+    // Copy file buffer to the none compressed data.\r
+    //\r
+    OutputBuffer = malloc (TotalLength);\r
+    if (OutputBuffer == NULL) {\r
+      free (FileBuffer);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength);\r
+    free (FileBuffer);\r
+    FileBuffer = OutputBuffer;\r
     break;\r
 \r
   case EFI_STANDARD_COMPRESSION:\r
@@ -540,13 +714,18 @@ Returns:
 \r
     Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);\r
     if (Status == EFI_BUFFER_TOO_SMALL) {\r
-      OutputBuffer = malloc (CompressedLength + sizeof (EFI_COMPRESSION_SECTION));\r
+      HeaderLength = sizeof (EFI_COMPRESSION_SECTION);\r
+      if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {\r
+        HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);\r
+      }\r
+      TotalLength = CompressedLength + HeaderLength;\r
+      OutputBuffer = malloc (TotalLength);\r
       if (!OutputBuffer) {\r
         free (FileBuffer);\r
         return EFI_OUT_OF_RESOURCES;\r
       }\r
 \r
-      Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + sizeof (EFI_COMPRESSION_SECTION), &CompressedLength);\r
+      Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength);\r
     }\r
 \r
     free (FileBuffer);\r
@@ -563,30 +742,40 @@ Returns:
 \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
-  TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);\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
-    if (FileBuffer != NULL) {\r
-      free (FileBuffer);\r
-    }\r
-    if (OutputBuffer != NULL) {\r
-      free (OutputBuffer);\r
-    }\r
-    return STATUS_ERROR;\r
-  }\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
+  //  if (FileBuffer != NULL) {\r
+  //    free (FileBuffer);\r
+  //  }\r
+  //  if (OutputBuffer != NULL) {\r
+  //    free (OutputBuffer);\r
+  //  }\r
+  //  return STATUS_ERROR;\r
+  //}\r
   VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
 \r
   //\r
   // Add the section header for the compressed data\r
   //\r
-  CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;\r
-  \r
-  CompressionSect->CommonHeader.Type     = EFI_SECTION_COMPRESSION;\r
-  CompressionSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
-  CompressionSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
-  CompressionSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
-  CompressionSect->CompressionType       = SectCompSubType;\r
-  CompressionSect->UncompressedLength    = InputLength;\r
+  if (TotalLength >= MAX_SECTION_SIZE) {\r
+    CompressionSect2 = (EFI_COMPRESSION_SECTION2 *)FileBuffer;\r
+\r
+    memset(CompressionSect2->CommonHeader.Size, 0xff, sizeof(UINT8) * 3);\r
+    CompressionSect2->CommonHeader.Type         = EFI_SECTION_COMPRESSION;\r
+    CompressionSect2->CommonHeader.ExtendedSize = TotalLength;\r
+    CompressionSect2->CompressionType           = SectCompSubType;\r
+    CompressionSect2->UncompressedLength        = InputLength;\r
+  } else {\r
+    CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;\r
+    \r
+    CompressionSect->CommonHeader.Type     = EFI_SECTION_COMPRESSION;\r
+    CompressionSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
+    CompressionSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
+    CompressionSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
+    CompressionSect->CompressionType       = SectCompSubType;\r
+    CompressionSect->UncompressedLength    = InputLength;\r
+  }\r
 \r
   //\r
   // Set OutFileBuffer \r
@@ -599,6 +788,7 @@ Returns:
 EFI_STATUS\r
 GenSectionGuidDefinedSection (\r
   CHAR8    **InputFileName,\r
+  UINT32   *InputFileAlign,\r
   UINT32   InputFileNum,\r
   EFI_GUID *VendorGuid,\r
   UINT16   DataAttribute,\r
@@ -618,6 +808,8 @@ Arguments:
                \r
   InputFileName - Name of the input file.\r
                 \r
+  InputFileAlign - Alignment required by the input file data.\r
+\r
   InputFileNum  - Number of input files. Should be at least 1.\r
 \r
   VendorGuid    - Specify vendor guid value.\r
@@ -644,17 +836,14 @@ Returns:
   UINT32                Crc32Checksum;\r
   EFI_STATUS            Status;\r
   CRC32_SECTION_HEADER  *Crc32GuidSect;\r
+  CRC32_SECTION_HEADER2  *Crc32GuidSect2;\r
   EFI_GUID_DEFINED_SECTION  *VendorGuidSect;\r
+  EFI_GUID_DEFINED_SECTION2  *VendorGuidSect2;\r
 \r
   InputLength = 0;\r
   Offset      = 0;\r
   FileBuffer  = NULL;\r
-\r
-  if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {\r
-    Offset = sizeof (CRC32_SECTION_HEADER);\r
-  } else {\r
-    Offset = sizeof (EFI_GUID_DEFINED_SECTION);\r
-  }\r
+  TotalLength = 0;\r
 \r
   //\r
   // read all input file contents into a buffer\r
@@ -662,12 +851,26 @@ Returns:
   //\r
   Status = GetSectionContents (\r
             InputFileName,\r
+            InputFileAlign,\r
             InputFileNum,\r
             FileBuffer,\r
             &InputLength\r
             );\r
 \r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {\r
+      Offset = sizeof (CRC32_SECTION_HEADER);\r
+      if (InputLength + Offset >= MAX_SECTION_SIZE) {\r
+        Offset = sizeof (CRC32_SECTION_HEADER2);\r
+      }\r
+    } else {\r
+      Offset = sizeof (EFI_GUID_DEFINED_SECTION);\r
+      if (InputLength + Offset >= MAX_SECTION_SIZE) {\r
+        Offset = sizeof (EFI_GUID_DEFINED_SECTION2);\r
+      }\r
+    }\r
+    TotalLength = InputLength + Offset;\r
+\r
     FileBuffer = (UINT8 *) malloc (InputLength + Offset);\r
     if (FileBuffer == NULL) {\r
       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
@@ -678,6 +881,7 @@ Returns:
     //\r
     Status = GetSectionContents (\r
               InputFileName,\r
+              InputFileAlign,\r
               InputFileNum,\r
               FileBuffer + Offset,\r
               &InputLength\r
@@ -700,48 +904,60 @@ Returns:
   //\r
   // Now data is in FileBuffer + Offset\r
   //\r
-  if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {\r
+  if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {\r
     //\r
     // Default Guid section is CRC32.\r
     //\r
     Crc32Checksum = 0;\r
     CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);\r
-\r
-    TotalLength = InputLength + sizeof (CRC32_SECTION_HEADER);\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
-      free (FileBuffer);\r
-      return STATUS_ERROR;\r
+      Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer;\r
+      Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
+      Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) 0xff;\r
+      Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) 0xff;\r
+      Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) 0xff;\r
+      Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength;\r
+      memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
+      Crc32GuidSect2->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
+      Crc32GuidSect2->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER2);\r
+      Crc32GuidSect2->CRC32Checksum                 = Crc32Checksum;\r
+      DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset);\r
+    } else {\r
+      Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;\r
+      Crc32GuidSect->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
+      Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
+      Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
+      Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
+      memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
+      Crc32GuidSect->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
+      Crc32GuidSect->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER);\r
+      Crc32GuidSect->CRC32Checksum                 = Crc32Checksum;\r
+      DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);\r
     }\r
-    \r
-    Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;\r
-    Crc32GuidSect->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
-    Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
-    Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
-    Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
-    memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
-    Crc32GuidSect->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
-    Crc32GuidSect->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER);\r
-    Crc32GuidSect->CRC32Checksum                 = Crc32Checksum;\r
-    DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);\r
-\r
   } else {\r
-    TotalLength = InputLength + sizeof (EFI_GUID_DEFINED_SECTION);\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
-      free (FileBuffer);\r
-      return STATUS_ERROR;\r
+      VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer;\r
+      VendorGuidSect2->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
+      VendorGuidSect2->CommonHeader.Size[0]  = (UINT8) 0xff;\r
+      VendorGuidSect2->CommonHeader.Size[1]  = (UINT8) 0xff;\r
+      VendorGuidSect2->CommonHeader.Size[2]  = (UINT8) 0xff;\r
+      VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2);\r
+      memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));\r
+      VendorGuidSect2->Attributes  = DataAttribute;\r
+      VendorGuidSect2->DataOffset  = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize);\r
+      DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset);\r
+    } else {\r
+      VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;\r
+      VendorGuidSect->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
+      VendorGuidSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
+      VendorGuidSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
+      VendorGuidSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
+      memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));\r
+      VendorGuidSect->Attributes  = DataAttribute;\r
+      VendorGuidSect->DataOffset  = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);\r
+      DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);\r
     }\r
-\r
-    VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;\r
-    VendorGuidSect->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
-    VendorGuidSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
-    VendorGuidSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
-    VendorGuidSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
-    memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));\r
-    VendorGuidSect->Attributes  = DataAttribute;\r
-    VendorGuidSect->DataOffset  = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);\r
-    DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);\r
   }\r
   VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
   \r
@@ -778,7 +994,6 @@ Returns:
 {\r
   UINT32                    Index;\r
   UINT32                    InputFileNum;\r
-  FILE                      *InFile;\r
   FILE                      *OutFile;\r
   CHAR8                     **InputFileName;\r
   CHAR8                     *OutputFileName;\r
@@ -797,19 +1012,23 @@ Returns:
   UINT8                     *OutFileBuffer;\r
   EFI_STATUS                Status;\r
   UINT64                    LogLevel;\r
-  \r
+  UINT32                    *InputFileAlign;\r
+  UINT32                    InputFileAlignNum;\r
+  EFI_COMMON_SECTION_HEADER *SectionHeader;\r
+\r
+  InputFileAlign        = NULL;\r
+  InputFileAlignNum     = 0;\r
   InputFileName         = NULL;\r
   OutputFileName        = NULL;\r
   SectionName           = NULL;\r
   CompressionName       = NULL;\r
   StringBuffer          = "";\r
-  InFile                = NULL;\r
   OutFile               = NULL;\r
   VersionNumber         = 0;\r
   InputFileNum          = 0;\r
   SectType              = EFI_SECTION_ALL;\r
   SectCompSubType       = 0;\r
-  SectGuidAttribute     = 0;\r
+  SectGuidAttribute     = EFI_GUIDED_SECTION_NONE;\r
   OutFileBuffer         = NULL;\r
   InputLength           = 0;\r
   Status                = STATUS_SUCCESS;\r
@@ -938,7 +1157,7 @@ Returns:
       // Verify string is a integrator number\r
       //\r
       for (Index = 0; Index < strlen (argv[1]); Index++) {\r
-        if ((argv[1][Index] != '-') && (isdigit (argv[1][Index]) == 0)) {\r
+        if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {\r
           Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
           goto Finish;\r
         }\r
@@ -983,6 +1202,41 @@ Returns:
       continue;\r
     }\r
 \r
+    //\r
+    // Section File alignment requirement\r
+    //\r
+    if (stricmp (argv[0], "--sectionalign") == 0) {\r
+      if (InputFileAlignNum == 0) {\r
+        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
+        }\r
+        memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
+      } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
+        InputFileAlign = (UINT32 *) realloc (\r
+          InputFileAlign,\r
+          (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)\r
+          );\r
+\r
+        if (InputFileAlign == NULL) {\r
+          Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+          return 1;\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
+      }\r
+      argc -= 2;\r
+      argv += 2;\r
+      InputFileAlignNum ++;\r
+      continue; \r
+    }\r
+\r
     //\r
     // Get Input file name\r
     //\r
@@ -992,7 +1246,6 @@ Returns:
         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
         return 1;\r
       }\r
-\r
       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
       //\r
@@ -1007,7 +1260,6 @@ Returns:
         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
         return 1;\r
       }\r
-\r
       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
     }\r
 \r
@@ -1016,6 +1268,11 @@ Returns:
     argv ++;\r
   }\r
 \r
+  if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {\r
+    Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");\r
+    goto Finish;\r
+  }\r
+\r
   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
 \r
   //\r
@@ -1045,19 +1302,12 @@ Returns:
     VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);\r
   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {\r
     SectType     = EFI_SECTION_GUID_DEFINED;\r
-\r
-    if (CompareGuid (&VendorGuid, &mZeroGuid) == 0) {\r
-      memcpy (&VendorGuid, &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
-    }\r
     \r
-    if (SectGuidAttribute == 0) {\r
-      SectGuidAttribute = EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
-    }\r
     if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {\r
       //\r
       // NONE attribute, clear attribute value.\r
       //\r
-      SectGuidAttribute = 0;\r
+      SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;\r
     }\r
     VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", \r
                 (unsigned) VendorGuid.Data1,\r
@@ -1092,8 +1342,8 @@ Returns:
     SectType = EFI_SECTION_SMM_DEPEX;\r
   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {\r
     SectType = EFI_SECTION_VERSION;\r
-    if (VersionNumber < 0 || VersionNumber > 9999) {\r
-      Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~9999", VersionNumber);\r
+    if (VersionNumber < 0 || VersionNumber > 65535) {\r
+      Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);\r
       goto Finish;\r
     }\r
     VerboseMsg ("Version section number is %d", VersionNumber);\r
@@ -1161,8 +1411,13 @@ Returns:
   //\r
   switch (SectType) {\r
   case EFI_SECTION_COMPRESSION:\r
+    if (InputFileAlign != NULL) {\r
+      free (InputFileAlign);\r
+      InputFileAlign = NULL;\r
+    }\r
     Status = GenSectionCompressionSection (\r
               InputFileName,\r
+              InputFileAlign,\r
               InputFileNum,\r
               SectCompSubType,\r
               &OutFileBuffer\r
@@ -1170,8 +1425,17 @@ Returns:
     break;\r
 \r
   case EFI_SECTION_GUID_DEFINED:\r
+    if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
+      //\r
+      // Only process alignment for the default known CRC32 guided section.\r
+      // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.\r
+      //\r
+      free (InputFileAlign);\r
+      InputFileAlign = NULL;\r
+    }\r
     Status = GenSectionGuidDefinedSection (\r
               InputFileName,\r
+              InputFileAlign,\r
               InputFileNum,\r
               &VendorGuid,\r
               SectGuidAttribute,\r
@@ -1232,6 +1496,7 @@ Returns:
     //\r
     Status = GetSectionContents (\r
               InputFileName,\r
+              InputFileAlign,\r
               InputFileNum,\r
               OutFileBuffer,\r
               &InputLength\r
@@ -1248,6 +1513,7 @@ Returns:
       //\r
       Status = GetSectionContents (\r
                 InputFileName,\r
+                InputFileAlign,\r
                 InputFileNum,\r
                 OutFileBuffer,\r
                 &InputLength\r
@@ -1277,13 +1543,17 @@ Returns:
   // Get output file length\r
   //\r
   if (SectType != EFI_SECTION_ALL) {\r
-    InputLength = SECTION_SIZE (OutFileBuffer);\r
+    SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer;\r
+    InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff;\r
+    if (InputLength == 0xffffff) {\r
+      InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;\r
+    }\r
   }\r
   \r
   //\r
   // Write the output file\r
   //\r
-  OutFile = fopen (OutputFileName, "wb");\r
+  OutFile = fopen (LongFilePath (OutputFileName), "wb");\r
   if (OutFile == NULL) {\r
     Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);\r
     goto Finish;\r
@@ -1296,6 +1566,10 @@ Finish:
     free (InputFileName);\r
   }\r
 \r
+  if (InputFileAlign != NULL) {\r
+    free (InputFileAlign);\r
+  }\r
+\r
   if (OutFileBuffer != NULL) {\r
     free (OutFileBuffer);\r
   }\r