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