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