• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 Creates output file that is a properly formed section per the PI spec.
3 
4 Copyright (c) 2004 - 2016, 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
Version(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
Usage(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
Ascii2UnicodeString(CHAR8 * String,CHAR16 * UniString)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
GenSectionCommonLeafSection(CHAR8 ** InputFileName,UINT32 InputFileNum,UINT8 SectionType,UINT8 ** OutFileBuffer)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 parameter", "more than one input file specified");
271     return STATUS_ERROR;
272   } else if (InputFileNum < 1) {
273     Error (NULL, 0, 2000, "Invalid parameter", "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 parameter", "%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
StringtoAlignment(IN CHAR8 * AlignBuffer,OUT UINT32 * AlignNumber)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
GetSectionContents(CHAR8 ** InputFileName,UINT32 * InputFileAlign,UINT32 InputFileNum,UINT8 * FileBuffer,UINT32 * BufferLength)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 parameter", "must specify at least one input file");
440     return EFI_INVALID_PARAMETER;
441   }
442 
443   if (BufferLength == NULL) {
444     Error (NULL, 0, 2000, "Invalid parameter", "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
GenSectionCompressionSection(CHAR8 ** InputFileName,UINT32 * InputFileAlign,UINT32 InputFileNum,UINT8 SectCompSubType,UINT8 ** OutFileBuffer)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   if (FileBuffer == NULL) {
671     return EFI_OUT_OF_RESOURCES;
672   }
673 
674   CompressFunction = NULL;
675 
676   //
677   // Now data is in FileBuffer, compress the data
678   //
679   switch (SectCompSubType) {
680   case EFI_NOT_COMPRESSED:
681     CompressedLength = InputLength;
682     HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
683     if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
684       HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
685     }
686     TotalLength = CompressedLength + HeaderLength;
687     //
688     // Copy file buffer to the none compressed data.
689     //
690     OutputBuffer = malloc (TotalLength);
691     if (OutputBuffer == NULL) {
692       free (FileBuffer);
693       return EFI_OUT_OF_RESOURCES;
694     }
695     memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength);
696     free (FileBuffer);
697     FileBuffer = OutputBuffer;
698     break;
699 
700   case EFI_STANDARD_COMPRESSION:
701     CompressFunction = (COMPRESS_FUNCTION) EfiCompress;
702     break;
703 
704   default:
705     Error (NULL, 0, 2000, "Invalid parameter", "unknown compression type");
706     free (FileBuffer);
707     return EFI_ABORTED;
708   }
709 
710   if (CompressFunction != NULL) {
711 
712     Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
713     if (Status == EFI_BUFFER_TOO_SMALL) {
714       HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
715       if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
716         HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
717       }
718       TotalLength = CompressedLength + HeaderLength;
719       OutputBuffer = malloc (TotalLength);
720       if (!OutputBuffer) {
721         free (FileBuffer);
722         return EFI_OUT_OF_RESOURCES;
723       }
724 
725       Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength);
726     }
727 
728     free (FileBuffer);
729     FileBuffer = OutputBuffer;
730 
731     if (EFI_ERROR (Status)) {
732       if (FileBuffer != NULL) {
733         free (FileBuffer);
734       }
735 
736       return Status;
737     }
738 
739     if (FileBuffer == NULL) {
740       return EFI_OUT_OF_RESOURCES;
741     }
742   }
743 
744   DebugMsg (NULL, 0, 9, "comprss file size",
745             "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);
746 
747   //if (TotalLength >= MAX_SECTION_SIZE) {
748   //  Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);
749   //  if (FileBuffer != NULL) {
750   //    free (FileBuffer);
751   //  }
752   //  if (OutputBuffer != NULL) {
753   //    free (OutputBuffer);
754   //  }
755   //  return STATUS_ERROR;
756   //}
757   VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
758 
759   //
760   // Add the section header for the compressed data
761   //
762   if (TotalLength >= MAX_SECTION_SIZE) {
763     CompressionSect2 = (EFI_COMPRESSION_SECTION2 *)FileBuffer;
764 
765     memset(CompressionSect2->CommonHeader.Size, 0xff, sizeof(UINT8) * 3);
766     CompressionSect2->CommonHeader.Type         = EFI_SECTION_COMPRESSION;
767     CompressionSect2->CommonHeader.ExtendedSize = TotalLength;
768     CompressionSect2->CompressionType           = SectCompSubType;
769     CompressionSect2->UncompressedLength        = InputLength;
770   } else {
771     CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;
772 
773     CompressionSect->CommonHeader.Type     = EFI_SECTION_COMPRESSION;
774     CompressionSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);
775     CompressionSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
776     CompressionSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
777     CompressionSect->CompressionType       = SectCompSubType;
778     CompressionSect->UncompressedLength    = InputLength;
779   }
780 
781   //
782   // Set OutFileBuffer
783   //
784   *OutFileBuffer = FileBuffer;
785 
786   return EFI_SUCCESS;
787 }
788 
789 EFI_STATUS
GenSectionGuidDefinedSection(CHAR8 ** InputFileName,UINT32 * InputFileAlign,UINT32 InputFileNum,EFI_GUID * VendorGuid,UINT16 DataAttribute,UINT32 DataHeaderSize,UINT8 ** OutFileBuffer)790 GenSectionGuidDefinedSection (
791   CHAR8    **InputFileName,
792   UINT32   *InputFileAlign,
793   UINT32   InputFileNum,
794   EFI_GUID *VendorGuid,
795   UINT16   DataAttribute,
796   UINT32   DataHeaderSize,
797   UINT8    **OutFileBuffer
798   )
799 /*++
800 
801 Routine Description:
802 
803   Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
804   Input file must be already sectioned. The function won't validate
805   the input files' contents. Caller should hand in files already
806   with section header.
807 
808 Arguments:
809 
810   InputFileName - Name of the input file.
811 
812   InputFileAlign - Alignment required by the input file data.
813 
814   InputFileNum  - Number of input files. Should be at least 1.
815 
816   VendorGuid    - Specify vendor guid value.
817 
818   DataAttribute - Specify attribute for the vendor guid data.
819 
820   DataHeaderSize- Guided Data Header Size
821 
822   OutFileBuffer   - Buffer pointer to Output file contents
823 
824 Returns:
825 
826   EFI_SUCCESS on successful return
827   EFI_INVALID_PARAMETER if InputFileNum is less than 1
828   EFI_ABORTED if unable to open input file.
829   EFI_OUT_OF_RESOURCES  No resource to complete the operation.
830 
831 --*/
832 {
833   UINT32                TotalLength;
834   UINT32                InputLength;
835   UINT32                Offset;
836   UINT8                 *FileBuffer;
837   UINT32                Crc32Checksum;
838   EFI_STATUS            Status;
839   CRC32_SECTION_HEADER  *Crc32GuidSect;
840   CRC32_SECTION_HEADER2  *Crc32GuidSect2;
841   EFI_GUID_DEFINED_SECTION  *VendorGuidSect;
842   EFI_GUID_DEFINED_SECTION2  *VendorGuidSect2;
843 
844   InputLength = 0;
845   Offset      = 0;
846   FileBuffer  = NULL;
847   TotalLength = 0;
848 
849   //
850   // read all input file contents into a buffer
851   // first get the size of all file contents
852   //
853   Status = GetSectionContents (
854             InputFileName,
855             InputFileAlign,
856             InputFileNum,
857             FileBuffer,
858             &InputLength
859             );
860 
861   if (Status == EFI_BUFFER_TOO_SMALL) {
862     if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
863       Offset = sizeof (CRC32_SECTION_HEADER);
864       if (InputLength + Offset >= MAX_SECTION_SIZE) {
865         Offset = sizeof (CRC32_SECTION_HEADER2);
866       }
867     } else {
868       Offset = sizeof (EFI_GUID_DEFINED_SECTION);
869       if (InputLength + Offset >= MAX_SECTION_SIZE) {
870         Offset = sizeof (EFI_GUID_DEFINED_SECTION2);
871       }
872     }
873     TotalLength = InputLength + Offset;
874 
875     FileBuffer = (UINT8 *) malloc (InputLength + Offset);
876     if (FileBuffer == NULL) {
877       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
878       return EFI_OUT_OF_RESOURCES;
879     }
880     //
881     // read all input file contents into a buffer
882     //
883     Status = GetSectionContents (
884               InputFileName,
885               InputFileAlign,
886               InputFileNum,
887               FileBuffer + Offset,
888               &InputLength
889               );
890   }
891 
892   if (EFI_ERROR (Status)) {
893     if (FileBuffer != NULL) {
894       free (FileBuffer);
895     }
896     Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);
897     return Status;
898   }
899 
900   if (InputLength == 0) {
901     if (FileBuffer != NULL) {
902       free (FileBuffer);
903     }
904     Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);
905     return EFI_NOT_FOUND;
906   }
907 
908   //
909   // InputLength != 0, but FileBuffer == NULL means out of resources.
910   //
911   if (FileBuffer == NULL) {
912     Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
913     return EFI_OUT_OF_RESOURCES;
914   }
915 
916   //
917   // Now data is in FileBuffer + Offset
918   //
919   if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
920     //
921     // Default Guid section is CRC32.
922     //
923     Crc32Checksum = 0;
924     CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);
925 
926     if (TotalLength >= MAX_SECTION_SIZE) {
927       Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer;
928       Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
929       Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) 0xff;
930       Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) 0xff;
931       Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) 0xff;
932       Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength;
933       memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
934       Crc32GuidSect2->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
935       Crc32GuidSect2->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER2);
936       Crc32GuidSect2->CRC32Checksum                 = Crc32Checksum;
937       DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset);
938     } else {
939       Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;
940       Crc32GuidSect->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
941       Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);
942       Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
943       Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
944       memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
945       Crc32GuidSect->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
946       Crc32GuidSect->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER);
947       Crc32GuidSect->CRC32Checksum                 = Crc32Checksum;
948       DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);
949     }
950   } else {
951     if (TotalLength >= MAX_SECTION_SIZE) {
952       VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer;
953       VendorGuidSect2->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
954       VendorGuidSect2->CommonHeader.Size[0]  = (UINT8) 0xff;
955       VendorGuidSect2->CommonHeader.Size[1]  = (UINT8) 0xff;
956       VendorGuidSect2->CommonHeader.Size[2]  = (UINT8) 0xff;
957       VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2);
958       memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
959       VendorGuidSect2->Attributes  = DataAttribute;
960       VendorGuidSect2->DataOffset  = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize);
961       DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset);
962     } else {
963       VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;
964       VendorGuidSect->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;
965       VendorGuidSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);
966       VendorGuidSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
967       VendorGuidSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
968       memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
969       VendorGuidSect->Attributes  = DataAttribute;
970       VendorGuidSect->DataOffset  = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);
971       DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);
972     }
973   }
974   VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
975 
976   //
977   // Set OutFileBuffer
978   //
979   *OutFileBuffer = FileBuffer;
980 
981   return EFI_SUCCESS;
982 }
983 
984 int
main(int argc,char * argv[])985 main (
986   int  argc,
987   char *argv[]
988   )
989 /*++
990 
991 Routine Description:
992 
993   Main
994 
995 Arguments:
996 
997   command line parameters
998 
999 Returns:
1000 
1001   EFI_SUCCESS    Section header successfully generated and section concatenated.
1002   EFI_ABORTED    Could not generate the section
1003   EFI_OUT_OF_RESOURCES  No resource to complete the operation.
1004 
1005 --*/
1006 {
1007   UINT32                    Index;
1008   UINT32                    InputFileNum;
1009   FILE                      *OutFile;
1010   CHAR8                     **InputFileName;
1011   CHAR8                     *OutputFileName;
1012   CHAR8                     *SectionName;
1013   CHAR8                     *CompressionName;
1014   CHAR8                     *StringBuffer;
1015   EFI_GUID                  VendorGuid = mZeroGuid;
1016   int                       VersionNumber;
1017   UINT8                     SectType;
1018   UINT8                     SectCompSubType;
1019   UINT16                    SectGuidAttribute;
1020   UINT64                    SectGuidHeaderLength;
1021   EFI_VERSION_SECTION       *VersionSect;
1022   EFI_USER_INTERFACE_SECTION *UiSect;
1023   UINT32                    InputLength;
1024   UINT8                     *OutFileBuffer;
1025   EFI_STATUS                Status;
1026   UINT64                    LogLevel;
1027   UINT32                    *InputFileAlign;
1028   UINT32                    InputFileAlignNum;
1029   EFI_COMMON_SECTION_HEADER *SectionHeader;
1030 
1031   InputFileAlign        = NULL;
1032   InputFileAlignNum     = 0;
1033   InputFileName         = NULL;
1034   OutputFileName        = NULL;
1035   SectionName           = NULL;
1036   CompressionName       = NULL;
1037   StringBuffer          = "";
1038   OutFile               = NULL;
1039   VersionNumber         = 0;
1040   InputFileNum          = 0;
1041   SectType              = EFI_SECTION_ALL;
1042   SectCompSubType       = 0;
1043   SectGuidAttribute     = EFI_GUIDED_SECTION_NONE;
1044   OutFileBuffer         = NULL;
1045   InputLength           = 0;
1046   Status                = STATUS_SUCCESS;
1047   LogLevel              = 0;
1048   SectGuidHeaderLength  = 0;
1049   VersionSect           = NULL;
1050   UiSect                = NULL;
1051 
1052   SetUtilityName (UTILITY_NAME);
1053 
1054   if (argc == 1) {
1055     Error (NULL, 0, 1001, "Missing options", "No options input");
1056     Usage ();
1057     return STATUS_ERROR;
1058   }
1059 
1060   //
1061   // Parse command line
1062   //
1063   argc --;
1064   argv ++;
1065 
1066   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
1067     Version ();
1068     Usage ();
1069     return STATUS_SUCCESS;
1070   }
1071 
1072   if (stricmp (argv[0], "--version") == 0) {
1073     Version ();
1074     return STATUS_SUCCESS;
1075   }
1076 
1077   while (argc > 0) {
1078     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {
1079       SectionName = argv[1];
1080       if (SectionName == NULL) {
1081         Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");
1082         goto Finish;
1083       }
1084       argc -= 2;
1085       argv += 2;
1086       continue;
1087     }
1088 
1089     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
1090       OutputFileName = argv[1];
1091       if (OutputFileName == NULL) {
1092         Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");
1093         goto Finish;
1094       }
1095       argc -= 2;
1096       argv += 2;
1097       continue;
1098     }
1099 
1100     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {
1101       CompressionName = argv[1];
1102       if (CompressionName == NULL) {
1103         Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
1104         goto Finish;
1105       }
1106       argc -= 2;
1107       argv += 2;
1108       continue;
1109     }
1110 
1111     if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {
1112       Status = StringToGuid (argv[1], &VendorGuid);
1113       if (EFI_ERROR (Status)) {
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], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {
1123       if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {
1124         SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
1125       } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {
1126         SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
1127       } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {
1128         //
1129         // NONE attribute
1130         //
1131         SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;
1132       } else {
1133         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1134         goto Finish;
1135       }
1136       argc -= 2;
1137       argv += 2;
1138       continue;
1139     }
1140 
1141     if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {
1142       Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);
1143       if (EFI_ERROR (Status)) {
1144         Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);
1145         goto Finish;
1146       }
1147       argc -= 2;
1148       argv += 2;
1149       continue;
1150     }
1151 
1152     if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {
1153       StringBuffer = argv[1];
1154       if (StringBuffer == NULL) {
1155         Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");
1156         goto Finish;
1157       }
1158       argc -= 2;
1159       argv += 2;
1160       continue;
1161     }
1162 
1163     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {
1164       if (argv[1] == NULL) {
1165         Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");
1166         goto Finish;
1167       }
1168       //
1169       // Verify string is a integrator number
1170       //
1171       for (Index = 0; Index < strlen (argv[1]); Index++) {
1172         if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {
1173           Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1174           goto Finish;
1175         }
1176       }
1177 
1178       sscanf (argv[1], "%d", &VersionNumber);
1179       argc -= 2;
1180       argv += 2;
1181       continue;
1182     }
1183 
1184     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
1185       SetPrintLevel (VERBOSE_LOG_LEVEL);
1186       VerboseMsg ("Verbose output Mode Set!");
1187       argc --;
1188       argv ++;
1189       continue;
1190     }
1191 
1192     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
1193       SetPrintLevel (KEY_LOG_LEVEL);
1194       KeyMsg ("Quiet output Mode Set!");
1195       argc --;
1196       argv ++;
1197       continue;
1198     }
1199 
1200     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
1201       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
1202       if (EFI_ERROR (Status)) {
1203         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1204         goto Finish;
1205       }
1206       if (LogLevel > 9) {
1207         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel);
1208         goto Finish;
1209       }
1210       SetPrintLevel (LogLevel);
1211       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
1212       argc -= 2;
1213       argv += 2;
1214       continue;
1215     }
1216 
1217     //
1218     // Section File alignment requirement
1219     //
1220     if (stricmp (argv[0], "--sectionalign") == 0) {
1221       if (InputFileAlignNum == 0) {
1222         InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
1223         if (InputFileAlign == NULL) {
1224           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1225           goto Finish;
1226         }
1227         memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
1228       } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {
1229         InputFileAlign = (UINT32 *) realloc (
1230           InputFileAlign,
1231           (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)
1232           );
1233 
1234         if (InputFileAlign == NULL) {
1235           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1236           goto Finish;
1237         }
1238         memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));
1239       }
1240 
1241       Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));
1242       if (EFI_ERROR (Status)) {
1243         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1244         goto Finish;
1245       }
1246       argc -= 2;
1247       argv += 2;
1248       InputFileAlignNum ++;
1249       continue;
1250     }
1251 
1252     //
1253     // Get Input file name
1254     //
1255     if ((InputFileNum == 0) && (InputFileName == NULL)) {
1256       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
1257       if (InputFileName == NULL) {
1258         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1259         goto Finish;
1260       }
1261       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1262     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
1263       //
1264       // InputFileName buffer too small, need to realloc
1265       //
1266       InputFileName = (CHAR8 **) realloc (
1267                                   InputFileName,
1268                                   (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
1269                                   );
1270 
1271       if (InputFileName == NULL) {
1272         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1273         goto Finish;
1274       }
1275       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1276     }
1277 
1278     InputFileName[InputFileNum++] = argv[0];
1279     argc --;
1280     argv ++;
1281   }
1282 
1283   if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {
1284     Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");
1285     goto Finish;
1286   }
1287 
1288   VerboseMsg ("%s tool start.", UTILITY_NAME);
1289 
1290   //
1291   // Parse all command line parameters to get the corresponding section type.
1292   //
1293   VerboseMsg ("Section type is %s", SectionName);
1294   if (SectionName == NULL) {
1295     //
1296     // No specified Section type, default is SECTION_ALL.
1297     //
1298     SectType = EFI_SECTION_ALL;
1299   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
1300     SectType     = EFI_SECTION_COMPRESSION;
1301     if (CompressionName == NULL) {
1302       //
1303       // Default is PI_STD compression algorithm.
1304       //
1305       SectCompSubType = EFI_STANDARD_COMPRESSION;
1306     } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
1307       SectCompSubType = EFI_NOT_COMPRESSED;
1308     } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
1309       SectCompSubType = EFI_STANDARD_COMPRESSION;
1310     } else {
1311       Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);
1312       goto Finish;
1313     }
1314     VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);
1315   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
1316     SectType     = EFI_SECTION_GUID_DEFINED;
1317 
1318     if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {
1319       //
1320       // NONE attribute, clear attribute value.
1321       //
1322       SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;
1323     }
1324     VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1325                 (unsigned) VendorGuid.Data1,
1326                 VendorGuid.Data2,
1327                 VendorGuid.Data3,
1328                 VendorGuid.Data4[0],
1329                 VendorGuid.Data4[1],
1330                 VendorGuid.Data4[2],
1331                 VendorGuid.Data4[3],
1332                 VendorGuid.Data4[4],
1333                 VendorGuid.Data4[5],
1334                 VendorGuid.Data4[6],
1335                 VendorGuid.Data4[7]);
1336     if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
1337       VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);
1338     }
1339     if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {
1340       VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);
1341     }
1342     if (SectGuidHeaderLength != 0) {
1343       VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);
1344     }
1345   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {
1346     SectType = EFI_SECTION_PE32;
1347   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {
1348     SectType = EFI_SECTION_PIC;
1349   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {
1350     SectType = EFI_SECTION_TE;
1351   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
1352     SectType = EFI_SECTION_DXE_DEPEX;
1353   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {
1354     SectType = EFI_SECTION_SMM_DEPEX;
1355   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {
1356     SectType = EFI_SECTION_VERSION;
1357     if (VersionNumber < 0 || VersionNumber > 65535) {
1358       Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);
1359       goto Finish;
1360     }
1361     VerboseMsg ("Version section number is %d", VersionNumber);
1362   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
1363     SectType = EFI_SECTION_USER_INTERFACE;
1364     if (StringBuffer[0] == '\0') {
1365       Error (NULL, 0, 1001, "Missing option", "user interface string");
1366       goto Finish;
1367     }
1368     VerboseMsg ("UI section string name is %s", StringBuffer);
1369   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
1370     SectType = EFI_SECTION_COMPATIBILITY16;
1371   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
1372     SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
1373   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
1374     SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
1375   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {
1376     SectType = EFI_SECTION_RAW;
1377   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
1378     SectType = EFI_SECTION_PEI_DEPEX;
1379   } else {
1380     Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);
1381     goto Finish;
1382   }
1383 
1384   //
1385   // GuidValue is only required by Guided section.
1386   //
1387   if ((SectType != EFI_SECTION_GUID_DEFINED) &&
1388     (SectionName != NULL) &&
1389     (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
1390     fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);
1391   }
1392 
1393   //
1394   // Check whether there is input file
1395   //
1396   if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {
1397     //
1398     // The input file are required for other section type.
1399     //
1400     if (InputFileNum == 0) {
1401       Error (NULL, 0, 1001, "Missing options", "Input files");
1402       goto Finish;
1403     }
1404   }
1405   //
1406   // Check whether there is output file
1407   //
1408   for (Index = 0; Index < InputFileNum; Index ++) {
1409     VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);
1410   }
1411   if (OutputFileName == NULL) {
1412     Error (NULL, 0, 1001, "Missing options", "Output file");
1413     goto Finish;
1414     // OutFile = stdout;
1415   }
1416   VerboseMsg ("Output file name is %s", OutputFileName);
1417 
1418   //
1419   // At this point, we've fully validated the command line, and opened appropriate
1420   // files, so let's go and do what we've been asked to do...
1421   //
1422   //
1423   // Within this switch, build and write out the section header including any
1424   // section type specific pieces.  If there's an input file, it's tacked on later
1425   //
1426   switch (SectType) {
1427   case EFI_SECTION_COMPRESSION:
1428     if (InputFileAlign != NULL) {
1429       free (InputFileAlign);
1430       InputFileAlign = NULL;
1431     }
1432     Status = GenSectionCompressionSection (
1433               InputFileName,
1434               InputFileAlign,
1435               InputFileNum,
1436               SectCompSubType,
1437               &OutFileBuffer
1438               );
1439     break;
1440 
1441   case EFI_SECTION_GUID_DEFINED:
1442     if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
1443       //
1444       // Only process alignment for the default known CRC32 guided section.
1445       // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
1446       //
1447       free (InputFileAlign);
1448       InputFileAlign = NULL;
1449     }
1450     Status = GenSectionGuidDefinedSection (
1451               InputFileName,
1452               InputFileAlign,
1453               InputFileNum,
1454               &VendorGuid,
1455               SectGuidAttribute,
1456               (UINT32) SectGuidHeaderLength,
1457               &OutFileBuffer
1458               );
1459     break;
1460 
1461   case EFI_SECTION_VERSION:
1462     Index           = sizeof (EFI_COMMON_SECTION_HEADER);
1463     //
1464     // 2 bytes for the build number UINT16
1465     //
1466     Index += 2;
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     VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;
1477     VersionSect->CommonHeader.Type     = SectType;
1478     VersionSect->CommonHeader.Size[0]  = (UINT8) (Index & 0xff);
1479     VersionSect->CommonHeader.Size[1]  = (UINT8) ((Index & 0xff00) >> 8);
1480     VersionSect->CommonHeader.Size[2]  = (UINT8) ((Index & 0xff0000) >> 16);
1481     VersionSect->BuildNumber           = (UINT16) VersionNumber;
1482     Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);
1483     VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
1484     break;
1485 
1486   case EFI_SECTION_USER_INTERFACE:
1487     Index           = sizeof (EFI_COMMON_SECTION_HEADER);
1488     //
1489     // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1490     //
1491     Index += (strlen (StringBuffer) * 2) + 2;
1492     OutFileBuffer = (UINT8 *) malloc (Index);
1493     if (OutFileBuffer == NULL) {
1494       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1495       goto Finish;
1496     }
1497     UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;
1498     UiSect->CommonHeader.Type     = SectType;
1499     UiSect->CommonHeader.Size[0]  = (UINT8) (Index & 0xff);
1500     UiSect->CommonHeader.Size[1]  = (UINT8) ((Index & 0xff00) >> 8);
1501     UiSect->CommonHeader.Size[2]  = (UINT8) ((Index & 0xff0000) >> 16);
1502     Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);
1503     VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
1504    break;
1505 
1506   case EFI_SECTION_ALL:
1507     //
1508     // read all input file contents into a buffer
1509     // first get the size of all file contents
1510     //
1511     Status = GetSectionContents (
1512               InputFileName,
1513               InputFileAlign,
1514               InputFileNum,
1515               OutFileBuffer,
1516               &InputLength
1517               );
1518 
1519     if (Status == EFI_BUFFER_TOO_SMALL) {
1520       OutFileBuffer = (UINT8 *) malloc (InputLength);
1521       if (OutFileBuffer == NULL) {
1522         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");
1523         goto Finish;
1524       }
1525       //
1526       // read all input file contents into a buffer
1527       //
1528       Status = GetSectionContents (
1529                 InputFileName,
1530                 InputFileAlign,
1531                 InputFileNum,
1532                 OutFileBuffer,
1533                 &InputLength
1534                 );
1535     }
1536     VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);
1537     break;
1538   default:
1539     //
1540     // All other section types are caught by default (they're all the same)
1541     //
1542     Status = GenSectionCommonLeafSection (
1543               InputFileName,
1544               InputFileNum,
1545               SectType,
1546               &OutFileBuffer
1547               );
1548     break;
1549   }
1550 
1551   if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {
1552     Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);
1553 	  goto Finish;
1554   }
1555 
1556   //
1557   // Get output file length
1558   //
1559   if (SectType != EFI_SECTION_ALL) {
1560     SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer;
1561     InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff;
1562     if (InputLength == 0xffffff) {
1563       InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
1564     }
1565   }
1566 
1567   //
1568   // Write the output file
1569   //
1570   OutFile = fopen (LongFilePath (OutputFileName), "wb");
1571   if (OutFile == NULL) {
1572     Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);
1573     goto Finish;
1574   }
1575 
1576   fwrite (OutFileBuffer, InputLength, 1, OutFile);
1577 
1578 Finish:
1579   if (InputFileName != NULL) {
1580     free (InputFileName);
1581   }
1582 
1583   if (InputFileAlign != NULL) {
1584     free (InputFileAlign);
1585   }
1586 
1587   if (OutFileBuffer != NULL) {
1588     free (OutFileBuffer);
1589   }
1590 
1591   if (OutFile != NULL) {
1592     fclose (OutFile);
1593   }
1594 
1595   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
1596 
1597   return GetUtilityStatus ();
1598 }
1599