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