• 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 - 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
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 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
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 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
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   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
GenSectionGuidDefinedSection(CHAR8 ** InputFileName,UINT32 * InputFileAlign,UINT32 InputFileNum,EFI_GUID * VendorGuid,UINT16 DataAttribute,UINT32 DataHeaderSize,UINT8 ** OutFileBuffer)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
main(int argc,char * argv[])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