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