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