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