Home | History | Annotate | Download | only in GenSec
      1 /** @file
      2 Creates output file that is a properly formed section per the PI spec.
      3 
      4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include <stdio.h>
     16 #include <stdlib.h>
     17 #include <string.h>
     18 #include <ctype.h>
     19 
     20 #include <Common/UefiBaseTypes.h>
     21 #include <Common/PiFirmwareFile.h>
     22 #include <Protocol/GuidedSectionExtraction.h>
     23 #include <IndustryStandard/PeImage.h>
     24 
     25 #include "CommonLib.h"
     26 #include "Compress.h"
     27 #include "Crc32.h"
     28 #include "EfiUtilityMsgs.h"
     29 #include "ParseInf.h"
     30 
     31 //
     32 // GenSec Tool Information
     33 //
     34 #define UTILITY_NAME            "GenSec"
     35 #define UTILITY_MAJOR_VERSION   0
     36 #define UTILITY_MINOR_VERSION   1
     37 
     38 STATIC CHAR8      *mSectionTypeName[] = {
     39   NULL,                                 // 0x00 - reserved
     40   "EFI_SECTION_COMPRESSION",            // 0x01
     41   "EFI_SECTION_GUID_DEFINED",           // 0x02
     42   NULL,                                 // 0x03 - reserved
     43   NULL,                                 // 0x04 - reserved
     44   NULL,                                 // 0x05 - reserved
     45   NULL,                                 // 0x06 - reserved
     46   NULL,                                 // 0x07 - reserved
     47   NULL,                                 // 0x08 - reserved
     48   NULL,                                 // 0x09 - reserved
     49   NULL,                                 // 0x0A - reserved
     50   NULL,                                 // 0x0B - reserved
     51   NULL,                                 // 0x0C - reserved
     52   NULL,                                 // 0x0D - reserved
     53   NULL,                                 // 0x0E - reserved
     54   NULL,                                 // 0x0F - reserved
     55   "EFI_SECTION_PE32",                   // 0x10
     56   "EFI_SECTION_PIC",                    // 0x11
     57   "EFI_SECTION_TE",                     // 0x12
     58   "EFI_SECTION_DXE_DEPEX",              // 0x13
     59   "EFI_SECTION_VERSION",                // 0x14
     60   "EFI_SECTION_USER_INTERFACE",         // 0x15
     61   "EFI_SECTION_COMPATIBILITY16",        // 0x16
     62   "EFI_SECTION_FIRMWARE_VOLUME_IMAGE",  // 0x17
     63   "EFI_SECTION_FREEFORM_SUBTYPE_GUID",  // 0x18
     64   "EFI_SECTION_RAW",                    // 0x19
     65   NULL,                                 // 0x1A
     66   "EFI_SECTION_PEI_DEPEX",              // 0x1B
     67   "EFI_SECTION_SMM_DEPEX"               // 0x1C
     68 };
     69 
     70 STATIC CHAR8      *mCompressionTypeName[]    = { "PI_NONE", "PI_STD" };
     71 
     72 #define EFI_GUIDED_SECTION_NONE 0x80
     73 STATIC CHAR8      *mGUIDedSectionAttribue[]  = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};
     74 
     75 STATIC CHAR8 *mAlignName[] = {
     76   "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
     77   "1K", "2K", "4K", "8K", "16K", "32K", "64K"
     78 };
     79 
     80 //
     81 // Crc32 GUID section related definitions.
     82 //
     83 typedef struct {
     84   EFI_GUID_DEFINED_SECTION  GuidSectionHeader;
     85   UINT32                    CRC32Checksum;
     86 } CRC32_SECTION_HEADER;
     87 
     88 typedef struct {
     89   EFI_GUID_DEFINED_SECTION2 GuidSectionHeader;
     90   UINT32                    CRC32Checksum;
     91 } CRC32_SECTION_HEADER2;
     92 
     93 STATIC EFI_GUID  mZeroGuid                 = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
     94 STATIC EFI_GUID  mEfiCrc32SectionGuid      = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
     95 
     96 STATIC
     97 VOID
     98 Version (
     99   VOID
    100   )
    101 /*++
    102 
    103 Routine Description:
    104 
    105   Print out version information for this utility.
    106 
    107 Arguments:
    108 
    109   None
    110 
    111 Returns:
    112 
    113   None
    114 
    115 --*/
    116 {
    117   fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
    118 }
    119 
    120 STATIC
    121 VOID
    122 Usage (
    123   VOID
    124   )
    125 /*++
    126 
    127 Routine Description:
    128 
    129   Print Help message.
    130 
    131 Arguments:
    132 
    133   VOID
    134 
    135 Returns:
    136 
    137   None
    138 
    139 --*/
    140 {
    141   //
    142   // Summary usage
    143   //
    144   fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME);
    145 
    146   //
    147   // Copyright declaration
    148   //
    149   fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");
    150 
    151   //
    152   // Details Option
    153   //
    154   fprintf (stdout, "Options:\n");
    155   fprintf (stdout, "  -o FileName, --outputfile FileName\n\
    156                         File is the SectionFile to be created.\n");
    157   fprintf (stdout, "  -s [SectionType], --sectiontype [SectionType]\n\
    158                         SectionType defined in PI spec is one type of\n\
    159                         EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\
    160                         EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\
    161                         EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\
    162                         EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\
    163                         EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\
    164                         EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\
    165                         EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\
    166                         if -s option is not given, \n\
    167                         EFI_SECTION_ALL is default section type.\n");
    168   fprintf (stdout, "  -c [Type], --compress [Type]\n\
    169                         Compress method type can be PI_NONE or PI_STD.\n\
    170                         if -c option is not given, PI_STD is default type.\n");
    171   fprintf (stdout, "  -g GuidValue, --vendor GuidValue\n\
    172                         GuidValue is one specific vendor guid value.\n\
    173                         Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
    174   fprintf (stdout, "  -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
    175                         GuidHeaderLength is the size of header of guided data\n");
    176   fprintf (stdout, "  -r GuidAttr, --attributes GuidAttr\n\
    177                         GuidAttr is guid section atttributes, which may be\n\
    178                         PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
    179                         if -r option is not given, default PROCESSING_REQUIRED\n");
    180   fprintf (stdout, "  -n String, --name String\n\
    181                         String is a NULL terminated string used in Ui section.\n");
    182   fprintf (stdout, "  -j Number, --buildnumber Number\n\
    183                         Number is an integer value between 0 and 65535\n\
    184                         used in Ver section.\n");
    185   fprintf (stdout, "  --sectionalign SectionAlign\n\
    186                         SectionAlign points to section alignment, which support\n\
    187                         the alignment scope 1~64K. It is specified in same\n\
    188                         order that the section file is input.\n");
    189   fprintf (stdout, "  -v, --verbose         Turn on verbose output with informational messages.\n");
    190   fprintf (stdout, "  -q, --quiet           Disable all messages except key message and fatal error\n");
    191   fprintf (stdout, "  -d, --debug level     Enable debug messages, at input debug level.\n");
    192   fprintf (stdout, "  --version             Show program's version number and exit.\n");
    193   fprintf (stdout, "  -h, --help            Show this help message and exit.\n");
    194 }
    195 
    196 VOID
    197 Ascii2UnicodeString (
    198   CHAR8    *String,
    199   CHAR16   *UniString
    200   )
    201 /*++
    202 
    203 Routine Description:
    204 
    205   Write ascii string as unicode string format to FILE
    206 
    207 Arguments:
    208 
    209   String      - Pointer to string that is written to FILE.
    210   UniString   - Pointer to unicode string
    211 
    212 Returns:
    213 
    214   NULL
    215 
    216 --*/
    217 {
    218   while (*String != '\0') {
    219     *(UniString++) = (CHAR16) *(String++);
    220   }
    221   //
    222   // End the UniString with a NULL.
    223   //
    224   *UniString = '\0';
    225 }
    226 
    227 STATUS
    228 GenSectionCommonLeafSection (
    229   CHAR8   **InputFileName,
    230   UINT32  InputFileNum,
    231   UINT8   SectionType,
    232   UINT8   **OutFileBuffer
    233   )
    234 /*++
    235 
    236 Routine Description:
    237 
    238   Generate a leaf section of type other than EFI_SECTION_VERSION
    239   and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
    240   The function won't validate the input file's contents. For
    241   common leaf sections, the input file may be a binary file.
    242   The utility will add section header to the file.
    243 
    244 Arguments:
    245 
    246   InputFileName  - Name of the input file.
    247 
    248   InputFileNum   - Number of input files. Should be 1 for leaf section.
    249 
    250   SectionType    - A valid section type string
    251 
    252   OutFileBuffer  - Buffer pointer to Output file contents
    253 
    254 Returns:
    255 
    256   STATUS_ERROR            - can't continue
    257   STATUS_SUCCESS          - successful return
    258 
    259 --*/
    260 {
    261   UINT32                    InputFileLength;
    262   FILE                      *InFile;
    263   UINT8                     *Buffer;
    264   UINT32                    TotalLength;
    265   UINT32                    HeaderLength;
    266   EFI_COMMON_SECTION_HEADER *CommonSect;
    267   STATUS                    Status;
    268 
    269   if (InputFileNum > 1) {
    270     Error (NULL, 0, 2000, "Invalid paramter", "more than one input file specified");
    271     return STATUS_ERROR;
    272   } else if (InputFileNum < 1) {
    273     Error (NULL, 0, 2000, "Invalid paramter", "no input file specified");
    274     return STATUS_ERROR;
    275   }
    276   //
    277   // Open the input file
    278   //
    279   InFile = fopen (LongFilePath (InputFileName[0]), "rb");
    280   if (InFile == NULL) {
    281     Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);
    282     return STATUS_ERROR;
    283   }
    284 
    285   Status  = STATUS_ERROR;
    286   Buffer  = NULL;
    287   //
    288   // Seek to the end of the input file so we can determine its size
    289   //
    290   fseek (InFile, 0, SEEK_END);
    291   InputFileLength = ftell (InFile);
    292   fseek (InFile, 0, SEEK_SET);
    293   DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName[0], (unsigned) InputFileLength);
    294   TotalLength     = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength;
    295   //
    296   // Size must fit in 3 bytes
    297   //
    298   //if (TotalLength >= MAX_SECTION_SIZE) {
    299   //  Error (NULL, 0, 2000, "Invalid paramter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20);
    300   //  goto Done;
    301   //}
    302   HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER);
    303   if (TotalLength >= MAX_SECTION_SIZE) {
    304     TotalLength = sizeof (EFI_COMMON_SECTION_HEADER2) + InputFileLength;
    305     HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER2);
    306   }
    307   VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
    308   //
    309   // Fill in the fields in the local section header structure
    310   //
    311   Buffer = (UINT8 *) malloc ((size_t) TotalLength);
    312   if (Buffer == NULL) {
    313     Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
    314     goto Done;
    315   }
    316   CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer;
    317   CommonSect->Type     = SectionType;
    318   if (TotalLength < MAX_SECTION_SIZE) {
    319     CommonSect->Size[0]  = (UINT8) (TotalLength & 0xff);
    320     CommonSect->Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
    321     CommonSect->Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
    322   } else {
    323     memset(CommonSect->Size, 0xff, sizeof(UINT8) * 3);
    324     ((EFI_COMMON_SECTION_HEADER2 *)CommonSect)->ExtendedSize = TotalLength;
    325   }
    326 
    327   //
    328   // read data from the input file.
    329   //
    330   if (InputFileLength != 0) {
    331     if (fread (Buffer + HeaderLength, (size_t) InputFileLength, 1, InFile) != 1) {
    332       Error (NULL, 0, 0004, "Error reading file", InputFileName[0]);
    333       goto Done;
    334     }
    335   }
    336 
    337   //
    338   // Set OutFileBuffer
    339   //
    340   *OutFileBuffer = Buffer;
    341   Status = STATUS_SUCCESS;
    342 
    343 Done:
    344   fclose (InFile);
    345 
    346   return Status;
    347 }
    348 
    349 STATIC
    350 EFI_STATUS
    351 StringtoAlignment (
    352   IN  CHAR8  *AlignBuffer,
    353   OUT UINT32 *AlignNumber
    354   )
    355 /*++
    356 
    357 Routine Description:
    358 
    359   Converts Align String to align value (1~64K).
    360 
    361 Arguments:
    362 
    363   AlignBuffer    - Pointer to Align string.
    364   AlignNumber    - Pointer to Align value.
    365 
    366 Returns:
    367 
    368   EFI_SUCCESS             Successfully convert align string to align value.
    369   EFI_INVALID_PARAMETER   Align string is invalid or align value is not in scope.
    370 
    371 --*/
    372 {
    373   UINT32 Index = 0;
    374   //
    375   // Check AlignBuffer
    376   //
    377   if (AlignBuffer == NULL) {
    378     return EFI_INVALID_PARAMETER;
    379   }
    380   for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) {
    381     if (stricmp (AlignBuffer, mAlignName [Index]) == 0) {
    382       *AlignNumber = 1 << Index;
    383       return EFI_SUCCESS;
    384     }
    385   }
    386   return EFI_INVALID_PARAMETER;
    387 }
    388 
    389 EFI_STATUS
    390 GetSectionContents (
    391   CHAR8   **InputFileName,
    392   UINT32  *InputFileAlign,
    393   UINT32  InputFileNum,
    394   UINT8   *FileBuffer,
    395   UINT32  *BufferLength
    396   )
    397 /*++
    398 
    399 Routine Description:
    400 
    401   Get the contents of all section files specified in InputFileName
    402   into FileBuffer.
    403 
    404 Arguments:
    405 
    406   InputFileName  - Name of the input file.
    407 
    408   InputFileAlign - Alignment required by the input file data.
    409 
    410   InputFileNum   - Number of input files. Should be at least 1.
    411 
    412   FileBuffer     - Output buffer to contain data
    413 
    414   BufferLength   - On input, this is size of the FileBuffer.
    415                    On output, this is the actual length of the data.
    416 
    417 Returns:
    418 
    419   EFI_SUCCESS on successful return
    420   EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
    421   EFI_ABORTED if unable to open input file.
    422   EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
    423 --*/
    424 {
    425   UINT32                     Size;
    426   UINT32                     Offset;
    427   UINT32                     FileSize;
    428   UINT32                     Index;
    429   FILE                       *InFile;
    430   EFI_COMMON_SECTION_HEADER  *SectHeader;
    431   EFI_COMMON_SECTION_HEADER2 TempSectHeader;
    432   EFI_TE_IMAGE_HEADER        TeHeader;
    433   UINT32                     TeOffset;
    434   EFI_GUID_DEFINED_SECTION   GuidSectHeader;
    435   EFI_GUID_DEFINED_SECTION2  GuidSectHeader2;
    436   UINT32                     HeaderSize;
    437 
    438   if (InputFileNum < 1) {
    439     Error (NULL, 0, 2000, "Invalid paramter", "must specify at least one input file");
    440     return EFI_INVALID_PARAMETER;
    441   }
    442 
    443   if (BufferLength == NULL) {
    444     Error (NULL, 0, 2000, "Invalid paramter", "BufferLength can't be NULL");
    445     return EFI_INVALID_PARAMETER;
    446   }
    447 
    448   Size          = 0;
    449   Offset        = 0;
    450   TeOffset      = 0;
    451   //
    452   // Go through our array of file names and copy their contents
    453   // to the output buffer.
    454   //
    455   for (Index = 0; Index < InputFileNum; Index++) {
    456     //
    457     // make sure section ends on a DWORD boundary
    458     //
    459     while ((Size & 0x03) != 0) {
    460       if (FileBuffer != NULL && Size < *BufferLength) {
    461         FileBuffer[Size] = 0;
    462       }
    463       Size++;
    464     }
    465 
    466     //
    467     // Open file and read contents
    468     //
    469     InFile = fopen (LongFilePath (InputFileName[Index]), "rb");
    470     if (InFile == NULL) {
    471       Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);
    472       return EFI_ABORTED;
    473     }
    474 
    475     fseek (InFile, 0, SEEK_END);
    476     FileSize = ftell (InFile);
    477     fseek (InFile, 0, SEEK_SET);
    478     DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize);
    479     //
    480     // Adjust section buffer when section alignment is required.
    481     //
    482     if (InputFileAlign != NULL) {
    483       //
    484       // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
    485       //
    486       TeOffset = 0;
    487       //
    488       // The section might be EFI_COMMON_SECTION_HEADER2
    489       // But only Type needs to be checked
    490       //
    491       if (FileSize >= MAX_SECTION_SIZE) {
    492         HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);
    493       } else {
    494         HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);
    495       }
    496       fread (&TempSectHeader, 1, HeaderSize, InFile);
    497       if (TempSectHeader.Type == EFI_SECTION_TE) {
    498         fread (&TeHeader, 1, sizeof (TeHeader), InFile);
    499         if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
    500           TeOffset = TeHeader.StrippedSize - sizeof (TeHeader);
    501         }
    502       } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) {
    503         fseek (InFile, 0, SEEK_SET);
    504         if (FileSize >= MAX_SECTION_SIZE) {
    505           fread (&GuidSectHeader2, 1, sizeof (GuidSectHeader2), InFile);
    506           if ((GuidSectHeader2.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
    507             HeaderSize = GuidSectHeader2.DataOffset;
    508           }
    509         } else {
    510           fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile);
    511           if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
    512             HeaderSize = GuidSectHeader.DataOffset;
    513           }
    514         }
    515       }
    516 
    517       fseek (InFile, 0, SEEK_SET);
    518 
    519       //
    520       // Revert TeOffset to the converse value relative to Alignment
    521       // This is to assure the original PeImage Header at Alignment.
    522       //
    523       if (TeOffset != 0) {
    524         TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]);
    525         TeOffset = TeOffset % InputFileAlign [Index];
    526       }
    527 
    528       //
    529       // make sure section data meet its alignment requirement by adding one raw pad section.
    530       //
    531       if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) {
    532         Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);
    533         Offset = Offset - Size - HeaderSize - TeOffset;
    534 
    535         if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {
    536           //
    537           // The maximal alignment is 64K, the raw section size must be less than 0xffffff
    538           //
    539           memset (FileBuffer + Size, 0, Offset);
    540           SectHeader          = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size);
    541           SectHeader->Type    = EFI_SECTION_RAW;
    542           SectHeader->Size[0] = (UINT8) (Offset & 0xff);
    543           SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8);
    544           SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);
    545         }
    546         DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset);
    547 
    548         Size = Size + Offset;
    549       }
    550     }
    551 
    552     //
    553     // Now read the contents of the file into the buffer
    554     // Buffer must be enough to contain the file content.
    555     //
    556     if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) {
    557       if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
    558         Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);
    559         fclose (InFile);
    560         return EFI_ABORTED;
    561       }
    562     }
    563 
    564     fclose (InFile);
    565     Size += FileSize;
    566   }
    567 
    568   //
    569   // Set the real required buffer size.
    570   //
    571   if (Size > *BufferLength) {
    572     *BufferLength = Size;
    573     return EFI_BUFFER_TOO_SMALL;
    574   } else {
    575     *BufferLength = Size;
    576     return EFI_SUCCESS;
    577   }
    578 }
    579 
    580 EFI_STATUS
    581 GenSectionCompressionSection (
    582   CHAR8   **InputFileName,
    583   UINT32  *InputFileAlign,
    584   UINT32  InputFileNum,
    585   UINT8   SectCompSubType,
    586   UINT8   **OutFileBuffer
    587   )
    588 /*++
    589 
    590 Routine Description:
    591 
    592   Generate an encapsulating section of type EFI_SECTION_COMPRESSION
    593   Input file must be already sectioned. The function won't validate
    594   the input files' contents. Caller should hand in files already
    595   with section header.
    596 
    597 Arguments:
    598 
    599   InputFileName  - Name of the input file.
    600 
    601   InputFileAlign - Alignment required by the input file data.
    602 
    603   InputFileNum   - Number of input files. Should be at least 1.
    604 
    605   SectCompSubType - Specify the compression algorithm requested.
    606 
    607   OutFileBuffer   - Buffer pointer to Output file contents
    608 
    609 Returns:
    610 
    611   EFI_SUCCESS           on successful return
    612   EFI_INVALID_PARAMETER if InputFileNum is less than 1
    613   EFI_ABORTED           if unable to open input file.
    614   EFI_OUT_OF_RESOURCES  No resource to complete the operation.
    615 --*/
    616 {
    617   UINT32                  TotalLength;
    618   UINT32                  InputLength;
    619   UINT32                  CompressedLength;
    620   UINT32                  HeaderLength;
    621   UINT8                   *FileBuffer;
    622   UINT8                   *OutputBuffer;
    623   EFI_STATUS              Status;
    624   EFI_COMPRESSION_SECTION *CompressionSect;
    625   EFI_COMPRESSION_SECTION2 *CompressionSect2;
    626   COMPRESS_FUNCTION       CompressFunction;
    627 
    628   InputLength       = 0;
    629   FileBuffer        = NULL;
    630   OutputBuffer      = NULL;
    631   CompressedLength  = 0;
    632   TotalLength       = 0;
    633   //
    634   // read all input file contents into a buffer
    635   // first get the size of all file contents
    636   //
    637   Status = GetSectionContents (
    638             InputFileName,
    639             InputFileAlign,
    640             InputFileNum,
    641             FileBuffer,
    642             &InputLength
    643             );
    644 
    645   if (Status == EFI_BUFFER_TOO_SMALL) {
    646     FileBuffer = (UINT8 *) malloc (InputLength);
    647     if (FileBuffer == NULL) {
    648       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
    649       return EFI_OUT_OF_RESOURCES;
    650     }
    651     //
    652     // read all input file contents into a buffer
    653     //
    654     Status = GetSectionContents (
    655               InputFileName,
    656               InputFileAlign,
    657               InputFileNum,
    658               FileBuffer,
    659               &InputLength
    660               );
    661   }
    662 
    663   if (EFI_ERROR (Status)) {
    664     if (FileBuffer != NULL) {
    665       free (FileBuffer);
    666     }
    667     return Status;
    668   }
    669 
    670   CompressFunction = NULL;
    671 
    672   //
    673   // Now data is in FileBuffer, compress the data
    674   //
    675   switch (SectCompSubType) {
    676   case EFI_NOT_COMPRESSED:
    677     CompressedLength = InputLength;
    678     HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
    679     if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
    680       HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
    681     }
    682     TotalLength = CompressedLength + HeaderLength;
    683     //
    684     // Copy file buffer to the none compressed data.
    685     //
    686     OutputBuffer = malloc (TotalLength);
    687     if (OutputBuffer == NULL) {
    688       free (FileBuffer);
    689       return EFI_OUT_OF_RESOURCES;
    690     }
    691     memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength);
    692     free (FileBuffer);
    693     FileBuffer = OutputBuffer;
    694     break;
    695 
    696   case EFI_STANDARD_COMPRESSION:
    697     CompressFunction = (COMPRESS_FUNCTION) EfiCompress;
    698     break;
    699 
    700   default:
    701     Error (NULL, 0, 2000, "Invalid paramter", "unknown compression type");
    702     free (FileBuffer);
    703     return EFI_ABORTED;
    704   }
    705 
    706   if (CompressFunction != NULL) {
    707 
    708     Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
    709     if (Status == EFI_BUFFER_TOO_SMALL) {
    710       HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
    711       if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
    712         HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
    713       }
    714       TotalLength = CompressedLength + HeaderLength;
    715       OutputBuffer = malloc (TotalLength);
    716       if (!OutputBuffer) {
    717         free (FileBuffer);
    718         return EFI_OUT_OF_RESOURCES;
    719       }
    720 
    721       Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength);
    722     }
    723 
    724     free (FileBuffer);
    725     FileBuffer = OutputBuffer;
    726 
    727     if (EFI_ERROR (Status)) {
    728       if (FileBuffer != NULL) {
    729         free (FileBuffer);
    730       }
    731 
    732       return Status;
    733     }
    734   }
    735 
    736   DebugMsg (NULL, 0, 9, "comprss file size",
    737             "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);
    738 
    739   //if (TotalLength >= MAX_SECTION_SIZE) {
    740   //  Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);
    741   //  if (FileBuffer != NULL) {
    742   //    free (FileBuffer);
    743   //  }
    744   //  if (OutputBuffer != NULL) {
    745   //    free (OutputBuffer);
    746   //  }
    747   //  return STATUS_ERROR;
    748   //}
    749   VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
    750 
    751   //
    752   // Add the section header for the compressed data
    753   //
    754   if (TotalLength >= MAX_SECTION_SIZE) {
    755     CompressionSect2 = (EFI_COMPRESSION_SECTION2 *)FileBuffer;
    756 
    757     memset(CompressionSect2->CommonHeader.Size, 0xff, sizeof(UINT8) * 3);
    758     CompressionSect2->CommonHeader.Type         = EFI_SECTION_COMPRESSION;
    759     CompressionSect2->CommonHeader.ExtendedSize = TotalLength;
    760     CompressionSect2->CompressionType           = SectCompSubType;
    761     CompressionSect2->UncompressedLength        = InputLength;
    762   } else {
    763     CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;
    764 
    765     CompressionSect->CommonHeader.Type     = EFI_SECTION_COMPRESSION;
    766     CompressionSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);
    767     CompressionSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
    768     CompressionSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
    769     CompressionSect->CompressionType       = SectCompSubType;
    770     CompressionSect->UncompressedLength    = InputLength;
    771   }
    772 
    773   //
    774   // Set OutFileBuffer
    775   //
    776   *OutFileBuffer = FileBuffer;
    777 
    778   return EFI_SUCCESS;
    779 }
    780 
    781 EFI_STATUS
    782 GenSectionGuidDefinedSection (
    783   CHAR8    **InputFileName,
    784   UINT32   *InputFileAlign,
    785   UINT32   InputFileNum,
    786   EFI_GUID *VendorGuid,
    787   UINT16   DataAttribute,
    788   UINT32   DataHeaderSize,
    789   UINT8    **OutFileBuffer
    790   )
    791 /*++
    792 
    793 Routine Description:
    794 
    795   Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
    796   Input file must be already sectioned. The function won't validate
    797   the input files' contents. Caller should hand in files already
    798   with section header.
    799 
    800 Arguments:
    801 
    802   InputFileName - Name of the input file.
    803 
    804   InputFileAlign - Alignment required by the input file data.
    805 
    806   InputFileNum  - Number of input files. Should be at least 1.
    807 
    808   VendorGuid    - Specify vendor guid value.
    809 
    810   DataAttribute - Specify attribute for the vendor guid data.
    811 
    812   DataHeaderSize- Guided Data Header Size
    813 
    814   OutFileBuffer   - Buffer pointer to Output file contents
    815 
    816 Returns:
    817 
    818   EFI_SUCCESS on successful return
    819   EFI_INVALID_PARAMETER if InputFileNum is less than 1
    820   EFI_ABORTED if unable to open input file.
    821   EFI_OUT_OF_RESOURCES  No resource to complete the operation.
    822 
    823 --*/
    824 {
    825   UINT32                TotalLength;
    826   UINT32                InputLength;
    827   UINT32                Offset;
    828   UINT8                 *FileBuffer;
    829   UINT32                Crc32Checksum;
    830   EFI_STATUS            Status;
    831   CRC32_SECTION_HEADER  *Crc32GuidSect;
    832   CRC32_SECTION_HEADER2  *Crc32GuidSect2;
    833   EFI_GUID_DEFINED_SECTION  *VendorGuidSect;
    834   EFI_GUID_DEFINED_SECTION2  *VendorGuidSect2;
    835 
    836   InputLength = 0;
    837   Offset      = 0;
    838   FileBuffer  = NULL;
    839   TotalLength = 0;
    840 
    841   //
    842   // read all input file contents into a buffer
    843   // first get the size of all file contents
    844   //
    845   Status = GetSectionContents (
    846             InputFileName,
    847             InputFileAlign,
    848             InputFileNum,
    849             FileBuffer,
    850             &InputLength
    851             );
    852 
    853   if (Status == EFI_BUFFER_TOO_SMALL) {
    854     if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
    855       Offset = sizeof (CRC32_SECTION_HEADER);
    856       if (InputLength + Offset >= MAX_SECTION_SIZE) {
    857         Offset = sizeof (CRC32_SECTION_HEADER2);
    858       }
    859     } else {
    860       Offset = sizeof (EFI_GUID_DEFINED_SECTION);
    861       if (InputLength + Offset >= MAX_SECTION_SIZE) {
    862         Offset = sizeof (EFI_GUID_DEFINED_SECTION2);
    863       }
    864     }
    865     TotalLength = InputLength + Offset;
    866 
    867     FileBuffer = (UINT8 *) malloc (InputLength + Offset);
    868     if (FileBuffer == NULL) {
    869       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
    870       return EFI_OUT_OF_RESOURCES;
    871     }
    872     //
    873     // read all input file contents into a buffer
    874     //
    875     Status = GetSectionContents (
    876               InputFileName,
    877               InputFileAlign,
    878               InputFileNum,
    879               FileBuffer + Offset,
    880               &InputLength
    881               );
    882   }
    883 
    884   if (EFI_ERROR (Status)) {
    885     if (FileBuffer != NULL) {
    886       free (FileBuffer);
    887     }
    888     Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);
    889     return Status;
    890   }
    891 
    892   if (InputLength == 0) {
    893     Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);
    894     return EFI_NOT_FOUND;
    895   }
    896 
    897   //
    898   // Now data is in FileBuffer + Offset
    899   //
    900   if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
    901     //
    902     // Default Guid section is CRC32.
    903     //
    904     Crc32Checksum = 0;
    905     CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);
    906 
    907     if (TotalLength >= MAX_SECTION_SIZE) {
    908       Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer;
    909       Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
    910       Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) 0xff;
    911       Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) 0xff;
    912       Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) 0xff;
    913       Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength;
    914       memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
    915       Crc32GuidSect2->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
    916       Crc32GuidSect2->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER2);
    917       Crc32GuidSect2->CRC32Checksum                 = Crc32Checksum;
    918       DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset);
    919     } else {
    920       Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;
    921       Crc32GuidSect->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
    922       Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);
    923       Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
    924       Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
    925       memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
    926       Crc32GuidSect->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
    927       Crc32GuidSect->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER);
    928       Crc32GuidSect->CRC32Checksum                 = Crc32Checksum;
    929       DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);
    930     }
    931   } else {
    932     if (TotalLength >= MAX_SECTION_SIZE) {
    933       VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer;
    934       VendorGuidSect2->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
    935       VendorGuidSect2->CommonHeader.Size[0]  = (UINT8) 0xff;
    936       VendorGuidSect2->CommonHeader.Size[1]  = (UINT8) 0xff;
    937       VendorGuidSect2->CommonHeader.Size[2]  = (UINT8) 0xff;
    938       VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2);
    939       memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
    940       VendorGuidSect2->Attributes  = DataAttribute;
    941       VendorGuidSect2->DataOffset  = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize);
    942       DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset);
    943     } else {
    944       VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;
    945       VendorGuidSect->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
    946       VendorGuidSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);
    947       VendorGuidSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
    948       VendorGuidSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
    949       memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
    950       VendorGuidSect->Attributes  = DataAttribute;
    951       VendorGuidSect->DataOffset  = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);
    952       DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);
    953     }
    954   }
    955   VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
    956 
    957   //
    958   // Set OutFileBuffer
    959   //
    960   *OutFileBuffer = FileBuffer;
    961 
    962   return EFI_SUCCESS;
    963 }
    964 
    965 int
    966 main (
    967   int  argc,
    968   char *argv[]
    969   )
    970 /*++
    971 
    972 Routine Description:
    973 
    974   Main
    975 
    976 Arguments:
    977 
    978   command line parameters
    979 
    980 Returns:
    981 
    982   EFI_SUCCESS    Section header successfully generated and section concatenated.
    983   EFI_ABORTED    Could not generate the section
    984   EFI_OUT_OF_RESOURCES  No resource to complete the operation.
    985 
    986 --*/
    987 {
    988   UINT32                    Index;
    989   UINT32                    InputFileNum;
    990   FILE                      *OutFile;
    991   CHAR8                     **InputFileName;
    992   CHAR8                     *OutputFileName;
    993   CHAR8                     *SectionName;
    994   CHAR8                     *CompressionName;
    995   CHAR8                     *StringBuffer;
    996   EFI_GUID                  VendorGuid = mZeroGuid;
    997   int                       VersionNumber;
    998   UINT8                     SectType;
    999   UINT8                     SectCompSubType;
   1000   UINT16                    SectGuidAttribute;
   1001   UINT64                    SectGuidHeaderLength;
   1002   EFI_VERSION_SECTION       *VersionSect;
   1003   EFI_USER_INTERFACE_SECTION *UiSect;
   1004   UINT32                    InputLength;
   1005   UINT8                     *OutFileBuffer;
   1006   EFI_STATUS                Status;
   1007   UINT64                    LogLevel;
   1008   UINT32                    *InputFileAlign;
   1009   UINT32                    InputFileAlignNum;
   1010   EFI_COMMON_SECTION_HEADER *SectionHeader;
   1011 
   1012   InputFileAlign        = NULL;
   1013   InputFileAlignNum     = 0;
   1014   InputFileName         = NULL;
   1015   OutputFileName        = NULL;
   1016   SectionName           = NULL;
   1017   CompressionName       = NULL;
   1018   StringBuffer          = "";
   1019   OutFile               = NULL;
   1020   VersionNumber         = 0;
   1021   InputFileNum          = 0;
   1022   SectType              = EFI_SECTION_ALL;
   1023   SectCompSubType       = 0;
   1024   SectGuidAttribute     = EFI_GUIDED_SECTION_NONE;
   1025   OutFileBuffer         = NULL;
   1026   InputLength           = 0;
   1027   Status                = STATUS_SUCCESS;
   1028   LogLevel              = 0;
   1029   SectGuidHeaderLength  = 0;
   1030   VersionSect           = NULL;
   1031   UiSect                = NULL;
   1032 
   1033   SetUtilityName (UTILITY_NAME);
   1034 
   1035   if (argc == 1) {
   1036     Error (NULL, 0, 1001, "Missing options", "No options input");
   1037     Usage ();
   1038     return STATUS_ERROR;
   1039   }
   1040 
   1041   //
   1042   // Parse command line
   1043   //
   1044   argc --;
   1045   argv ++;
   1046 
   1047   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
   1048     Version ();
   1049     Usage ();
   1050     return STATUS_SUCCESS;
   1051   }
   1052 
   1053   if (stricmp (argv[0], "--version") == 0) {
   1054     Version ();
   1055     return STATUS_SUCCESS;
   1056   }
   1057 
   1058   while (argc > 0) {
   1059     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {
   1060       SectionName = argv[1];
   1061       if (SectionName == NULL) {
   1062         Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");
   1063         goto Finish;
   1064       }
   1065       argc -= 2;
   1066       argv += 2;
   1067       continue;
   1068     }
   1069 
   1070     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
   1071       OutputFileName = argv[1];
   1072       if (OutputFileName == NULL) {
   1073         Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");
   1074         goto Finish;
   1075       }
   1076       argc -= 2;
   1077       argv += 2;
   1078       continue;
   1079     }
   1080 
   1081     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {
   1082       CompressionName = argv[1];
   1083       if (CompressionName == NULL) {
   1084         Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
   1085         goto Finish;
   1086       }
   1087       argc -= 2;
   1088       argv += 2;
   1089       continue;
   1090     }
   1091 
   1092     if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {
   1093       Status = StringToGuid (argv[1], &VendorGuid);
   1094       if (EFI_ERROR (Status)) {
   1095         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
   1096         goto Finish;
   1097       }
   1098       argc -= 2;
   1099       argv += 2;
   1100       continue;
   1101     }
   1102 
   1103     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {
   1104       if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {
   1105         SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
   1106       } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {
   1107         SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
   1108       } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {
   1109         //
   1110         // NONE attribute
   1111         //
   1112         SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;
   1113       } else {
   1114         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
   1115         goto Finish;
   1116       }
   1117       argc -= 2;
   1118       argv += 2;
   1119       continue;
   1120     }
   1121 
   1122     if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {
   1123       Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);
   1124       if (EFI_ERROR (Status)) {
   1125         Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);
   1126         goto Finish;
   1127       }
   1128       argc -= 2;
   1129       argv += 2;
   1130       continue;
   1131     }
   1132 
   1133     if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {
   1134       StringBuffer = argv[1];
   1135       if (StringBuffer == NULL) {
   1136         Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");
   1137         goto Finish;
   1138       }
   1139       argc -= 2;
   1140       argv += 2;
   1141       continue;
   1142     }
   1143 
   1144     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {
   1145       if (argv[1] == NULL) {
   1146         Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");
   1147         goto Finish;
   1148       }
   1149       //
   1150       // Verify string is a integrator number
   1151       //
   1152       for (Index = 0; Index < strlen (argv[1]); Index++) {
   1153         if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {
   1154           Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
   1155           goto Finish;
   1156         }
   1157       }
   1158 
   1159       sscanf (argv[1], "%d", &VersionNumber);
   1160       argc -= 2;
   1161       argv += 2;
   1162       continue;
   1163     }
   1164 
   1165     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
   1166       SetPrintLevel (VERBOSE_LOG_LEVEL);
   1167       VerboseMsg ("Verbose output Mode Set!");
   1168       argc --;
   1169       argv ++;
   1170       continue;
   1171     }
   1172 
   1173     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
   1174       SetPrintLevel (KEY_LOG_LEVEL);
   1175       KeyMsg ("Quiet output Mode Set!");
   1176       argc --;
   1177       argv ++;
   1178       continue;
   1179     }
   1180 
   1181     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
   1182       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
   1183       if (EFI_ERROR (Status)) {
   1184         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
   1185         goto Finish;
   1186       }
   1187       if (LogLevel > 9) {
   1188         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel);
   1189         goto Finish;
   1190       }
   1191       SetPrintLevel (LogLevel);
   1192       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
   1193       argc -= 2;
   1194       argv += 2;
   1195       continue;
   1196     }
   1197 
   1198     //
   1199     // Section File alignment requirement
   1200     //
   1201     if (stricmp (argv[0], "--sectionalign") == 0) {
   1202       if (InputFileAlignNum == 0) {
   1203         InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
   1204         if (InputFileAlign == NULL) {
   1205           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
   1206           return 1;
   1207         }
   1208         memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
   1209       } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {
   1210         InputFileAlign = (UINT32 *) realloc (
   1211           InputFileAlign,
   1212           (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)
   1213           );
   1214 
   1215         if (InputFileAlign == NULL) {
   1216           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
   1217           return 1;
   1218         }
   1219         memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));
   1220       }
   1221 
   1222       Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));
   1223       if (EFI_ERROR (Status)) {
   1224         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
   1225         goto Finish;
   1226       }
   1227       argc -= 2;
   1228       argv += 2;
   1229       InputFileAlignNum ++;
   1230       continue;
   1231     }
   1232 
   1233     //
   1234     // Get Input file name
   1235     //
   1236     if ((InputFileNum == 0) && (InputFileName == NULL)) {
   1237       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
   1238       if (InputFileName == NULL) {
   1239         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
   1240         return 1;
   1241       }
   1242       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
   1243     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
   1244       //
   1245       // InputFileName buffer too small, need to realloc
   1246       //
   1247       InputFileName = (CHAR8 **) realloc (
   1248                                   InputFileName,
   1249                                   (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
   1250                                   );
   1251 
   1252       if (InputFileName == NULL) {
   1253         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
   1254         return 1;
   1255       }
   1256       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
   1257     }
   1258 
   1259     InputFileName[InputFileNum++] = argv[0];
   1260     argc --;
   1261     argv ++;
   1262   }
   1263 
   1264   if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {
   1265     Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");
   1266     goto Finish;
   1267   }
   1268 
   1269   VerboseMsg ("%s tool start.", UTILITY_NAME);
   1270 
   1271   //
   1272   // Parse all command line parameters to get the corresponding section type.
   1273   //
   1274   VerboseMsg ("Section type is %s", SectionName);
   1275   if (SectionName == NULL) {
   1276     //
   1277     // No specified Section type, default is SECTION_ALL.
   1278     //
   1279     SectType = EFI_SECTION_ALL;
   1280   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
   1281     SectType     = EFI_SECTION_COMPRESSION;
   1282     if (CompressionName == NULL) {
   1283       //
   1284       // Default is PI_STD compression algorithm.
   1285       //
   1286       SectCompSubType = EFI_STANDARD_COMPRESSION;
   1287     } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
   1288       SectCompSubType = EFI_NOT_COMPRESSED;
   1289     } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
   1290       SectCompSubType = EFI_STANDARD_COMPRESSION;
   1291     } else {
   1292       Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);
   1293       goto Finish;
   1294     }
   1295     VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);
   1296   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
   1297     SectType     = EFI_SECTION_GUID_DEFINED;
   1298 
   1299     if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {
   1300       //
   1301       // NONE attribute, clear attribute value.
   1302       //
   1303       SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;
   1304     }
   1305     VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
   1306                 (unsigned) VendorGuid.Data1,
   1307                 VendorGuid.Data2,
   1308                 VendorGuid.Data3,
   1309                 VendorGuid.Data4[0],
   1310                 VendorGuid.Data4[1],
   1311                 VendorGuid.Data4[2],
   1312                 VendorGuid.Data4[3],
   1313                 VendorGuid.Data4[4],
   1314                 VendorGuid.Data4[5],
   1315                 VendorGuid.Data4[6],
   1316                 VendorGuid.Data4[7]);
   1317     if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
   1318       VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);
   1319     }
   1320     if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {
   1321       VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);
   1322     }
   1323     if (SectGuidHeaderLength != 0) {
   1324       VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);
   1325     }
   1326   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {
   1327     SectType = EFI_SECTION_PE32;
   1328   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {
   1329     SectType = EFI_SECTION_PIC;
   1330   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {
   1331     SectType = EFI_SECTION_TE;
   1332   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
   1333     SectType = EFI_SECTION_DXE_DEPEX;
   1334   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {
   1335     SectType = EFI_SECTION_SMM_DEPEX;
   1336   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {
   1337     SectType = EFI_SECTION_VERSION;
   1338     if (VersionNumber < 0 || VersionNumber > 65535) {
   1339       Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);
   1340       goto Finish;
   1341     }
   1342     VerboseMsg ("Version section number is %d", VersionNumber);
   1343   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
   1344     SectType = EFI_SECTION_USER_INTERFACE;
   1345     if (StringBuffer[0] == '\0') {
   1346       Error (NULL, 0, 1001, "Missing option", "user interface string");
   1347       goto Finish;
   1348     }
   1349     VerboseMsg ("UI section string name is %s", StringBuffer);
   1350   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
   1351     SectType = EFI_SECTION_COMPATIBILITY16;
   1352   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
   1353     SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
   1354   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
   1355     SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
   1356   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {
   1357     SectType = EFI_SECTION_RAW;
   1358   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
   1359     SectType = EFI_SECTION_PEI_DEPEX;
   1360   } else {
   1361     Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);
   1362     goto Finish;
   1363   }
   1364 
   1365   //
   1366   // GuidValue is only required by Guided section.
   1367   //
   1368   if ((SectType != EFI_SECTION_GUID_DEFINED) && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
   1369     fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);
   1370   }
   1371 
   1372   //
   1373   // Check whether there is input file
   1374   //
   1375   if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {
   1376     //
   1377     // The input file are required for other section type.
   1378     //
   1379     if (InputFileNum == 0) {
   1380       Error (NULL, 0, 1001, "Missing options", "Input files");
   1381       goto Finish;
   1382     }
   1383   }
   1384   //
   1385   // Check whether there is output file
   1386   //
   1387   for (Index = 0; Index < InputFileNum; Index ++) {
   1388     VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);
   1389   }
   1390   if (OutputFileName == NULL) {
   1391     Error (NULL, 0, 1001, "Missing options", "Output file");
   1392     goto Finish;
   1393     // OutFile = stdout;
   1394   }
   1395   VerboseMsg ("Output file name is %s", OutputFileName);
   1396 
   1397   //
   1398   // At this point, we've fully validated the command line, and opened appropriate
   1399   // files, so let's go and do what we've been asked to do...
   1400   //
   1401   //
   1402   // Within this switch, build and write out the section header including any
   1403   // section type specific pieces.  If there's an input file, it's tacked on later
   1404   //
   1405   switch (SectType) {
   1406   case EFI_SECTION_COMPRESSION:
   1407     if (InputFileAlign != NULL) {
   1408       free (InputFileAlign);
   1409       InputFileAlign = NULL;
   1410     }
   1411     Status = GenSectionCompressionSection (
   1412               InputFileName,
   1413               InputFileAlign,
   1414               InputFileNum,
   1415               SectCompSubType,
   1416               &OutFileBuffer
   1417               );
   1418     break;
   1419 
   1420   case EFI_SECTION_GUID_DEFINED:
   1421     if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
   1422       //
   1423       // Only process alignment for the default known CRC32 guided section.
   1424       // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
   1425       //
   1426       free (InputFileAlign);
   1427       InputFileAlign = NULL;
   1428     }
   1429     Status = GenSectionGuidDefinedSection (
   1430               InputFileName,
   1431               InputFileAlign,
   1432               InputFileNum,
   1433               &VendorGuid,
   1434               SectGuidAttribute,
   1435               (UINT32) SectGuidHeaderLength,
   1436               &OutFileBuffer
   1437               );
   1438     break;
   1439 
   1440   case EFI_SECTION_VERSION:
   1441     Index           = sizeof (EFI_COMMON_SECTION_HEADER);
   1442     //
   1443     // 2 bytes for the build number UINT16
   1444     //
   1445     Index += 2;
   1446     //
   1447     // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
   1448     //
   1449     Index += (strlen (StringBuffer) * 2) + 2;
   1450     OutFileBuffer = (UINT8 *) malloc (Index);
   1451     if (OutFileBuffer == NULL) {
   1452       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
   1453       goto Finish;
   1454     }
   1455     VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;
   1456     VersionSect->CommonHeader.Type     = SectType;
   1457     VersionSect->CommonHeader.Size[0]  = (UINT8) (Index & 0xff);
   1458     VersionSect->CommonHeader.Size[1]  = (UINT8) ((Index & 0xff00) >> 8);
   1459     VersionSect->CommonHeader.Size[2]  = (UINT8) ((Index & 0xff0000) >> 16);
   1460     VersionSect->BuildNumber           = (UINT16) VersionNumber;
   1461     Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);
   1462     VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
   1463     break;
   1464 
   1465   case EFI_SECTION_USER_INTERFACE:
   1466     Index           = sizeof (EFI_COMMON_SECTION_HEADER);
   1467     //
   1468     // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
   1469     //
   1470     Index += (strlen (StringBuffer) * 2) + 2;
   1471     OutFileBuffer = (UINT8 *) malloc (Index);
   1472     if (OutFileBuffer == NULL) {
   1473       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
   1474       goto Finish;
   1475     }
   1476     UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;
   1477     UiSect->CommonHeader.Type     = SectType;
   1478     UiSect->CommonHeader.Size[0]  = (UINT8) (Index & 0xff);
   1479     UiSect->CommonHeader.Size[1]  = (UINT8) ((Index & 0xff00) >> 8);
   1480     UiSect->CommonHeader.Size[2]  = (UINT8) ((Index & 0xff0000) >> 16);
   1481     Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);
   1482     VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
   1483    break;
   1484 
   1485   case EFI_SECTION_ALL:
   1486     //
   1487     // read all input file contents into a buffer
   1488     // first get the size of all file contents
   1489     //
   1490     Status = GetSectionContents (
   1491               InputFileName,
   1492               InputFileAlign,
   1493               InputFileNum,
   1494               OutFileBuffer,
   1495               &InputLength
   1496               );
   1497 
   1498     if (Status == EFI_BUFFER_TOO_SMALL) {
   1499       OutFileBuffer = (UINT8 *) malloc (InputLength);
   1500       if (OutFileBuffer == NULL) {
   1501         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
   1502         goto Finish;
   1503       }
   1504       //
   1505       // read all input file contents into a buffer
   1506       //
   1507       Status = GetSectionContents (
   1508                 InputFileName,
   1509                 InputFileAlign,
   1510                 InputFileNum,
   1511                 OutFileBuffer,
   1512                 &InputLength
   1513                 );
   1514     }
   1515     VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);
   1516     break;
   1517   default:
   1518     //
   1519     // All other section types are caught by default (they're all the same)
   1520     //
   1521     Status = GenSectionCommonLeafSection (
   1522               InputFileName,
   1523               InputFileNum,
   1524               SectType,
   1525               &OutFileBuffer
   1526               );
   1527     break;
   1528   }
   1529 
   1530   if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {
   1531     Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);
   1532 	  goto Finish;
   1533   }
   1534 
   1535   //
   1536   // Get output file length
   1537   //
   1538   if (SectType != EFI_SECTION_ALL) {
   1539     SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer;
   1540     InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff;
   1541     if (InputLength == 0xffffff) {
   1542       InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
   1543     }
   1544   }
   1545 
   1546   //
   1547   // Write the output file
   1548   //
   1549   OutFile = fopen (LongFilePath (OutputFileName), "wb");
   1550   if (OutFile == NULL) {
   1551     Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);
   1552     goto Finish;
   1553   }
   1554 
   1555   fwrite (OutFileBuffer, InputLength, 1, OutFile);
   1556 
   1557 Finish:
   1558   if (InputFileName != NULL) {
   1559     free (InputFileName);
   1560   }
   1561 
   1562   if (InputFileAlign != NULL) {
   1563     free (InputFileAlign);
   1564   }
   1565 
   1566   if (OutFileBuffer != NULL) {
   1567     free (OutFileBuffer);
   1568   }
   1569 
   1570   if (OutFile != NULL) {
   1571     fclose (OutFile);
   1572   }
   1573 
   1574   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
   1575 
   1576   return GetUtilityStatus ();
   1577 }
   1578