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