Fix two bugs in GenFfs and GenSec tool to handle the different cases.
[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     return Status;\r
688   }\r
689 \r
690   //\r
691   // Now data is in FileBuffer + Offset\r
692   //\r
693   if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {\r
694     //\r
695     // Default Guid section is CRC32.\r
696     //\r
697     Crc32Checksum = 0;\r
698     CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);\r
699 \r
700     TotalLength = InputLength + sizeof (CRC32_SECTION_HEADER);\r
701     if (TotalLength >= MAX_SECTION_SIZE) {\r
702       Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);\r
703       free (FileBuffer);\r
704       return STATUS_ERROR;\r
705     }\r
706     \r
707     Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;\r
708     Crc32GuidSect->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
709     Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
710     Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
711     Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
712     memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
713     Crc32GuidSect->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
714     Crc32GuidSect->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER);\r
715     Crc32GuidSect->CRC32Checksum                 = Crc32Checksum;\r
716     DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %d", Crc32GuidSect->GuidSectionHeader.DataOffset);\r
717 \r
718   } else {\r
719     TotalLength = InputLength + sizeof (EFI_GUID_DEFINED_SECTION);\r
720     if (TotalLength >= MAX_SECTION_SIZE) {\r
721       Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);\r
722       free (FileBuffer);\r
723       return STATUS_ERROR;\r
724     }\r
725 \r
726     VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;\r
727     VendorGuidSect->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
728     VendorGuidSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
729     VendorGuidSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
730     VendorGuidSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
731     memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));\r
732     VendorGuidSect->Attributes  = DataAttribute;\r
733     VendorGuidSect->DataOffset  = sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize;\r
734     DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %d", VendorGuidSect->DataOffset);\r
735   }\r
736   VerboseMsg ("the size of the created section file is %d bytes", TotalLength);\r
737   \r
738   //\r
739   // Set OutFileBuffer \r
740   //\r
741   *OutFileBuffer = FileBuffer;\r
742 \r
743   return EFI_SUCCESS;\r
744 }\r
745 \r
746 int\r
747 main (\r
748   int  argc,\r
749   char *argv[]\r
750   )\r
751 /*++\r
752 \r
753 Routine Description:\r
754 \r
755   Main\r
756 \r
757 Arguments:\r
758 \r
759   command line parameters\r
760 \r
761 Returns:\r
762 \r
763   EFI_SUCCESS    Section header successfully generated and section concatenated.\r
764   EFI_ABORTED    Could not generate the section\r
765   EFI_OUT_OF_RESOURCES  No resource to complete the operation.\r
766 \r
767 --*/\r
768 {\r
769   UINT32                    Index;\r
770   UINT32                    InputFileNum;\r
771   FILE                      *InFile;\r
772   FILE                      *OutFile;\r
773   CHAR8                     **InputFileName;\r
774   CHAR8                     *OutputFileName;\r
775   CHAR8                     *SectionName;\r
776   CHAR8                     *CompressionName;\r
777   CHAR8                     *StringBuffer;\r
778   EFI_GUID                  VendorGuid = mZeroGuid;\r
779   INT32                     VersionNumber;\r
780   UINT8                     SectType;\r
781   UINT8                     SectCompSubType;\r
782   UINT16                    SectGuidAttribute; \r
783   UINT64                    SectGuidHeaderLength;\r
784   EFI_VERSION_SECTION       *VersionSect;\r
785   EFI_USER_INTERFACE_SECTION *UiSect;\r
786   UINT32                    InputLength;\r
787   UINT8                     *OutFileBuffer;\r
788   UINT8                     *TempBuffer;\r
789   UINT32                    TempLength;\r
790   EFI_STATUS                Status;\r
791   UINT64                    LogLevel;\r
792   \r
793   InputFileName         = NULL;\r
794   OutputFileName        = NULL;\r
795   SectionName           = NULL;\r
796   CompressionName       = NULL;\r
797   StringBuffer          = "";\r
798   InFile                = NULL;\r
799   OutFile               = NULL;\r
800   VersionNumber         = 0;\r
801   InputFileNum          = 0;\r
802   SectType              = EFI_SECTION_ALL;\r
803   SectCompSubType       = 0;\r
804   SectGuidAttribute     = 0;\r
805   OutFileBuffer         = NULL;\r
806   InputLength           = 0;\r
807   Status                = STATUS_SUCCESS;\r
808   LogLevel              = 0;\r
809   SectGuidHeaderLength  = 0;\r
810   VersionSect           = NULL;\r
811   UiSect                = NULL;\r
812   TempBuffer            = NULL;\r
813   \r
814   SetUtilityName (UTILITY_NAME);\r
815   \r
816   if (argc == 1) {\r
817     Error (NULL, 0, 1001, "Missing options", "No options input");\r
818     Usage ();\r
819     return STATUS_ERROR;\r
820   }\r
821 \r
822   //\r
823   // Parse command line\r
824   //\r
825   argc --;\r
826   argv ++;\r
827 \r
828   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
829     Version ();\r
830     Usage ();\r
831     return STATUS_SUCCESS;    \r
832   }\r
833 \r
834   if (stricmp (argv[0], "--version") == 0) {\r
835     Version ();\r
836     return STATUS_SUCCESS;    \r
837   }\r
838 \r
839   while (argc > 0) {\r
840     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {\r
841       SectionName = argv[1];\r
842       if (SectionName == NULL) {\r
843         Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");\r
844         goto Finish;\r
845       }\r
846       argc -= 2;\r
847       argv += 2;\r
848       continue; \r
849     }\r
850 \r
851     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
852       OutputFileName = argv[1];\r
853       if (OutputFileName == NULL) {\r
854         Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");\r
855         goto Finish;\r
856       }\r
857       argc -= 2;\r
858       argv += 2;\r
859       continue; \r
860     }\r
861 \r
862     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {\r
863       CompressionName = argv[1];\r
864       if (CompressionName == NULL) {\r
865         Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");\r
866         goto Finish;\r
867       }\r
868       argc -= 2;\r
869       argv += 2;\r
870       continue;\r
871     }\r
872 \r
873     if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {\r
874       Status = StringToGuid (argv[1], &VendorGuid);\r
875       if (EFI_ERROR (Status)) {\r
876         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
877         goto Finish;\r
878       }\r
879       argc -= 2;\r
880       argv += 2;\r
881       continue;\r
882     }\r
883 \r
884     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {\r
885       if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {\r
886         SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
887       } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {\r
888         SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
889       } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {\r
890         //\r
891         // NONE attribute\r
892         //\r
893         SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;\r
894       } else {\r
895         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
896         goto Finish;\r
897       }\r
898       argc -= 2;\r
899       argv += 2;\r
900       continue;\r
901     }\r
902 \r
903     if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {\r
904       Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);\r
905       if (EFI_ERROR (Status)) {\r
906         Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);\r
907         goto Finish;\r
908       }\r
909       argc -= 2;\r
910       argv += 2;\r
911       continue;\r
912     }\r
913 \r
914     if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {\r
915       StringBuffer = argv[1];\r
916       if (StringBuffer == NULL) {\r
917         Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");\r
918         goto Finish;\r
919       }\r
920       argc -= 2;\r
921       argv += 2;\r
922       continue;\r
923     }\r
924 \r
925     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {\r
926       if (argv[1] == NULL) {\r
927         Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");\r
928         goto Finish;\r
929       }\r
930       //\r
931       // Verify string is a integrator number\r
932       //\r
933       for (Index = 0; Index < strlen (argv[1]); Index++) {\r
934         if ((argv[1][Index] != '-') && (isdigit (argv[1][Index]) == 0)) {\r
935           Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
936           goto Finish;\r
937         }\r
938       }\r
939 \r
940       sscanf (argv[1], "%d", &VersionNumber);\r
941       argc -= 2;\r
942       argv += 2;\r
943       continue;\r
944     }\r
945 \r
946     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
947       SetPrintLevel (VERBOSE_LOG_LEVEL);\r
948       VerboseMsg ("Verbose output Mode Set!");\r
949       argc --;\r
950       argv ++;\r
951       continue;\r
952     }\r
953 \r
954     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
955       SetPrintLevel (KEY_LOG_LEVEL);\r
956       KeyMsg ("Quiet output Mode Set!");\r
957       argc --;\r
958       argv ++;\r
959       continue;\r
960     }\r
961 \r
962     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
963       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
964       if (EFI_ERROR (Status)) {\r
965         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
966         goto Finish;\r
967       }\r
968       if (LogLevel > 9) {\r
969         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", LogLevel);\r
970         goto Finish;\r
971       }\r
972       SetPrintLevel (LogLevel);\r
973       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
974       argc -= 2;\r
975       argv += 2;\r
976       continue;\r
977     }\r
978 \r
979     //\r
980     // Get Input file name\r
981     //\r
982     if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
983       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
984       if (InputFileName == NULL) {\r
985         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
986         return EFI_OUT_OF_RESOURCES;\r
987       }\r
988 \r
989       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
990     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
991       //\r
992       // InputFileName buffer too small, need to realloc\r
993       //\r
994       InputFileName = (CHAR8 **) realloc (\r
995                                   InputFileName,\r
996                                   (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
997                                   );\r
998 \r
999       if (InputFileName == NULL) {\r
1000         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1001         return EFI_OUT_OF_RESOURCES;\r
1002       }\r
1003 \r
1004       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1005     }\r
1006 \r
1007     InputFileName[InputFileNum++] = argv[0];\r
1008     argc --;\r
1009     argv ++;\r
1010   }\r
1011 \r
1012   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
1013 \r
1014   //\r
1015   // Parse all command line parameters to get the corresponding section type.\r
1016   //\r
1017   VerboseMsg ("Section type is %s", SectionName);\r
1018   if (SectionName == NULL) {\r
1019     //\r
1020     // No specified Section type, default is SECTION_ALL.\r
1021     //\r
1022     SectType = EFI_SECTION_ALL;\r
1023   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {\r
1024     SectType     = EFI_SECTION_COMPRESSION;\r
1025     if (CompressionName == NULL) {\r
1026       //\r
1027       // Default is PI_STD compression algorithm.\r
1028       //\r
1029       SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1030     } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {\r
1031       SectCompSubType = EFI_NOT_COMPRESSED;\r
1032     } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {\r
1033       SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1034     } else {\r
1035       Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);\r
1036       goto Finish;\r
1037     }\r
1038     VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);\r
1039   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {\r
1040     SectType     = EFI_SECTION_GUID_DEFINED;\r
1041 \r
1042     if (CompareGuid (&VendorGuid, &mZeroGuid) == 0) {\r
1043       memcpy (&VendorGuid, &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
1044     }\r
1045     \r
1046     if (SectGuidAttribute == 0) {\r
1047       SectGuidAttribute = EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
1048     }\r
1049     if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {\r
1050       //\r
1051       // NONE attribute, clear attribute value.\r
1052       //\r
1053       SectGuidAttribute = 0;\r
1054     }\r
1055     VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", \r
1056                 VendorGuid.Data1,\r
1057                 VendorGuid.Data2,\r
1058                 VendorGuid.Data3,\r
1059                 VendorGuid.Data4[0],\r
1060                 VendorGuid.Data4[1],\r
1061                 VendorGuid.Data4[2],\r
1062                 VendorGuid.Data4[3],\r
1063                 VendorGuid.Data4[4],\r
1064                 VendorGuid.Data4[5],\r
1065                 VendorGuid.Data4[6],\r
1066                 VendorGuid.Data4[7]);\r
1067     if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {\r
1068       VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);\r
1069     }\r
1070     if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {\r
1071       VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);\r
1072     }\r
1073     if (SectGuidHeaderLength != 0) {\r
1074       VerboseMsg ("Guid Data Header size is 0x%x", SectGuidHeaderLength);\r
1075     }\r
1076   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {\r
1077     SectType = EFI_SECTION_PE32;\r
1078   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {\r
1079     SectType = EFI_SECTION_PIC;\r
1080   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {\r
1081     SectType = EFI_SECTION_TE;\r
1082   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {\r
1083     SectType = EFI_SECTION_DXE_DEPEX;\r
1084   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {\r
1085     SectType = EFI_SECTION_VERSION;\r
1086     if (VersionNumber < 0 || VersionNumber > 9999) {\r
1087       Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~9999", VersionNumber);\r
1088       goto Finish;\r
1089     }\r
1090     VerboseMsg ("Version section number is %d", VersionNumber);\r
1091   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {\r
1092     SectType = EFI_SECTION_USER_INTERFACE;\r
1093     if (StringBuffer[0] == '\0') {\r
1094       Error (NULL, 0, 1001, "Missing option", "user interface string");\r
1095       goto Finish;\r
1096     }\r
1097     VerboseMsg ("UI section string name is %s", StringBuffer);\r
1098   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {\r
1099     SectType = EFI_SECTION_COMPATIBILITY16;\r
1100   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {\r
1101     SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
1102   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {\r
1103     SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;\r
1104   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {\r
1105     SectType = EFI_SECTION_RAW;\r
1106   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {\r
1107     SectType = EFI_SECTION_PEI_DEPEX;\r
1108   } else {\r
1109     Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);\r
1110     goto Finish;\r
1111   }\r
1112   \r
1113   //\r
1114   // GuidValue is only required by Guided section.\r
1115   //\r
1116   if ((SectType != EFI_SECTION_GUID_DEFINED) && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
1117     fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);\r
1118   }\r
1119   \r
1120   //\r
1121   // Check whether there is input file\r
1122   //  \r
1123   if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {\r
1124     //\r
1125     // The input file are required for other section type.\r
1126     //\r
1127     if (InputFileNum == 0) {\r
1128       Error (NULL, 0, 1001, "Missing options", "Input files");\r
1129       goto Finish;\r
1130     }\r
1131   }\r
1132   //\r
1133   // Check whether there is output file\r
1134   //\r
1135   for (Index = 0; Index < InputFileNum; Index ++) {\r
1136     VerboseMsg ("the %dth input file name is %s", Index, InputFileName[Index]);\r
1137   }\r
1138   if (OutputFileName == NULL) {\r
1139     Error (NULL, 0, 1001, "Missing options", "Output file");\r
1140     goto Finish;\r
1141     // OutFile = stdout;\r
1142   }\r
1143   VerboseMsg ("Output file name is %s", OutputFileName);\r
1144 \r
1145   //\r
1146   // At this point, we've fully validated the command line, and opened appropriate\r
1147   // files, so let's go and do what we've been asked to do...\r
1148   //\r
1149   //\r
1150   // Within this switch, build and write out the section header including any\r
1151   // section type specific pieces.  If there's an input file, it's tacked on later\r
1152   //\r
1153   switch (SectType) {\r
1154   case EFI_SECTION_COMPRESSION:\r
1155     Status = GenSectionCompressionSection (\r
1156               InputFileName,\r
1157               InputFileNum,\r
1158               SectCompSubType,\r
1159               &OutFileBuffer\r
1160               );\r
1161     break;\r
1162 \r
1163   case EFI_SECTION_GUID_DEFINED:\r
1164     Status = GenSectionGuidDefinedSection (\r
1165               InputFileName,\r
1166               InputFileNum,\r
1167               &VendorGuid,\r
1168               SectGuidAttribute,\r
1169               (UINT32) SectGuidHeaderLength,\r
1170               &OutFileBuffer\r
1171               );\r
1172     break;\r
1173 \r
1174   case EFI_SECTION_VERSION:\r
1175     Index           = sizeof (EFI_COMMON_SECTION_HEADER);\r
1176     //\r
1177     // 2 bytes for the build number UINT16\r
1178     //\r
1179     Index += 2;\r
1180     //\r
1181     // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1182     //\r
1183     Index += (strlen (StringBuffer) * 2) + 2;\r
1184     OutFileBuffer = (UINT8 *) malloc (Index);\r
1185     if (OutFileBuffer == NULL) {\r
1186       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1187       goto Finish;\r
1188     }\r
1189     VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;\r
1190     VersionSect->CommonHeader.Type     = SectType;\r
1191     VersionSect->CommonHeader.Size[0]  = (UINT8) (Index & 0xff);\r
1192     VersionSect->CommonHeader.Size[1]  = (UINT8) ((Index & 0xff00) >> 8);\r
1193     VersionSect->CommonHeader.Size[2]  = (UINT8) ((Index & 0xff0000) >> 16);\r
1194     VersionSect->BuildNumber           = (UINT16) VersionNumber;\r
1195     Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);\r
1196     VerboseMsg ("the size of the created section file is %d bytes", Index);\r
1197     break;\r
1198 \r
1199   case EFI_SECTION_USER_INTERFACE:\r
1200     Index           = sizeof (EFI_COMMON_SECTION_HEADER);\r
1201     //\r
1202     // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1203     //\r
1204     Index += (strlen (StringBuffer) * 2) + 2;\r
1205     OutFileBuffer = (UINT8 *) malloc (Index);\r
1206     if (OutFileBuffer == NULL) {\r
1207       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1208       goto Finish;\r
1209     }\r
1210     UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;\r
1211     UiSect->CommonHeader.Type     = SectType;\r
1212     UiSect->CommonHeader.Size[0]  = (UINT8) (Index & 0xff);\r
1213     UiSect->CommonHeader.Size[1]  = (UINT8) ((Index & 0xff00) >> 8);\r
1214     UiSect->CommonHeader.Size[2]  = (UINT8) ((Index & 0xff0000) >> 16);\r
1215     Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);\r
1216     VerboseMsg ("the size of the created section file is %d bytes", Index);\r
1217    break;\r
1218 \r
1219   case EFI_SECTION_ALL:\r
1220     //\r
1221     // read all input file contents into a buffer\r
1222     // first get the size of all file contents\r
1223     //\r
1224     Status = GetSectionContents (\r
1225               InputFileName,\r
1226               InputFileNum,\r
1227               OutFileBuffer,\r
1228               &InputLength\r
1229               );\r
1230   \r
1231     if (Status == EFI_BUFFER_TOO_SMALL) {\r
1232       OutFileBuffer = (UINT8 *) malloc (InputLength);\r
1233       if (OutFileBuffer == NULL) {\r
1234         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1235         goto Finish;\r
1236       }\r
1237       //\r
1238       // read all input file contents into a buffer\r
1239       //\r
1240       Status = GetSectionContents (\r
1241                 InputFileName,\r
1242                 InputFileNum,\r
1243                 OutFileBuffer,\r
1244                 &InputLength\r
1245                 );\r
1246     }\r
1247     VerboseMsg ("the size of the created section file is %d bytes", InputLength);\r
1248     break;\r
1249   default:\r
1250     //\r
1251     // All other section types are caught by default (they're all the same)\r
1252     //\r
1253     Status = GenSectionCommonLeafSection (\r
1254               InputFileName,\r
1255               InputFileNum,\r
1256               SectType,\r
1257               &OutFileBuffer\r
1258               );\r
1259     break;\r
1260   }\r
1261   \r
1262   if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {\r
1263           goto Finish;\r
1264   }\r
1265 \r
1266   //\r
1267   // Get output file length\r
1268   //\r
1269   if (SectType != EFI_SECTION_ALL) {\r
1270     InputLength = SECTION_SIZE (OutFileBuffer);\r
1271   }\r
1272   //\r
1273   // Write the Buffer to the Output file.\r
1274   //\r
1275   OutFile = fopen (OutputFileName, "rb");\r
1276   if (OutFile != NULL) {\r
1277     //\r
1278     // the output file exists\r
1279     // first compare the output buffer and the exist output file \r
1280     // if same, not to update output file\r
1281     //\r
1282     fseek (OutFile, 0, SEEK_END);\r
1283     TempLength = ftell (OutFile);\r
1284     fseek (OutFile, 0, SEEK_SET);\r
1285 \r
1286     if (InputLength != TempLength) {\r
1287       //\r
1288       //  they can't be same because their size are different\r
1289       //\r
1290       goto WriteFile;\r
1291     }\r
1292     //\r
1293     // read file data from output file\r
1294     //\r
1295     TempBuffer = (UINT8 *) malloc (TempLength);\r
1296     if (TempBuffer == NULL) {\r
1297       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1298       goto Finish;\r
1299     }\r
1300     fread (TempBuffer, TempLength, 1, OutFile);\r
1301     //\r
1302     // Compare Data byte by byte\r
1303     //\r
1304     for (Index = 0; Index < InputLength; Index ++) {\r
1305       if (OutFileBuffer [Index] != TempBuffer [Index]) {\r
1306         break;\r
1307       }\r
1308     }\r
1309     //\r
1310     // Data is same, output file doesn't need to be updated.\r
1311     //\r
1312     if (Index >= InputLength) {\r
1313       goto Finish;\r
1314     }\r
1315   }\r
1316 \r
1317 WriteFile:\r
1318   if (OutFile != NULL) {\r
1319     fclose (OutFile);\r
1320   }\r
1321 \r
1322   OutFile = fopen (OutputFileName, "wb");\r
1323   if (OutFile == NULL) {\r
1324     Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);\r
1325     goto Finish;\r
1326   }\r
1327 \r
1328   fwrite (OutFileBuffer, InputLength, 1, OutFile);\r
1329 \r
1330 Finish:\r
1331   if (InputFileName != NULL) {\r
1332     free (InputFileName);\r
1333   }\r
1334   \r
1335   if (TempBuffer != NULL) {\r
1336     free (TempBuffer);\r
1337   }\r
1338 \r
1339   if (OutFileBuffer != NULL) {\r
1340     free (OutFileBuffer);\r
1341   }\r
1342 \r
1343   if (OutFile != NULL) {\r
1344     fclose (OutFile);\r
1345   }\r
1346   \r
1347   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
1348 \r
1349   return GetUtilityStatus ();\r
1350 }\r