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