fdf0375b47f0dcdf891ffc5252957d69322117a0
[efi/basetools/.git] / 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     break;\r
650 \r
651   case EFI_STANDARD_COMPRESSION:\r
652     CompressFunction = (COMPRESS_FUNCTION) EfiCompress;\r
653     break;\r
654 \r
655   default:\r
656     Error (NULL, 0, 2000, "Invalid paramter", "unknown compression type");\r
657     free (FileBuffer);\r
658     return EFI_ABORTED;\r
659   }\r
660 \r
661   if (CompressFunction != NULL) {\r
662 \r
663     Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);\r
664     if (Status == EFI_BUFFER_TOO_SMALL) {\r
665       OutputBuffer = malloc (CompressedLength + sizeof (EFI_COMPRESSION_SECTION));\r
666       if (!OutputBuffer) {\r
667         free (FileBuffer);\r
668         return EFI_OUT_OF_RESOURCES;\r
669       }\r
670 \r
671       Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + sizeof (EFI_COMPRESSION_SECTION), &CompressedLength);\r
672     }\r
673 \r
674     free (FileBuffer);\r
675     FileBuffer = OutputBuffer;\r
676 \r
677     if (EFI_ERROR (Status)) {\r
678       if (FileBuffer != NULL) {\r
679         free (FileBuffer);\r
680       }\r
681 \r
682       return Status;\r
683     }\r
684   }\r
685 \r
686   DebugMsg (NULL, 0, 9, "comprss file size", \r
687             "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);\r
688   TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);\r
689   if (TotalLength >= MAX_SECTION_SIZE) {\r
690     Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);\r
691     if (FileBuffer != NULL) {\r
692       free (FileBuffer);\r
693     }\r
694     if (OutputBuffer != NULL) {\r
695       free (OutputBuffer);\r
696     }\r
697     return STATUS_ERROR;\r
698   }\r
699   VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
700 \r
701   //\r
702   // Add the section header for the compressed data\r
703   //\r
704   CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;\r
705   \r
706   CompressionSect->CommonHeader.Type     = EFI_SECTION_COMPRESSION;\r
707   CompressionSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
708   CompressionSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
709   CompressionSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
710   CompressionSect->CompressionType       = SectCompSubType;\r
711   CompressionSect->UncompressedLength    = InputLength;\r
712 \r
713   //\r
714   // Set OutFileBuffer \r
715   //\r
716   *OutFileBuffer = FileBuffer;\r
717 \r
718   return EFI_SUCCESS;\r
719 }\r
720 \r
721 EFI_STATUS\r
722 GenSectionGuidDefinedSection (\r
723   CHAR8    **InputFileName,\r
724   UINT32   *InputFileAlign,\r
725   UINT32   InputFileNum,\r
726   EFI_GUID *VendorGuid,\r
727   UINT16   DataAttribute,\r
728   UINT32   DataHeaderSize,\r
729   UINT8    **OutFileBuffer\r
730   )\r
731 /*++\r
732         \r
733 Routine Description:\r
734            \r
735   Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED\r
736   Input file must be already sectioned. The function won't validate\r
737   the input files' contents. Caller should hand in files already \r
738   with section header.\r
739             \r
740 Arguments:\r
741                \r
742   InputFileName - Name of the input file.\r
743                 \r
744   InputFileAlign - Alignment required by the input file data.\r
745 \r
746   InputFileNum  - Number of input files. Should be at least 1.\r
747 \r
748   VendorGuid    - Specify vendor guid value.\r
749 \r
750   DataAttribute - Specify attribute for the vendor guid data. \r
751   \r
752   DataHeaderSize- Guided Data Header Size\r
753   \r
754   OutFileBuffer   - Buffer pointer to Output file contents\r
755 \r
756 Returns:\r
757                        \r
758   EFI_SUCCESS on successful return\r
759   EFI_INVALID_PARAMETER if InputFileNum is less than 1\r
760   EFI_ABORTED if unable to open input file.\r
761   EFI_OUT_OF_RESOURCES  No resource to complete the operation.\r
762 \r
763 --*/\r
764 {\r
765   UINT32                TotalLength;\r
766   UINT32                InputLength;\r
767   UINT32                Offset;\r
768   UINT8                 *FileBuffer;\r
769   UINT32                Crc32Checksum;\r
770   EFI_STATUS            Status;\r
771   CRC32_SECTION_HEADER  *Crc32GuidSect;\r
772   EFI_GUID_DEFINED_SECTION  *VendorGuidSect;\r
773 \r
774   InputLength = 0;\r
775   Offset      = 0;\r
776   FileBuffer  = NULL;\r
777 \r
778   if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {\r
779     Offset = sizeof (CRC32_SECTION_HEADER);\r
780   } else {\r
781     Offset = sizeof (EFI_GUID_DEFINED_SECTION);\r
782   }\r
783 \r
784   //\r
785   // read all input file contents into a buffer\r
786   // first get the size of all file contents\r
787   //\r
788   Status = GetSectionContents (\r
789             InputFileName,\r
790             InputFileAlign,\r
791             InputFileNum,\r
792             FileBuffer,\r
793             &InputLength\r
794             );\r
795 \r
796   if (Status == EFI_BUFFER_TOO_SMALL) {\r
797     FileBuffer = (UINT8 *) malloc (InputLength + Offset);\r
798     if (FileBuffer == NULL) {\r
799       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
800       return EFI_OUT_OF_RESOURCES;\r
801     }\r
802     //\r
803     // read all input file contents into a buffer\r
804     //\r
805     Status = GetSectionContents (\r
806               InputFileName,\r
807               InputFileAlign,\r
808               InputFileNum,\r
809               FileBuffer + Offset,\r
810               &InputLength\r
811               );\r
812   }\r
813 \r
814   if (EFI_ERROR (Status)) {\r
815     if (FileBuffer != NULL) {\r
816       free (FileBuffer);\r
817     }\r
818     Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);\r
819     return Status;\r
820   }\r
821 \r
822   if (InputLength == 0) {\r
823     Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);\r
824     return EFI_NOT_FOUND;\r
825   }\r
826 \r
827   //\r
828   // Now data is in FileBuffer + Offset\r
829   //\r
830   if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {\r
831     //\r
832     // Default Guid section is CRC32.\r
833     //\r
834     Crc32Checksum = 0;\r
835     CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);\r
836 \r
837     TotalLength = InputLength + sizeof (CRC32_SECTION_HEADER);\r
838     if (TotalLength >= MAX_SECTION_SIZE) {\r
839       Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);\r
840       free (FileBuffer);\r
841       return STATUS_ERROR;\r
842     }\r
843     \r
844     Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;\r
845     Crc32GuidSect->GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
846     Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
847     Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
848     Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
849     memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
850     Crc32GuidSect->GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
851     Crc32GuidSect->GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER);\r
852     Crc32GuidSect->CRC32Checksum                 = Crc32Checksum;\r
853     DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);\r
854 \r
855   } else {\r
856     TotalLength = InputLength + sizeof (EFI_GUID_DEFINED_SECTION);\r
857     if (TotalLength >= MAX_SECTION_SIZE) {\r
858       Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);\r
859       free (FileBuffer);\r
860       return STATUS_ERROR;\r
861     }\r
862 \r
863     VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;\r
864     VendorGuidSect->CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
865     VendorGuidSect->CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
866     VendorGuidSect->CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
867     VendorGuidSect->CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
868     memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));\r
869     VendorGuidSect->Attributes  = DataAttribute;\r
870     VendorGuidSect->DataOffset  = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);\r
871     DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);\r
872   }\r
873   VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
874   \r
875   //\r
876   // Set OutFileBuffer \r
877   //\r
878   *OutFileBuffer = FileBuffer;\r
879 \r
880   return EFI_SUCCESS;\r
881 }\r
882 \r
883 int\r
884 main (\r
885   int  argc,\r
886   char *argv[]\r
887   )\r
888 /*++\r
889 \r
890 Routine Description:\r
891 \r
892   Main\r
893 \r
894 Arguments:\r
895 \r
896   command line parameters\r
897 \r
898 Returns:\r
899 \r
900   EFI_SUCCESS    Section header successfully generated and section concatenated.\r
901   EFI_ABORTED    Could not generate the section\r
902   EFI_OUT_OF_RESOURCES  No resource to complete the operation.\r
903 \r
904 --*/\r
905 {\r
906   UINT32                    Index;\r
907   UINT32                    InputFileNum;\r
908   FILE                      *InFile;\r
909   FILE                      *OutFile;\r
910   CHAR8                     **InputFileName;\r
911   CHAR8                     *OutputFileName;\r
912   CHAR8                     *SectionName;\r
913   CHAR8                     *CompressionName;\r
914   CHAR8                     *StringBuffer;\r
915   EFI_GUID                  VendorGuid = mZeroGuid;\r
916   int                       VersionNumber;\r
917   UINT8                     SectType;\r
918   UINT8                     SectCompSubType;\r
919   UINT16                    SectGuidAttribute; \r
920   UINT64                    SectGuidHeaderLength;\r
921   EFI_VERSION_SECTION       *VersionSect;\r
922   EFI_USER_INTERFACE_SECTION *UiSect;\r
923   UINT32                    InputLength;\r
924   UINT8                     *OutFileBuffer;\r
925   EFI_STATUS                Status;\r
926   UINT64                    LogLevel;\r
927   UINT32                    *InputFileAlign;\r
928   UINT32                    InputFileAlignNum;\r
929 \r
930   InputFileAlign        = NULL;\r
931   InputFileAlignNum     = 0;\r
932   InputFileName         = NULL;\r
933   OutputFileName        = NULL;\r
934   SectionName           = NULL;\r
935   CompressionName       = NULL;\r
936   StringBuffer          = "";\r
937   InFile                = NULL;\r
938   OutFile               = NULL;\r
939   VersionNumber         = 0;\r
940   InputFileNum          = 0;\r
941   SectType              = EFI_SECTION_ALL;\r
942   SectCompSubType       = 0;\r
943   SectGuidAttribute     = EFI_GUIDED_SECTION_NONE;\r
944   OutFileBuffer         = NULL;\r
945   InputLength           = 0;\r
946   Status                = STATUS_SUCCESS;\r
947   LogLevel              = 0;\r
948   SectGuidHeaderLength  = 0;\r
949   VersionSect           = NULL;\r
950   UiSect                = NULL;\r
951   \r
952   SetUtilityName (UTILITY_NAME);\r
953   \r
954   if (argc == 1) {\r
955     Error (NULL, 0, 1001, "Missing options", "No options input");\r
956     Usage ();\r
957     return STATUS_ERROR;\r
958   }\r
959 \r
960   //\r
961   // Parse command line\r
962   //\r
963   argc --;\r
964   argv ++;\r
965 \r
966   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
967     Version ();\r
968     Usage ();\r
969     return STATUS_SUCCESS;    \r
970   }\r
971 \r
972   if (stricmp (argv[0], "--version") == 0) {\r
973     Version ();\r
974     return STATUS_SUCCESS;    \r
975   }\r
976 \r
977   while (argc > 0) {\r
978     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {\r
979       SectionName = argv[1];\r
980       if (SectionName == NULL) {\r
981         Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");\r
982         goto Finish;\r
983       }\r
984       argc -= 2;\r
985       argv += 2;\r
986       continue; \r
987     }\r
988 \r
989     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
990       OutputFileName = argv[1];\r
991       if (OutputFileName == NULL) {\r
992         Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");\r
993         goto Finish;\r
994       }\r
995       argc -= 2;\r
996       argv += 2;\r
997       continue; \r
998     }\r
999 \r
1000     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {\r
1001       CompressionName = argv[1];\r
1002       if (CompressionName == NULL) {\r
1003         Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");\r
1004         goto Finish;\r
1005       }\r
1006       argc -= 2;\r
1007       argv += 2;\r
1008       continue;\r
1009     }\r
1010 \r
1011     if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {\r
1012       Status = StringToGuid (argv[1], &VendorGuid);\r
1013       if (EFI_ERROR (Status)) {\r
1014         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1015         goto Finish;\r
1016       }\r
1017       argc -= 2;\r
1018       argv += 2;\r
1019       continue;\r
1020     }\r
1021 \r
1022     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {\r
1023       if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {\r
1024         SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
1025       } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {\r
1026         SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
1027       } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {\r
1028         //\r
1029         // NONE attribute\r
1030         //\r
1031         SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;\r
1032       } else {\r
1033         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1034         goto Finish;\r
1035       }\r
1036       argc -= 2;\r
1037       argv += 2;\r
1038       continue;\r
1039     }\r
1040 \r
1041     if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {\r
1042       Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);\r
1043       if (EFI_ERROR (Status)) {\r
1044         Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);\r
1045         goto Finish;\r
1046       }\r
1047       argc -= 2;\r
1048       argv += 2;\r
1049       continue;\r
1050     }\r
1051 \r
1052     if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {\r
1053       StringBuffer = argv[1];\r
1054       if (StringBuffer == NULL) {\r
1055         Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");\r
1056         goto Finish;\r
1057       }\r
1058       argc -= 2;\r
1059       argv += 2;\r
1060       continue;\r
1061     }\r
1062 \r
1063     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {\r
1064       if (argv[1] == NULL) {\r
1065         Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");\r
1066         goto Finish;\r
1067       }\r
1068       //\r
1069       // Verify string is a integrator number\r
1070       //\r
1071       for (Index = 0; Index < strlen (argv[1]); Index++) {\r
1072         if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {\r
1073           Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1074           goto Finish;\r
1075         }\r
1076       }\r
1077 \r
1078       sscanf (argv[1], "%d", &VersionNumber);\r
1079       argc -= 2;\r
1080       argv += 2;\r
1081       continue;\r
1082     }\r
1083 \r
1084     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
1085       SetPrintLevel (VERBOSE_LOG_LEVEL);\r
1086       VerboseMsg ("Verbose output Mode Set!");\r
1087       argc --;\r
1088       argv ++;\r
1089       continue;\r
1090     }\r
1091 \r
1092     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
1093       SetPrintLevel (KEY_LOG_LEVEL);\r
1094       KeyMsg ("Quiet output Mode Set!");\r
1095       argc --;\r
1096       argv ++;\r
1097       continue;\r
1098     }\r
1099 \r
1100     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
1101       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
1102       if (EFI_ERROR (Status)) {\r
1103         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1104         goto Finish;\r
1105       }\r
1106       if (LogLevel > 9) {\r
1107         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel);\r
1108         goto Finish;\r
1109       }\r
1110       SetPrintLevel (LogLevel);\r
1111       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
1112       argc -= 2;\r
1113       argv += 2;\r
1114       continue;\r
1115     }\r
1116 \r
1117     //\r
1118     // Section File alignment requirement\r
1119     //\r
1120     if (stricmp (argv[0], "--sectionalign") == 0) {\r
1121       if (InputFileAlignNum == 0) {\r
1122         InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
1123         if (InputFileAlign == NULL) {\r
1124           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1125           return 1;\r
1126         }\r
1127         memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
1128       } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1129         InputFileAlign = (UINT32 *) realloc (\r
1130           InputFileAlign,\r
1131           (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)\r
1132           );\r
1133 \r
1134         if (InputFileAlign == NULL) {\r
1135           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1136           return 1;\r
1137         }\r
1138         memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));\r
1139       }\r
1140       \r
1141       Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));\r
1142       if (EFI_ERROR (Status)) {\r
1143         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1144         goto Finish;\r
1145       }\r
1146       argc -= 2;\r
1147       argv += 2;\r
1148       InputFileAlignNum ++;\r
1149       continue; \r
1150     }\r
1151 \r
1152     //\r
1153     // Get Input file name\r
1154     //\r
1155     if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
1156       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
1157       if (InputFileName == NULL) {\r
1158         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1159         return 1;\r
1160       }\r
1161       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1162     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1163       //\r
1164       // InputFileName buffer too small, need to realloc\r
1165       //\r
1166       InputFileName = (CHAR8 **) realloc (\r
1167                                   InputFileName,\r
1168                                   (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
1169                                   );\r
1170 \r
1171       if (InputFileName == NULL) {\r
1172         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1173         return 1;\r
1174       }\r
1175       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1176     }\r
1177 \r
1178     InputFileName[InputFileNum++] = argv[0];\r
1179     argc --;\r
1180     argv ++;\r
1181   }\r
1182 \r
1183   if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {\r
1184     Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");\r
1185     goto Finish;\r
1186   }\r
1187 \r
1188   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
1189 \r
1190   //\r
1191   // Parse all command line parameters to get the corresponding section type.\r
1192   //\r
1193   VerboseMsg ("Section type is %s", SectionName);\r
1194   if (SectionName == NULL) {\r
1195     //\r
1196     // No specified Section type, default is SECTION_ALL.\r
1197     //\r
1198     SectType = EFI_SECTION_ALL;\r
1199   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {\r
1200     SectType     = EFI_SECTION_COMPRESSION;\r
1201     if (CompressionName == NULL) {\r
1202       //\r
1203       // Default is PI_STD compression algorithm.\r
1204       //\r
1205       SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1206     } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {\r
1207       SectCompSubType = EFI_NOT_COMPRESSED;\r
1208     } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {\r
1209       SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1210     } else {\r
1211       Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);\r
1212       goto Finish;\r
1213     }\r
1214     VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);\r
1215   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {\r
1216     SectType     = EFI_SECTION_GUID_DEFINED;\r
1217 \r
1218     if (CompareGuid (&VendorGuid, &mZeroGuid) == 0) {\r
1219       memcpy (&VendorGuid, &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
1220     }\r
1221     \r
1222     if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {\r
1223       //\r
1224       // NONE attribute, clear attribute value.\r
1225       //\r
1226       SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;\r
1227     }\r
1228     VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", \r
1229                 (unsigned) VendorGuid.Data1,\r
1230                 VendorGuid.Data2,\r
1231                 VendorGuid.Data3,\r
1232                 VendorGuid.Data4[0],\r
1233                 VendorGuid.Data4[1],\r
1234                 VendorGuid.Data4[2],\r
1235                 VendorGuid.Data4[3],\r
1236                 VendorGuid.Data4[4],\r
1237                 VendorGuid.Data4[5],\r
1238                 VendorGuid.Data4[6],\r
1239                 VendorGuid.Data4[7]);\r
1240     if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {\r
1241       VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);\r
1242     }\r
1243     if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {\r
1244       VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);\r
1245     }\r
1246     if (SectGuidHeaderLength != 0) {\r
1247       VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);\r
1248     }\r
1249   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {\r
1250     SectType = EFI_SECTION_PE32;\r
1251   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {\r
1252     SectType = EFI_SECTION_PIC;\r
1253   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {\r
1254     SectType = EFI_SECTION_TE;\r
1255   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {\r
1256     SectType = EFI_SECTION_DXE_DEPEX;\r
1257   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {\r
1258     SectType = EFI_SECTION_SMM_DEPEX;\r
1259   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {\r
1260     SectType = EFI_SECTION_VERSION;\r
1261     if (VersionNumber < 0 || VersionNumber > 9999) {\r
1262       Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~9999", VersionNumber);\r
1263       goto Finish;\r
1264     }\r
1265     VerboseMsg ("Version section number is %d", VersionNumber);\r
1266   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {\r
1267     SectType = EFI_SECTION_USER_INTERFACE;\r
1268     if (StringBuffer[0] == '\0') {\r
1269       Error (NULL, 0, 1001, "Missing option", "user interface string");\r
1270       goto Finish;\r
1271     }\r
1272     VerboseMsg ("UI section string name is %s", StringBuffer);\r
1273   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {\r
1274     SectType = EFI_SECTION_COMPATIBILITY16;\r
1275   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {\r
1276     SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
1277   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {\r
1278     SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;\r
1279   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {\r
1280     SectType = EFI_SECTION_RAW;\r
1281   } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {\r
1282     SectType = EFI_SECTION_PEI_DEPEX;\r
1283   } else {\r
1284     Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);\r
1285     goto Finish;\r
1286   }\r
1287   \r
1288   //\r
1289   // GuidValue is only required by Guided section.\r
1290   //\r
1291   if ((SectType != EFI_SECTION_GUID_DEFINED) && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
1292     fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);\r
1293   }\r
1294   \r
1295   //\r
1296   // Check whether there is input file\r
1297   //  \r
1298   if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {\r
1299     //\r
1300     // The input file are required for other section type.\r
1301     //\r
1302     if (InputFileNum == 0) {\r
1303       Error (NULL, 0, 1001, "Missing options", "Input files");\r
1304       goto Finish;\r
1305     }\r
1306   }\r
1307   //\r
1308   // Check whether there is output file\r
1309   //\r
1310   for (Index = 0; Index < InputFileNum; Index ++) {\r
1311     VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);\r
1312   }\r
1313   if (OutputFileName == NULL) {\r
1314     Error (NULL, 0, 1001, "Missing options", "Output file");\r
1315     goto Finish;\r
1316     // OutFile = stdout;\r
1317   }\r
1318   VerboseMsg ("Output file name is %s", OutputFileName);\r
1319 \r
1320   //\r
1321   // At this point, we've fully validated the command line, and opened appropriate\r
1322   // files, so let's go and do what we've been asked to do...\r
1323   //\r
1324   //\r
1325   // Within this switch, build and write out the section header including any\r
1326   // section type specific pieces.  If there's an input file, it's tacked on later\r
1327   //\r
1328   switch (SectType) {\r
1329   case EFI_SECTION_COMPRESSION:\r
1330     if (InputFileAlign != NULL) {\r
1331       free (InputFileAlign);\r
1332       InputFileAlign = NULL;\r
1333     }\r
1334     Status = GenSectionCompressionSection (\r
1335               InputFileName,\r
1336               InputFileAlign,\r
1337               InputFileNum,\r
1338               SectCompSubType,\r
1339               &OutFileBuffer\r
1340               );\r
1341     break;\r
1342 \r
1343   case EFI_SECTION_GUID_DEFINED:\r
1344     if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mEfiCrc32SectionGuid) != 0)) {\r
1345       //\r
1346       // Only process alignment for the default known CRC32 guided section.\r
1347       // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.\r
1348       //\r
1349       free (InputFileAlign);\r
1350       InputFileAlign = NULL;\r
1351     }\r
1352     Status = GenSectionGuidDefinedSection (\r
1353               InputFileName,\r
1354               InputFileAlign,\r
1355               InputFileNum,\r
1356               &VendorGuid,\r
1357               SectGuidAttribute,\r
1358               (UINT32) SectGuidHeaderLength,\r
1359               &OutFileBuffer\r
1360               );\r
1361     break;\r
1362 \r
1363   case EFI_SECTION_VERSION:\r
1364     Index           = sizeof (EFI_COMMON_SECTION_HEADER);\r
1365     //\r
1366     // 2 bytes for the build number UINT16\r
1367     //\r
1368     Index += 2;\r
1369     //\r
1370     // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1371     //\r
1372     Index += (strlen (StringBuffer) * 2) + 2;\r
1373     OutFileBuffer = (UINT8 *) malloc (Index);\r
1374     if (OutFileBuffer == NULL) {\r
1375       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1376       goto Finish;\r
1377     }\r
1378     VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;\r
1379     VersionSect->CommonHeader.Type     = SectType;\r
1380     VersionSect->CommonHeader.Size[0]  = (UINT8) (Index & 0xff);\r
1381     VersionSect->CommonHeader.Size[1]  = (UINT8) ((Index & 0xff00) >> 8);\r
1382     VersionSect->CommonHeader.Size[2]  = (UINT8) ((Index & 0xff0000) >> 16);\r
1383     VersionSect->BuildNumber           = (UINT16) VersionNumber;\r
1384     Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);\r
1385     VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
1386     break;\r
1387 \r
1388   case EFI_SECTION_USER_INTERFACE:\r
1389     Index           = sizeof (EFI_COMMON_SECTION_HEADER);\r
1390     //\r
1391     // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1392     //\r
1393     Index += (strlen (StringBuffer) * 2) + 2;\r
1394     OutFileBuffer = (UINT8 *) malloc (Index);\r
1395     if (OutFileBuffer == NULL) {\r
1396       Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1397       goto Finish;\r
1398     }\r
1399     UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;\r
1400     UiSect->CommonHeader.Type     = SectType;\r
1401     UiSect->CommonHeader.Size[0]  = (UINT8) (Index & 0xff);\r
1402     UiSect->CommonHeader.Size[1]  = (UINT8) ((Index & 0xff00) >> 8);\r
1403     UiSect->CommonHeader.Size[2]  = (UINT8) ((Index & 0xff0000) >> 16);\r
1404     Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);\r
1405     VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
1406    break;\r
1407 \r
1408   case EFI_SECTION_ALL:\r
1409     //\r
1410     // read all input file contents into a buffer\r
1411     // first get the size of all file contents\r
1412     //\r
1413     Status = GetSectionContents (\r
1414               InputFileName,\r
1415               InputFileAlign,\r
1416               InputFileNum,\r
1417               OutFileBuffer,\r
1418               &InputLength\r
1419               );\r
1420   \r
1421     if (Status == EFI_BUFFER_TOO_SMALL) {\r
1422       OutFileBuffer = (UINT8 *) malloc (InputLength);\r
1423       if (OutFileBuffer == NULL) {\r
1424         Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1425         goto Finish;\r
1426       }\r
1427       //\r
1428       // read all input file contents into a buffer\r
1429       //\r
1430       Status = GetSectionContents (\r
1431                 InputFileName,\r
1432                 InputFileAlign,\r
1433                 InputFileNum,\r
1434                 OutFileBuffer,\r
1435                 &InputLength\r
1436                 );\r
1437     }\r
1438     VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);\r
1439     break;\r
1440   default:\r
1441     //\r
1442     // All other section types are caught by default (they're all the same)\r
1443     //\r
1444     Status = GenSectionCommonLeafSection (\r
1445               InputFileName,\r
1446               InputFileNum,\r
1447               SectType,\r
1448               &OutFileBuffer\r
1449               );\r
1450     break;\r
1451   }\r
1452   \r
1453   if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {\r
1454     Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);\r
1455           goto Finish;\r
1456   }\r
1457 \r
1458   //\r
1459   // Get output file length\r
1460   //\r
1461   if (SectType != EFI_SECTION_ALL) {\r
1462     InputLength = SECTION_SIZE (OutFileBuffer);\r
1463   }\r
1464   \r
1465   //\r
1466   // Write the output file\r
1467   //\r
1468   OutFile = fopen (OutputFileName, "wb");\r
1469   if (OutFile == NULL) {\r
1470     Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);\r
1471     goto Finish;\r
1472   }\r
1473 \r
1474   fwrite (OutFileBuffer, InputLength, 1, OutFile);\r
1475 \r
1476 Finish:\r
1477   if (InputFileName != NULL) {\r
1478     free (InputFileName);\r
1479   }\r
1480 \r
1481   if (InputFileAlign != NULL) {\r
1482     free (InputFileAlign);\r
1483   }\r
1484 \r
1485   if (OutFileBuffer != NULL) {\r
1486     free (OutFileBuffer);\r
1487   }\r
1488 \r
1489   if (OutFile != NULL) {\r
1490     fclose (OutFile);\r
1491   }\r
1492   \r
1493   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
1494 \r
1495   return GetUtilityStatus ();\r
1496 }\r