Add check for the input file whose size is Zero.
[efi/basetools/.git] / Source / C / GenSec / GenSec.c
1 /** @file\r
2 \r
3 Copyright (c) 2004 - 2008, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14   GenSection.c\r
15 \r
16 Abstract:\r
17 \r
18   Creates output file that is a properly formed section per the PI spec.\r
19 \r
20 **/\r
21 \r
22 #include <stdio.h>\r
23 #include <stdlib.h>\r
24 #include <string.h>\r
25 \r
26 #include <Common/UefiBaseTypes.h>\r
27 #include <Common/PiFirmwareFile.h>\r
28 #include <Protocol/GuidedSectionExtraction.h>\r
29 \r
30 #include "CommonLib.h"\r
31 #include "Compress.h"\r
32 #include "Crc32.h"\r
33 #include "EfiUtilityMsgs.h"\r
34 \r
35 //\r
36 // GenSec Tool Information\r
37 //\r
38 #define UTILITY_NAME            "GenSec"\r
39 #define UTILITY_MAJOR_VERSION   0\r
40 #define UTILITY_MINOR_VERSION   1\r
41 \r
42 #define MAX_SECTION_SIZE        0x1000000\r
43 \r
44 STATIC CHAR8      *mSectionTypeName[] = {\r
45   NULL,                                 // 0x00 - reserved\r
46   "EFI_SECTION_COMPRESSION",            // 0x01\r
47   "EFI_SECTION_GUID_DEFINED",           // 0x02\r
48   NULL,                                 // 0x03 - reserved\r
49   NULL,                                 // 0x04 - reserved\r
50   NULL,                                 // 0x05 - reserved\r
51   NULL,                                 // 0x06 - reserved\r
52   NULL,                                 // 0x07 - reserved\r
53   NULL,                                 // 0x08 - reserved\r
54   NULL,                                 // 0x09 - reserved\r
55   NULL,                                 // 0x0A - reserved\r
56   NULL,                                 // 0x0B - reserved\r
57   NULL,                                 // 0x0C - reserved\r
58   NULL,                                 // 0x0D - reserved\r
59   NULL,                                 // 0x0E - reserved\r
60   NULL,                                 // 0x0F - reserved\r
61   "EFI_SECTION_PE32",                   // 0x10\r
62   "EFI_SECTION_PIC",                    // 0x11\r
63   "EFI_SECTION_TE",                     // 0x12\r
64   "EFI_SECTION_DXE_DEPEX",              // 0x13\r
65   "EFI_SECTION_VERSION",                // 0x14\r
66   "EFI_SECTION_USER_INTERFACE",         // 0x15\r
67   "EFI_SECTION_COMPATIBILITY16",        // 0x16\r
68   "EFI_SECTION_FIRMWARE_VOLUME_IMAGE",  // 0x17\r
69   "EFI_SECTION_FREEFORM_SUBTYPE_GUID",  // 0x18\r
70   "EFI_SECTION_RAW",                    // 0x19\r
71   NULL,                                 // 0x1A\r
72   "EFI_SECTION_PEI_DEPEX"               // 0x1B\r
73 };\r
74 \r
75 STATIC CHAR8      *mCompressionTypeName[]    = { "PI_NONE", "PI_STD" };\r
76 \r
77 #define EFI_GUIDED_SECTION_NONE 0x80\r
78 STATIC CHAR8      *mGUIDedSectionAttribue[]  = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};\r
79 \r
80 //\r
81 // Crc32 GUID section related definitions.\r
82 //\r
83 typedef struct {\r
84   EFI_GUID_DEFINED_SECTION  GuidSectionHeader;\r
85   UINT32                    CRC32Checksum;\r
86 } CRC32_SECTION_HEADER;\r
87 \r
88 STATIC EFI_GUID  mZeroGuid                 = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
89 STATIC EFI_GUID  mEfiCrc32SectionGuid      = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;\r
90 \r
91 STATIC\r
92 VOID \r
93 Version (\r
94   VOID\r
95   )\r
96 /*++\r
97 \r
98 Routine Description:\r
99 \r
100   Print out version information for this utility.\r
101 \r
102 Arguments:\r
103 \r
104   None\r
105   \r
106 Returns:\r
107 \r
108   None\r
109   \r
110 --*/ \r
111 {\r
112   fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
113 }\r
114 \r
115 STATIC\r
116 VOID\r
117 Usage (\r
118   VOID\r
119   )\r
120 /*++\r
121 \r
122 Routine Description:\r
123 \r
124   Print Help message.\r
125 \r
126 Arguments:\r
127 \r
128   VOID\r
129 \r
130 Returns:\r
131 \r
132   None\r
133 \r
134 --*/\r
135 {\r
136   //\r
137   // Summary usage\r
138   //\r
139   fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME);\r
140   \r
141   //\r
142   // Copyright declaration\r
143   // \r
144   fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");\r
145 \r
146   //\r
147   // Details Option\r
148   //\r
149   fprintf (stdout, "Options:\n");\r
150   fprintf (stdout, "  -o FileName, --outputfile FileName\n\\r
151                         File is the SectionFile to be created.\n");\r
152   fprintf (stdout, "  -s [SectionType], --sectiontype [SectionType]\n\\r
153                         SectionType defined in PI spec is one type of\n\\r
154                         EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\\r
155                         EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\\r
156                         EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\\r
157                         EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\\r
158                         EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\\r
159                         EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\\r
160                         EFI_SECTION_PEI_DEPEX. if -s option is not given, \n\\r
161                         EFI_SECTION_ALL is default section type.\n");\r
162   fprintf (stdout, "  -c [Type], --compress [Type]\n\\r
163                         Compress method type can be PI_NONE or PI_STD.\n\\r
164                         if -c option is not given, PI_STD is default type.\n"); \r
165   fprintf (stdout, "  -g GuidValue, --vendor GuidValue\n\\r
166                         GuidValue is one specific vendor guid value.\n\\r
167                         Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");\r
168   fprintf (stdout, "  -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\\r
169                         GuidHeaderLength is the size of header of guided data\n");\r
170   fprintf (stdout, "  -r GuidAttr, --attributes GuidAttr\n\\r
171                         GuidAttr is guid section atttributes, which may be\n\\r
172                         PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\\r
173                         if -r option is not given, default PROCESSING_REQUIRED\n");\r
174   fprintf (stdout, "  -n String, --name String\n\\r
175                         String is a NULL terminated string used in Ui section.\n");\r
176   fprintf (stdout, "  -j Number, --buildnumber Number\n\\r
177                         Number is an integer value between 0000 and 9999\n\\r
178                         used in Ver section.\n");\r
179   fprintf (stdout, "  -v, --verbose         Turn on verbose output with informational messages.\n");\r
180   fprintf (stdout, "  -q, --quiet           Disable all messages except key message and fatal error\n");\r
181   fprintf (stdout, "  -d, --debug level     Enable debug messages, at input debug level.\n");\r
182   fprintf (stdout, "  --version             Show program's version number and exit.\n");\r
183   fprintf (stdout, "  -h, --help            Show this help message and exit.\n");\r
184 }\r
185 \r
186 VOID\r
187 Ascii2UnicodeString (\r
188   CHAR8    *String,\r
189   CHAR16   *UniString\r
190   )\r
191 /*++\r
192 \r
193 Routine Description:\r
194 \r
195   Write ascii string as unicode string format to FILE \r
196 \r
197 Arguments:\r
198 \r
199   String      - Pointer to string that is written to FILE.\r
200   UniString   - Pointer to unicode string\r
201 \r
202 Returns:\r
203 \r
204   NULL\r
205 \r
206 --*/\r
207 {\r
208   while (*String != '\0') {\r
209     *(UniString++) = (CHAR16) *(String++);\r
210   }\r
211   //\r
212   // End the UniString with a NULL.\r
213   //\r
214   *UniString = '\0';\r
215\r
216 \r
217 STATUS\r
218 GenSectionCommonLeafSection (\r
219   CHAR8   **InputFileName,\r
220   UINT32  InputFileNum,\r
221   UINT8   SectionType,\r
222   UINT8   **OutFileBuffer\r
223   )\r
224 /*++\r
225         \r
226 Routine Description:\r
227            \r
228   Generate a leaf section of type other than EFI_SECTION_VERSION\r
229   and EFI_SECTION_USER_INTERFACE. Input file must be well formed.\r
230   The function won't validate the input file's contents. For\r
231   common leaf sections, the input file may be a binary file.\r
232   The utility will add section header to the file.\r
233             \r
234 Arguments:\r
235                \r
236   InputFileName  - Name of the input file.\r
237                 \r
238   InputFileNum   - Number of input files. Should be 1 for leaf section.\r
239 \r
240   SectionType    - A valid section type string\r
241 \r
242   OutFileBuffer  - Buffer pointer to Output file contents\r
243 \r
244 Returns:\r
245                        \r
246   STATUS_ERROR            - can't continue\r
247   STATUS_SUCCESS          - successful return\r
248 \r
249 --*/\r
250 {\r
251   UINT32                    InputFileLength;\r
252   FILE                      *InFile;\r
253   UINT8                     *Buffer;\r
254   UINT32                    TotalLength;\r
255   EFI_COMMON_SECTION_HEADER *CommonSect;\r
256   STATUS                    Status;\r
257 \r
258   if (InputFileNum > 1) {\r
259     Error (NULL, 0, 2000, "Invalid paramter", "more than one input file specified");\r
260     return STATUS_ERROR;\r
261   } else if (InputFileNum < 1) {\r
262     Error (NULL, 0, 2000, "Invalid paramter", "no input file specified");\r
263     return STATUS_ERROR;\r
264   }\r
265   //\r
266   // Open the input file\r
267   //\r
268   InFile = fopen (InputFileName[0], "rb");\r
269   if (InFile == NULL) {\r
270     Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);\r
271     return STATUS_ERROR;\r
272   }\r
273 \r
274   Status  = STATUS_ERROR;\r
275   Buffer  = NULL;\r
276   //\r
277   // Seek to the end of the input file so we can determine its size\r
278   //\r
279   fseek (InFile, 0, SEEK_END);\r
280   InputFileLength = ftell (InFile);\r
281   fseek (InFile, 0, SEEK_SET);\r
282   DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %d bytes", InputFileName[0], InputFileLength);\r
283   TotalLength     = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength;\r
284   //\r
285   // Size must fit in 3 bytes\r
286   //\r
287   if (TotalLength >= MAX_SECTION_SIZE) {\r
288     Error (NULL, 0, 2000, "Invalid paramter", "%s file size (0x%X) exceeds section size limit(%dM).", InputFileName[0], TotalLength, MAX_SECTION_SIZE>>20);\r
289     goto Done;\r
290   }\r
291   VerboseMsg ("the size of the created section file is %d bytes", TotalLength);\r
292   //\r
293   // Fill in the fields in the local section header structure\r
294   //\r
295   Buffer = (UINT8 *) malloc ((size_t) TotalLength);\r
296   if (Buffer == NULL) {\r
297     Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); \r
298     goto Done;\r
299   }\r
300   CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer;\r
301   CommonSect->Type     = SectionType;\r
302   CommonSect->Size[0]  = (UINT8) (TotalLength & 0xff);\r
303   CommonSect->Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
304   CommonSect->Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
305   \r
306   //\r
307   // read data from the input file.\r
308   //\r
309   if (InputFileLength != 0) {\r
310     if (fread (Buffer + sizeof (EFI_COMMON_SECTION_HEADER), (size_t) InputFileLength, 1, InFile) != 1) {\r
311       Error (NULL, 0, 0004, "Error reading file", InputFileName[0]);\r
312       goto Done;\r
313     }\r
314   }\r
315 \r
316   //\r
317   // Set OutFileBuffer \r
318   //\r
319   *OutFileBuffer = Buffer;\r
320   Status = STATUS_SUCCESS;\r
321 \r
322 Done:\r
323   fclose (InFile);\r
324 \r
325   return Status;\r
326 }\r
327 \r
328 EFI_STATUS\r
329 GetSectionContents (\r
330   CHAR8   **InputFileName,\r
331   UINT32  InputFileNum,\r
332   UINT8   *FileBuffer,\r
333   UINT32  *BufferLength\r
334   )\r
335 /*++\r
336         \r
337 Routine Description:\r
338            \r
339   Get the contents of all section files specified in InputFileName\r
340   into FileBuffer.\r
341             \r
342 Arguments:\r
343                \r
344   InputFileName  - Name of the input file.\r
345                 \r
346   InputFileNum   - Number of input files. Should be at least 1.\r
347 \r
348   FileBuffer     - Output buffer to contain data\r
349 \r
350   BufferLength   - On input, this is size of the FileBuffer. \r
351                    On output, this is the actual length of the data.\r
352 \r
353 Returns:\r
354                        \r
355   EFI_SUCCESS on successful return\r
356   EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.\r
357   EFI_ABORTED if unable to open input file.\r
358   EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.\r
359 --*/\r
360 {\r
361   UINT32   Size;\r
362   UINT32   FileSize;\r
363   UINT32   Index;\r
364   FILE    *InFile;\r
365 \r
366   if (InputFileNum < 1) {\r
367     Error (NULL, 0, 2000, "Invalid paramter", "must specify at least one input file");\r
368     return EFI_INVALID_PARAMETER;\r
369   }\r
370 \r
371   if (BufferLength == NULL) {\r
372     Error (NULL, 0, 2000, "Invalid paramter", "BufferLength can't be NULL");\r
373     return EFI_INVALID_PARAMETER;\r
374   }\r
375 \r
376   Size = 0;\r
377   //\r
378   // Go through our array of file names and copy their contents\r
379   // to the output buffer.\r
380   //\r
381   for (Index = 0; Index < InputFileNum; Index++) {\r
382     //\r
383     // make sure section ends on a DWORD boundary\r
384     //\r
385     while ((Size & 0x03) != 0) {\r
386       if (FileBuffer != NULL && Size < *BufferLength) {\r
387         FileBuffer[Size] = 0;\r
388       }\r
389       Size++;\r
390     }\r
391     \r
392     // \r
393     // Open file and read contents\r
394     //\r
395     InFile = fopen (InputFileName[Index], "rb");\r
396     if (InFile == NULL) {\r
397       Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);\r
398       return EFI_ABORTED;\r
399     }\r
400 \r
401     fseek (InFile, 0, SEEK_END);\r
402     FileSize = ftell (InFile);\r
403     fseek (InFile, 0, SEEK_SET);\r
404     DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %d bytes", InputFileName[Index], FileSize); \r
405     //\r
406     // Now read the contents of the file into the buffer\r
407     // Buffer must be enough to contain the file content.\r
408     //\r
409     if (FileSize > 0 && FileBuffer != NULL && (Size + FileSize) <= *BufferLength) {\r
410       if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {\r
411         Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);\r
412         fclose (InFile);\r
413         return EFI_ABORTED;\r
414       }\r
415     }\r
416 \r
417     fclose (InFile);\r
418     Size += FileSize;\r
419   }\r
420   \r
421   //\r
422   // Set the real required buffer size.\r
423   //\r
424   if (Size > *BufferLength) {\r
425     *BufferLength = Size;\r
426     return EFI_BUFFER_TOO_SMALL;\r
427   } else {\r
428     *BufferLength = Size;\r
429     return EFI_SUCCESS;\r
430   }\r
431 }\r
432 \r
433 EFI_STATUS\r
434 GenSectionCompressionSection (\r
435   CHAR8   **InputFileName,\r
436   UINT32  InputFileNum,\r
437   UINT8   SectCompSubType,\r
438   UINT8   **OutFileBuffer\r
439   )\r
440 /*++\r
441         \r
442 Routine Description:\r
443            \r
444   Generate an encapsulating section of type EFI_SECTION_COMPRESSION\r
445   Input file must be already sectioned. The function won't validate\r
446   the input files' contents. Caller should hand in files already \r
447   with section header.\r
448             \r
449 Arguments:\r
450                \r
451   InputFileName  - Name of the input file.\r
452                 \r
453   InputFileNum   - Number of input files. Should be at least 1.\r
454 \r
455   SectCompSubType - Specify the compression algorithm requested. \r
456   \r
457   OutFileBuffer   - Buffer pointer to Output file contents\r
458 \r
459 Returns:\r
460                        \r
461   EFI_SUCCESS           on successful return\r
462   EFI_INVALID_PARAMETER if InputFileNum is less than 1\r
463   EFI_ABORTED           if unable to open input file.\r
464   EFI_OUT_OF_RESOURCES  No resource to complete the operation.\r
465 --*/\r
466 {\r
467   UINT32                  TotalLength;\r
468   UINT32                  InputLength;\r
469   UINT32                  CompressedLength;\r
470   UINT8                   *FileBuffer;\r
471   UINT8                   *OutputBuffer;\r
472   EFI_STATUS              Status;\r
473   EFI_COMPRESSION_SECTION *CompressionSect;\r
474   COMPRESS_FUNCTION       CompressFunction;\r
475 \r
476   InputLength       = 0;\r
477   FileBuffer        = NULL;\r
478   OutputBuffer      = NULL;\r
479   CompressedLength  = 0;\r
480   //\r
481   // read all input file contents into a buffer\r
482   // first get the size of all file contents\r
483   //\r
484   Status = GetSectionContents (\r
485             InputFileName,\r
486             InputFileNum,\r
487             FileBuffer,\r
488             &InputLength\r
489             );\r
490 \r
491   if (Status == EFI_BUFFER_TOO_SMALL) {\r
492     FileBuffer = (UINT8 *) malloc (InputLength);\r
493     if (FileBuffer == NULL) {\r
494       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
495       return EFI_OUT_OF_RESOURCES;\r
496     }\r
497     //\r
498     // read all input file contents into a buffer\r
499     //\r
500     Status = GetSectionContents (\r
501               InputFileName,\r
502               InputFileNum,\r
503               FileBuffer,\r
504               &InputLength\r
505               );\r
506   }\r
507 \r
508   if (EFI_ERROR (Status)) {\r
509     if (FileBuffer != NULL) {\r
510       free (FileBuffer);\r
511     }\r
512     return Status;\r
513   }\r
514 \r
515   CompressFunction = NULL;\r
516 \r
517   //\r
518   // Now data is in FileBuffer, compress the data\r
519   //\r
520   switch (SectCompSubType) {\r
521   case EFI_NOT_COMPRESSED:\r
522     CompressedLength = InputLength;\r
523     break;\r
524 \r
525   case EFI_STANDARD_COMPRESSION:\r
526     CompressFunction = (COMPRESS_FUNCTION) EfiCompress;\r
527     break;\r
528 \r
529   default:\r
530     Error (NULL, 0, 2000, "Invalid paramter", "unknown compression type");\r
531     free (FileBuffer);\r
532     return EFI_ABORTED;\r
533   }\r
534 \r
535   if (CompressFunction != NULL) {\r
536 \r
537     Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);\r
538     if (Status == EFI_BUFFER_TOO_SMALL) {\r
539       OutputBuffer = malloc (CompressedLength + sizeof (EFI_COMPRESSION_SECTION));\r
540       if (!OutputBuffer) {\r
541         free (FileBuffer);\r
542         return EFI_OUT_OF_RESOURCES;\r
543       }\r
544 \r
545       Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + sizeof (EFI_COMPRESSION_SECTION), &CompressedLength);\r
546     }\r
547 \r
548     free (FileBuffer);\r
549     FileBuffer = OutputBuffer;\r
550 \r
551     if (EFI_ERROR (Status)) {\r
552       if (FileBuffer != NULL) {\r
553         free (FileBuffer);\r
554       }\r
555 \r
556       return Status;\r
557     }\r
558   }\r
559 \r
560   DebugMsg (NULL, 0, 9, "comprss file size", \r
561             "the original section size is %d bytes and the compressed section size is %d bytes", InputLength, CompressedLength);\r
562   TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);\r
563   if (TotalLength >= MAX_SECTION_SIZE) {\r
564     Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);\r
565     if (FileBuffer != NULL) {\r
566       free (FileBuffer);\r
567     }\r
568     if (OutputBuffer != NULL) {\r
569       free (OutputBuffer);\r
570     }\r
571     return STATUS_ERROR;\r
572   }\r
573   VerboseMsg ("the size of the created section file is %d bytes", TotalLength);\r
574 \r
575   //\r
576   // Add the section header for the compressed data\r
577   //\r
578   CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;\r
579   \r
580   CompressionSect->CommonHeader.Type     = EFI_SECTION_COMPRESSION;\r
581   CompressionSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
582   CompressionSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
583   CompressionSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
584   CompressionSect->CompressionType       = SectCompSubType;\r
585   CompressionSect->UncompressedLength    = InputLength;\r
586 \r
587   //\r
588   // Set OutFileBuffer \r
589   //\r
590   *OutFileBuffer = FileBuffer;\r
591 \r
592   return EFI_SUCCESS;\r
593 }\r
594 \r
595 EFI_STATUS\r
596 GenSectionGuidDefinedSection (\r
597   CHAR8    **InputFileName,\r
598   UINT32   InputFileNum,\r
599   EFI_GUID *VendorGuid,\r
600   UINT16   DataAttribute,\r
601   UINT32   DataHeaderSize,\r
602   UINT8    **OutFileBuffer\r
603   )\r
604 /*++\r
605         \r
606 Routine Description:\r
607            \r
608   Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED\r
609   Input file must be already sectioned. The function won't validate\r
610   the input files' contents. Caller should hand in files already \r
611   with section header.\r
612             \r
613 Arguments:\r
614                \r
615   InputFileName - Name of the input file.\r
616                 \r
617   InputFileNum  - Number of input files. Should be at least 1.\r
618 \r
619   VendorGuid    - Specify vendor guid value.\r
620 \r
621   DataAttribute - Specify attribute for the vendor guid data. \r
622   \r
623   DataHeaderSize- Guided Data Header Size\r
624   \r
625   OutFileBuffer   - Buffer pointer to Output file contents\r
626 \r
627 Returns:\r
628                        \r
629   EFI_SUCCESS on successful return\r
630   EFI_INVALID_PARAMETER if InputFileNum is less than 1\r
631   EFI_ABORTED if unable to open input file.\r
632   EFI_OUT_OF_RESOURCES  No resource to complete the operation.\r
633 \r
634 --*/\r
635 {\r
636   UINT32                TotalLength;\r
637   UINT32                InputLength;\r
638   UINT32                Offset;\r
639   UINT8                 *FileBuffer;\r
640   UINT32                Crc32Checksum;\r
641   EFI_STATUS            Status;\r
642   CRC32_SECTION_HEADER  *Crc32GuidSect;\r
643   EFI_GUID_DEFINED_SECTION  *VendorGuidSect;\r
644 \r
645   InputLength = 0;\r
646   Offset      = 0;\r
647   FileBuffer  = NULL;\r
648 \r
649   if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {\r
650     Offset = sizeof (CRC32_SECTION_HEADER);\r
651   } else {\r
652     Offset = sizeof (EFI_GUID_DEFINED_SECTION);\r
653   }\r
654 \r
655   //\r
656   // read all input file contents into a buffer\r
657   // first get the size of all file contents\r
658   //\r
659   Status = GetSectionContents (\r
660             InputFileName,\r
661             InputFileNum,\r
662             FileBuffer,\r
663             &InputLength\r
664             );\r
665 \r
666   if (Status == EFI_BUFFER_TOO_SMALL) {\r
667     FileBuffer = (UINT8 *) malloc (InputLength + Offset);\r
668     if (FileBuffer == NULL) {\r
669       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
670       return EFI_OUT_OF_RESOURCES;\r
671     }\r
672     //\r
673     // read all input file contents into a buffer\r
674     //\r
675     Status = GetSectionContents (\r
676               InputFileName,\r
677               InputFileNum,\r
678               FileBuffer + Offset,\r
679               &InputLength\r
680               );\r
681   }\r
682 \r
683   if (EFI_ERROR (Status)) {\r
684     if (FileBuffer != NULL) {\r
685       free (FileBuffer);\r
686     }\r
687     Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);\r
688     return Status;\r
689   }\r
690 \r
691   if (InputLength == 0) {\r
692     Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);\r
693     return EFI_NOT_FOUND;\r
694   }\r
695 \r
696   //\r
697   // Now data is in FileBuffer + Offset\r
698   //\r
699   if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {\r
700     //\r
701     // Default Guid section is CRC32.\r
702     //\r
703     Crc32Checksum = 0;\r
704     CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);\r
705 \r
706     TotalLength = InputLength + sizeof (CRC32_SECTION_HEADER);\r
707     if (TotalLength >= MAX_SECTION_SIZE) {\r
708       Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);\r
709       free (FileBuffer);\r
710       return STATUS_ERROR;\r
711     }\r
712     \r
713     Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;\r
714     Crc32GuidSect->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
715     Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
716     Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
717     Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
718     memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
719     Crc32GuidSect->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
720     Crc32GuidSect->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER);\r
721     Crc32GuidSect->CRC32Checksum                 = Crc32Checksum;\r
722     DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %d", Crc32GuidSect->GuidSectionHeader.DataOffset);\r
723 \r
724   } else {\r
725     TotalLength = InputLength + sizeof (EFI_GUID_DEFINED_SECTION);\r
726     if (TotalLength >= MAX_SECTION_SIZE) {\r
727       Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);\r
728       free (FileBuffer);\r
729       return STATUS_ERROR;\r
730     }\r
731 \r
732     VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;\r
733     VendorGuidSect->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
734     VendorGuidSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
735     VendorGuidSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
736     VendorGuidSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
737     memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));\r
738     VendorGuidSect->Attributes  = DataAttribute;\r
739     VendorGuidSect->DataOffset  = sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize;\r
740     DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %d", VendorGuidSect->DataOffset);\r
741   }\r
742   VerboseMsg ("the size of the created section file is %d bytes", TotalLength);\r
743   \r
744   //\r
745   // Set OutFileBuffer \r
746   //\r
747   *OutFileBuffer = FileBuffer;\r
748 \r
749   return EFI_SUCCESS;\r
750 }\r
751 \r
752 int\r
753 main (\r
754   int  argc,\r
755   char *argv[]\r
756   )\r
757 /*++\r
758 \r
759 Routine Description:\r
760 \r
761   Main\r
762 \r
763 Arguments:\r
764 \r
765   command line parameters\r
766 \r
767 Returns:\r
768 \r
769   EFI_SUCCESS    Section header successfully generated and section concatenated.\r
770   EFI_ABORTED    Could not generate the section\r
771   EFI_OUT_OF_RESOURCES  No resource to complete the operation.\r
772 \r
773 --*/\r
774 {\r
775   UINT32                    Index;\r
776   UINT32                    InputFileNum;\r
777   FILE                      *InFile;\r
778   FILE                      *OutFile;\r
779   CHAR8                     **InputFileName;\r
780   CHAR8                     *OutputFileName;\r
781   CHAR8                     *SectionName;\r
782   CHAR8                     *CompressionName;\r
783   CHAR8                     *StringBuffer;\r
784   EFI_GUID                  VendorGuid = mZeroGuid;\r
785   INT32                     VersionNumber;\r
786   UINT8                     SectType;\r
787   UINT8                     SectCompSubType;\r
788   UINT16                    SectGuidAttribute; \r
789   UINT64                    SectGuidHeaderLength;\r
790   EFI_VERSION_SECTION       *VersionSect;\r
791   EFI_USER_INTERFACE_SECTION *UiSect;\r
792   UINT32                    InputLength;\r
793   UINT8                     *OutFileBuffer;\r
794   UINT8                     *TempBuffer;\r
795   UINT32                    TempLength;\r
796   EFI_STATUS                Status;\r
797   UINT64                    LogLevel;\r
798   \r
799   InputFileName         = NULL;\r
800   OutputFileName        = NULL;\r
801   SectionName           = NULL;\r
802   CompressionName       = NULL;\r
803   StringBuffer          = "";\r
804   InFile                = NULL;\r
805   OutFile               = NULL;\r
806   VersionNumber         = 0;\r
807   InputFileNum          = 0;\r
808   SectType              = EFI_SECTION_ALL;\r
809   SectCompSubType       = 0;\r
810   SectGuidAttribute     = 0;\r
811   OutFileBuffer         = NULL;\r
812   InputLength           = 0;\r
813   Status                = STATUS_SUCCESS;\r
814   LogLevel              = 0;\r
815   SectGuidHeaderLength  = 0;\r
816   VersionSect           = NULL;\r
817   UiSect                = NULL;\r
818   TempBuffer            = 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", 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 EFI_OUT_OF_RESOURCES;\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 EFI_OUT_OF_RESOURCES;\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                 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%x", 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 %dth input file name is %s", 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 %d bytes", 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 %d bytes", 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 %d bytes", 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", (UINTN) 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   // Write the Buffer to the Output file.\r
1281   //\r
1282   OutFile = fopen (OutputFileName, "rb");\r
1283   if (OutFile != NULL) {\r
1284     //\r
1285     // the output file exists\r
1286     // first compare the output buffer and the exist output file \r
1287     // if same, not to update output file\r
1288     //\r
1289     fseek (OutFile, 0, SEEK_END);\r
1290     TempLength = ftell (OutFile);\r
1291     fseek (OutFile, 0, SEEK_SET);\r
1292 \r
1293     if (InputLength != TempLength) {\r
1294       //\r
1295       //  they can't be same because their size are different\r
1296       //\r
1297       goto WriteFile;\r
1298     }\r
1299     //\r
1300     // read file data from output file\r
1301     //\r
1302     TempBuffer = (UINT8 *) malloc (TempLength);\r
1303     if (TempBuffer == NULL) {\r
1304       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1305       goto Finish;\r
1306     }\r
1307     fread (TempBuffer, TempLength, 1, OutFile);\r
1308     //\r
1309     // Compare Data byte by byte\r
1310     //\r
1311     for (Index = 0; Index < InputLength; Index ++) {\r
1312       if (OutFileBuffer [Index] != TempBuffer [Index]) {\r
1313         break;\r
1314       }\r
1315     }\r
1316     //\r
1317     // Data is same, output file doesn't need to be updated.\r
1318     //\r
1319     if (Index >= InputLength) {\r
1320       goto Finish;\r
1321     }\r
1322   }\r
1323 \r
1324 WriteFile:\r
1325   if (OutFile != NULL) {\r
1326     fclose (OutFile);\r
1327   }\r
1328 \r
1329   OutFile = fopen (OutputFileName, "wb");\r
1330   if (OutFile == NULL) {\r
1331     Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);\r
1332     goto Finish;\r
1333   }\r
1334 \r
1335   fwrite (OutFileBuffer, InputLength, 1, OutFile);\r
1336 \r
1337 Finish:\r
1338   if (InputFileName != NULL) {\r
1339     free (InputFileName);\r
1340   }\r
1341   \r
1342   if (TempBuffer != NULL) {\r
1343     free (TempBuffer);\r
1344   }\r
1345 \r
1346   if (OutFileBuffer != NULL) {\r
1347     free (OutFileBuffer);\r
1348   }\r
1349 \r
1350   if (OutFile != NULL) {\r
1351     fclose (OutFile);\r
1352   }\r
1353   \r
1354   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
1355 \r
1356   return GetUtilityStatus ();\r
1357 }\r