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