Delete unused PrintLib and Move PeCoffLib into Common Library to clean up library...
[efi/basetools/.git] / Source / C / GenSec / GenSec.c
1 /*++\r
2 \r
3 Copyright (c) 2004, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14   GenSection.c\r
15 \r
16 Abstract:\r
17 \r
18   Creates output file that is a properly formed section per the FV spec.\r
19 \r
20 --*/\r
21 \r
22 #include <stdio.h>\r
23 #include <stdlib.h>\r
24 #include <string.h>\r
25 \r
26 #include <Common/UefiBaseTypes.h>\r
27 #include <Common/PiFirmwareFile.h>\r
28 #include <Protocol/GuidedSectionExtraction.h>\r
29 \r
30 #include "CommonLib.h"\r
31 #include "Compress.h"\r
32 #include "Crc32.h"\r
33 #include "EfiUtilityMsgs.h"\r
34 \r
35 //\r
36 // GenSec Tool Information\r
37 //\r
38 #define UTILITY_NAME            "GenSec"\r
39 #define UTILITY_MAJOR_VERSION   1\r
40 #define UTILITY_MINOR_VERSION   0\r
41 \r
42 #define MAXIMUM_INPUT_FILE_NUM  10\r
43 #define MAX_SECTION_SIZE        0x1000000\r
44 \r
45 CHAR8      *SectionTypeName[] = {\r
46   NULL,                                 // 0x00 - reserved\r
47   "EFI_SECTION_COMPRESSION",            // 0x01\r
48   "EFI_SECTION_GUID_DEFINED",           // 0x02\r
49   NULL,                                 // 0x03 - reserved\r
50   NULL,                                 // 0x04 - reserved\r
51   NULL,                                 // 0x05 - reserved\r
52   NULL,                                 // 0x06 - reserved\r
53   NULL,                                 // 0x07 - reserved\r
54   NULL,                                 // 0x08 - reserved\r
55   NULL,                                 // 0x09 - reserved\r
56   NULL,                                 // 0x0A - reserved\r
57   NULL,                                 // 0x0B - reserved\r
58   NULL,                                 // 0x0C - reserved\r
59   NULL,                                 // 0x0D - reserved\r
60   NULL,                                 // 0x0E - reserved\r
61   NULL,                                 // 0x0F - reserved\r
62   "EFI_SECTION_PE32",                   // 0x10\r
63   "EFI_SECTION_PIC",                    // 0x11\r
64   "EFI_SECTION_TE",                     // 0x12\r
65   "EFI_SECTION_DXE_DEPEX",              // 0x13\r
66   "EFI_SECTION_VERSION",                // 0x14\r
67   "EFI_SECTION_USER_INTERFACE",         // 0x15\r
68   "EFI_SECTION_COMPATIBILITY16",        // 0x16\r
69   "EFI_SECTION_FIRMWARE_VOLUME_IMAGE",  // 0x17\r
70   "EFI_SECTION_FREEFORM_SUBTYPE_GUID",  // 0x18\r
71   "EFI_SECTION_RAW",                    // 0x19\r
72   NULL,                                 // 0x1A\r
73   "EFI_SECTION_PEI_DEPEX"               // 0x1B\r
74 };\r
75 \r
76 CHAR8      *CompressionTypeName[]    = { "PI_NONE", "PI_STD" };\r
77 CHAR8      *GUIDedSectionAttribue[]  = { NULL, "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};\r
78 \r
79 //\r
80 // Crc32 GUID section related definitions.\r
81 //\r
82 typedef struct {\r
83   EFI_GUID_DEFINED_SECTION  GuidSectionHeader;\r
84   UINT32                    CRC32Checksum;\r
85 } CRC32_SECTION_HEADER;\r
86 \r
87 EFI_GUID  gZeroGuid                 = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
88 EFI_GUID  gEfiCrc32SectionGuid      = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;\r
89 \r
90 STATIC\r
91 VOID \r
92 Version(\r
93   VOID\r
94   )\r
95 /*++\r
96 \r
97 Routine Description:\r
98 \r
99   Print out version information for this utility.\r
100 \r
101 Arguments:\r
102 \r
103   None\r
104   \r
105 Returns:\r
106 \r
107   None\r
108   \r
109 --*/ \r
110 {\r
111   printf ("%s v%d.%d - EDKII Utility to create output file with formed section per the PI spec.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
112   printf ("Copyright (c) 2007 Intel Corporation. All rights reserved.\n");\r
113 }\r
114 \r
115 STATIC\r
116 VOID\r
117 Usage (\r
118   VOID\r
119   )\r
120 {\r
121   Version();\r
122 \r
123   printf ("\nUsage: " UTILITY_NAME " [inputfilename]\n\\r
124         -o, --outputfile [FileName]\n\\r
125         -s, --SectionType <EFI_SECTION_COMPRESSION|\n\\r
126                           EFI_SECTION_GUID_DEFINED|\n\\r
127                           EFI_SECTION_PE32|\n\\r
128                           EFI_SECTION_PIC|\n\\r
129                           EFI_SECTION_TE|\n\\r
130                           EFI_SECTION_DXE_DEPEX|\n\\r
131                           EFI_SECTION_VERSION|\n\\r
132                           EFI_SECTION_USER_INTERFACE|\n\\r
133                           EFI_SECTION_COMPATIBILITY16|\n\\r
134                           EFI_SECTION_FIRMWARE_VOLUME_IMAGE|\n\\r
135                           EFI_SECTION_FREEFORM_SUBTYPE_GUID|\n\\r
136                           EFI_SECTION_RAW|\n\\r
137                           EFI_SECTION_PEI_DEPEX>\n\\r
138         -c, --compress <PI_NONE|PI_STD>\n\\r
139         -g, --vendorguid [GuidValue (########-####-####-####-############)]\n\\r
140         -r, --attributes <PROCESSING_REQUIRED|AUTH_STATUS_VALID>\n\\r
141         -n, --name \"string\"\n\\r
142         -j, --buildnumber #### (0000~9999)\n\\r
143         -h, --help\n\\r
144         -V, --version\n");\r
145 }\r
146 \r
147 VOID\r
148 Ascii2UnicodeWriteString (\r
149   CHAR8    *String,\r
150   FILE     *OutFile\r
151   )\r
152 {\r
153   UINT32 Index;\r
154   UINT8  AsciiNull;\r
155 \r
156   AsciiNull = 0;\r
157 \r
158   //\r
159   // Next, write out the string... Convert ASCII to Unicode in the process.\r
160   //\r
161   Index = 0;\r
162   do {\r
163     fwrite (&String[Index], 1, 1, OutFile);\r
164     fwrite (&AsciiNull, 1, 1, OutFile);\r
165   } while (String[Index++] != 0);\r
166 }\r
167 \r
168 STATUS\r
169 GenSectionCommonLeafSection (\r
170   CHAR8   **InputFileName,\r
171   UINT32  InputFileNum,\r
172   UINT8   SectionType,\r
173   FILE    *OutFile\r
174   )\r
175 /*++\r
176         \r
177 Routine Description:\r
178            \r
179   Generate a leaf section of type other than EFI_SECTION_VERSION\r
180   and EFI_SECTION_USER_INTERFACE. Input file must be well formed.\r
181   The function won't validate the input file's contents. For\r
182   common leaf sections, the input file may be a binary file.\r
183   The utility will add section header to the file.\r
184             \r
185 Arguments:\r
186                \r
187   InputFileName  - Name of the input file.\r
188                 \r
189   InputFileNum   - Number of input files. Should be 1 for leaf section.\r
190 \r
191   SectionType    - A valid section type string\r
192 \r
193   OutFile        - Output file handle\r
194 \r
195 Returns:\r
196                        \r
197   STATUS_ERROR            - can't continue\r
198   STATUS_SUCCESS          - successful return\r
199 \r
200 --*/\r
201 {\r
202   UINT32                    InputFileLength;\r
203   FILE                      *InFile;\r
204   UINT8                     *Buffer;\r
205   UINT32                    TotalLength;\r
206   EFI_COMMON_SECTION_HEADER CommonSect;\r
207   STATUS                    Status;\r
208 \r
209   if (InputFileNum > 1) {\r
210     Error (NULL, 0, 0, "invalid parameter", "more than one input file specified");\r
211     return STATUS_ERROR;\r
212   } else if (InputFileNum < 1) {\r
213     Error (NULL, 0, 0, "no input file specified", NULL);\r
214     return STATUS_ERROR;\r
215   }\r
216   //\r
217   // Open the input file\r
218   //\r
219   InFile = fopen (InputFileName[0], "rb");\r
220   if (InFile == NULL) {\r
221     Error (NULL, 0, 0, InputFileName[0], "failed to open input file");\r
222     return STATUS_ERROR;\r
223   }\r
224 \r
225   Status  = STATUS_ERROR;\r
226   Buffer  = NULL;\r
227   //\r
228   // Seek to the end of the input file so we can determine its size\r
229   //\r
230   fseek (InFile, 0, SEEK_END);\r
231   InputFileLength = ftell (InFile);\r
232   fseek (InFile, 0, SEEK_SET);\r
233   //\r
234   // Fill in the fields in the local section header structure\r
235   //\r
236   CommonSect.Type = (EFI_SECTION_TYPE) SectionType;\r
237   TotalLength     = sizeof (CommonSect) + InputFileLength;\r
238   //\r
239   // Size must fit in 3 bytes\r
240   //\r
241   if (TotalLength >= MAX_SECTION_SIZE) {\r
242     Error (NULL, 0, 0, InputFileName[0], "file size (0x%X) exceeds section size limit(%dM).", TotalLength, MAX_SECTION_SIZE>>20);\r
243     goto Done;\r
244   }\r
245   //\r
246   // Now copy the size into the section header and write out the section header\r
247   //\r
248   memcpy (&CommonSect.Size, &TotalLength, 3);\r
249   fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);\r
250   //\r
251   // Allocate a buffer to read in the contents of the input file. Then\r
252   // read it in as one block and write it to the output file.\r
253   //\r
254   if (InputFileLength != 0) {\r
255     Buffer = (UINT8 *) malloc ((size_t) InputFileLength);\r
256     if (Buffer == NULL) {\r
257       Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
258       goto Done;\r
259     }\r
260 \r
261     if (fread (Buffer, (size_t) InputFileLength, 1, InFile) != 1) {\r
262       Error (NULL, 0, 0, InputFileName[0], "failed to read contents of file");\r
263       goto Done;\r
264     }\r
265 \r
266     if (fwrite (Buffer, (size_t) InputFileLength, 1, OutFile) != 1) {\r
267       Error (NULL, 0, 0, "failed to write to output file", NULL);\r
268       goto Done;\r
269     }\r
270   }\r
271 \r
272   Status = STATUS_SUCCESS;\r
273 \r
274 Done:\r
275   fclose (InFile);\r
276   if (Buffer != NULL) {\r
277     free (Buffer);\r
278   }\r
279 \r
280   return Status;\r
281 }\r
282 \r
283 EFI_STATUS\r
284 GetSectionContents (\r
285   CHAR8   **InputFileName,\r
286   UINT32  InputFileNum,\r
287   UINT8   *FileBuffer,\r
288   UINT32  *BufferLength\r
289   )\r
290 /*++\r
291         \r
292 Routine Description:\r
293            \r
294   Get the contents of all section files specified in InputFileName\r
295   into FileBuffer.\r
296             \r
297 Arguments:\r
298                \r
299   InputFileName  - Name of the input file.\r
300                 \r
301   InputFileNum   - Number of input files. Should be at least 1.\r
302 \r
303   FileBuffer     - Output buffer to contain data\r
304 \r
305   BufferLength   - On input, this is size of the FileBuffer. \r
306                    On output, this is the actual length of the data.\r
307 \r
308 Returns:\r
309                        \r
310   EFI_SUCCESS on successful return\r
311   EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.\r
312   EFI_ABORTED if unable to open input file.\r
313   EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.\r
314 --*/\r
315 {\r
316   UINT32   Size;\r
317   UINT32   FileSize;\r
318   UINT32   Index;\r
319   FILE    *InFile;\r
320 \r
321   if (InputFileNum < 1) {\r
322     Error (NULL, 0, 0, "must specify at least one input file", NULL);\r
323     return EFI_INVALID_PARAMETER;\r
324   }\r
325 \r
326   if (BufferLength == NULL) {\r
327     Error (NULL, 0, 0, "BufferLength can't be NULL", NULL);\r
328     return EFI_INVALID_PARAMETER;\r
329   }\r
330 \r
331   Size = 0;\r
332   //\r
333   // Go through our array of file names and copy their contents\r
334   // to the output buffer.\r
335   //\r
336   for (Index = 0; Index < InputFileNum; Index++) {\r
337     //\r
338     // make sure section ends on a DWORD boundary\r
339     //\r
340     while ((Size & 0x03) != 0) {\r
341       if (FileBuffer != NULL && Size < *BufferLength) {\r
342         FileBuffer[Size] = 0;\r
343       }\r
344       Size++;\r
345     }\r
346     \r
347     // \r
348     // Open file and read contents\r
349     //\r
350     InFile = fopen (InputFileName[Index], "rb");\r
351     if (InFile == NULL) {\r
352       Error (NULL, 0, 0, InputFileName[Index], "failed to open input file");\r
353       return EFI_ABORTED;\r
354     }\r
355 \r
356     fseek (InFile, 0, SEEK_END);\r
357     FileSize = ftell (InFile);\r
358     fseek (InFile, 0, SEEK_SET);\r
359     //\r
360     // Now read the contents of the file into the buffer\r
361     // Buffer must be enough to contain the file content.\r
362     //\r
363     if (FileSize > 0 && FileBuffer != NULL && (Size + FileSize) <= *BufferLength) {\r
364       if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {\r
365         Error (NULL, 0, 0, InputFileName[Index], "failed to read contents of input file");\r
366         fclose (InFile);\r
367         return EFI_ABORTED;\r
368       }\r
369     }\r
370 \r
371     fclose (InFile);\r
372     Size += FileSize;\r
373   }\r
374   \r
375   if (Size > *BufferLength) {\r
376     *BufferLength = Size;\r
377     return EFI_BUFFER_TOO_SMALL;\r
378   } else {\r
379     *BufferLength = Size;\r
380     return EFI_SUCCESS;\r
381   }\r
382 }\r
383 \r
384 EFI_STATUS\r
385 GenSectionCompressionSection (\r
386   CHAR8    **InputFileName,\r
387   UINT32  InputFileNum,\r
388   UINT8   SectCompSubType,\r
389   FILE    *OutFile\r
390   )\r
391 /*++\r
392         \r
393 Routine Description:\r
394            \r
395   Generate an encapsulating section of type EFI_SECTION_COMPRESSION\r
396   Input file must be already sectioned. The function won't validate\r
397   the input files' contents. Caller should hand in files already \r
398   with section header.\r
399             \r
400 Arguments:\r
401                \r
402   InputFileName  - Name of the input file.\r
403                 \r
404   InputFileNum   - Number of input files. Should be at least 1.\r
405 \r
406   SectCompSubType - Specify the compression algorithm requested. \r
407   \r
408   OutFile        - Output file handle\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\r
414   EFI_ABORTED           if unable to open input file.\r
415   EFI_OUT_OF_RESOURCES  No resource to complete the operation.\r
416 --*/\r
417 {\r
418   UINT32                  TotalLength;\r
419   UINT32                  InputLength;\r
420   UINT32                  CompressedLength;\r
421   UINT8                   *FileBuffer;\r
422   UINT8                   *OutputBuffer;\r
423   EFI_STATUS              Status;\r
424   EFI_COMPRESSION_SECTION CompressionSect;\r
425   COMPRESS_FUNCTION       CompressFunction;\r
426 \r
427   InputLength       = 0;\r
428   FileBuffer        = NULL;\r
429   OutputBuffer      = NULL;\r
430   CompressedLength  = 0;\r
431   //\r
432   // read all input file contents into a buffer\r
433   // first get the size of all file contents\r
434   //\r
435   Status = GetSectionContents (\r
436             InputFileName,\r
437             InputFileNum,\r
438             FileBuffer,\r
439             &InputLength\r
440             );\r
441 \r
442   if (Status == EFI_BUFFER_TOO_SMALL) {\r
443     FileBuffer = (UINT8 *) malloc (InputLength);\r
444     if (FileBuffer == NULL) {\r
445       Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
446       return EFI_OUT_OF_RESOURCES;\r
447     }\r
448     //\r
449     // read all input file contents into a buffer\r
450     //\r
451     Status = GetSectionContents (\r
452               InputFileName,\r
453               InputFileNum,\r
454               FileBuffer,\r
455               &InputLength\r
456               );\r
457   }\r
458 \r
459   if (EFI_ERROR (Status)) {\r
460     if (FileBuffer != NULL) {\r
461       free (FileBuffer);\r
462     }\r
463     return Status;\r
464   }\r
465 \r
466   CompressFunction = NULL;\r
467 \r
468   //\r
469   // Now data is in FileBuffer, compress the data\r
470   //\r
471   switch (SectCompSubType) {\r
472   case EFI_NOT_COMPRESSED:\r
473     CompressedLength = InputLength;\r
474     break;\r
475 \r
476   case EFI_STANDARD_COMPRESSION:\r
477     CompressFunction = (COMPRESS_FUNCTION) EfiCompress;\r
478     break;\r
479 \r
480   default:\r
481     Error (NULL, 0, 0, "unknown compression type", NULL);\r
482     free (FileBuffer);\r
483     return EFI_ABORTED;\r
484   }\r
485 \r
486   if (CompressFunction != NULL) {\r
487 \r
488     Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);\r
489     if (Status == EFI_BUFFER_TOO_SMALL) {\r
490       OutputBuffer = malloc (CompressedLength);\r
491       if (!OutputBuffer) {\r
492         free (FileBuffer);\r
493         return EFI_OUT_OF_RESOURCES;\r
494       }\r
495 \r
496       Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);\r
497     }\r
498 \r
499     free (FileBuffer);\r
500     FileBuffer = OutputBuffer;\r
501 \r
502     if (EFI_ERROR (Status)) {\r
503       if (FileBuffer != NULL) {\r
504         free (FileBuffer);\r
505       }\r
506 \r
507       return Status;\r
508     }\r
509   }\r
510 \r
511   TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);\r
512   if (TotalLength >= MAX_SECTION_SIZE) {\r
513     Error (__FILE__, __LINE__, 0, "input error", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);\r
514     if (FileBuffer != NULL) {\r
515       free (FileBuffer);\r
516     }\r
517     if (OutputBuffer != NULL) {\r
518       free (OutputBuffer);\r
519     }\r
520     return STATUS_ERROR;\r
521   }\r
522 \r
523   //\r
524   // Add the section header for the compressed data\r
525   //\r
526   CompressionSect.CommonHeader.Type     = EFI_SECTION_COMPRESSION;\r
527   CompressionSect.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
528   CompressionSect.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
529   CompressionSect.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
530   CompressionSect.CompressionType       = SectCompSubType;\r
531   CompressionSect.UncompressedLength    = InputLength;\r
532 \r
533   fwrite (&CompressionSect, sizeof (CompressionSect), 1, OutFile);\r
534   fwrite (FileBuffer, CompressedLength, 1, OutFile);\r
535   free (FileBuffer);\r
536   return EFI_SUCCESS;\r
537 }\r
538 \r
539 EFI_STATUS\r
540 GenSectionGuidDefinedSection (\r
541   CHAR8    **InputFileName,\r
542   UINT32   InputFileNum,\r
543   EFI_GUID *VendorGuid,\r
544   UINT16   DataAttribute,\r
545   FILE     *OutFile\r
546   )\r
547 /*++\r
548         \r
549 Routine Description:\r
550            \r
551   Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED\r
552   Input file must be already sectioned. The function won't validate\r
553   the input files' contents. Caller should hand in files already \r
554   with section header.\r
555             \r
556 Arguments:\r
557                \r
558   InputFileName - Name of the input file.\r
559                 \r
560   InputFileNum  - Number of input files. Should be at least 1.\r
561 \r
562   VendorGuid    - Specify vendor guid value.\r
563 \r
564   DataAttribute - Specify attribute for the vendor guid data. \r
565   \r
566   OutFile       - Output file handle\r
567 \r
568 Returns:\r
569                        \r
570   EFI_SUCCESS on successful return\r
571   EFI_INVALID_PARAMETER if InputFileNum is less than 1\r
572   EFI_ABORTED if unable to open input file.\r
573   EFI_OUT_OF_RESOURCES  No resource to complete the operation.\r
574 \r
575 --*/\r
576 {\r
577   UINT32                TotalLength;\r
578   UINT32                InputLength;\r
579   UINT8                 *FileBuffer;\r
580   UINT32                Crc32Checksum;\r
581   EFI_STATUS            Status;\r
582   CRC32_SECTION_HEADER  Crc32GuidSect;\r
583   EFI_GUID_DEFINED_SECTION  VendorGuidSect;\r
584 \r
585   InputLength = 0;\r
586   FileBuffer  = NULL;\r
587   //\r
588   // read all input file contents into a buffer\r
589   // first get the size of all file contents\r
590   //\r
591   Status = GetSectionContents (\r
592             InputFileName,\r
593             InputFileNum,\r
594             FileBuffer,\r
595             &InputLength\r
596             );\r
597 \r
598   if (Status == EFI_BUFFER_TOO_SMALL) {\r
599     FileBuffer = (UINT8 *) malloc (InputLength);\r
600     if (FileBuffer == NULL) {\r
601       Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
602       return EFI_OUT_OF_RESOURCES;\r
603     }\r
604     //\r
605     // read all input file contents into a buffer\r
606     //\r
607     Status = GetSectionContents (\r
608               InputFileName,\r
609               InputFileNum,\r
610               FileBuffer,\r
611               &InputLength\r
612               );\r
613   }\r
614 \r
615   if (EFI_ERROR (Status)) {\r
616     if (FileBuffer != NULL) {\r
617       free (FileBuffer);\r
618     }\r
619     return Status;\r
620   }\r
621 \r
622   //\r
623   // Now data is in FileBuffer\r
624   //\r
625   if (CompareGuid (VendorGuid, &gEfiCrc32SectionGuid) == 0) {\r
626     //\r
627     // Default Guid section is CRC32.\r
628     //\r
629     Crc32Checksum = 0;\r
630     CalculateCrc32 (FileBuffer, InputLength, &Crc32Checksum);\r
631 \r
632     TotalLength = InputLength + sizeof (CRC32_SECTION_HEADER);\r
633     if (TotalLength >= MAX_SECTION_SIZE) {\r
634       Error (__FILE__, __LINE__, 0, "input error", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);\r
635       free (FileBuffer);\r
636       return STATUS_ERROR;\r
637     }\r
638 \r
639     Crc32GuidSect.GuidSectionHeader.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
640     Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
641     Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
642     Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
643     memcpy (&(Crc32GuidSect.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
644     Crc32GuidSect.GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
645     Crc32GuidSect.GuidSectionHeader.DataOffset  = sizeof (CRC32_SECTION_HEADER);\r
646     Crc32GuidSect.CRC32Checksum                 = Crc32Checksum;\r
647     fwrite (&Crc32GuidSect, sizeof (Crc32GuidSect), 1, OutFile);  \r
648 \r
649   } else {\r
650     TotalLength = InputLength + sizeof (EFI_GUID_DEFINED_SECTION);\r
651     if (TotalLength >= MAX_SECTION_SIZE) {\r
652       Error (__FILE__, __LINE__, 0, "input error", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20);\r
653       free (FileBuffer);\r
654       return STATUS_ERROR;\r
655     }\r
656 \r
657     VendorGuidSect.CommonHeader.Type     = EFI_SECTION_GUID_DEFINED;\r
658     VendorGuidSect.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);\r
659     VendorGuidSect.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);\r
660     VendorGuidSect.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
661     memcpy (&(VendorGuidSect.SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));\r
662     VendorGuidSect.Attributes  = DataAttribute;\r
663     VendorGuidSect.DataOffset  = sizeof (EFI_GUID_DEFINED_SECTION);\r
664     fwrite (&VendorGuidSect, sizeof (EFI_GUID_DEFINED_SECTION), 1, OutFile);  \r
665   }\r
666 \r
667   fwrite (FileBuffer, InputLength, 1, OutFile);\r
668   free (FileBuffer);\r
669 \r
670   return EFI_SUCCESS;\r
671 }\r
672 \r
673 int\r
674 main (\r
675   int  argc,\r
676   char *argv[]\r
677   )\r
678 /*++\r
679 \r
680 Routine Description:\r
681 \r
682   Main\r
683 \r
684 Arguments:\r
685 \r
686   command line parameters\r
687 \r
688 Returns:\r
689 \r
690   EFI_SUCCESS    Section header successfully generated and section concatenated.\r
691   EFI_ABORTED    Could not generate the section\r
692   EFI_OUT_OF_RESOURCES  No resource to complete the operation.\r
693 \r
694 --*/\r
695 {\r
696   UINT32                    Index;\r
697   UINT32                    InputFileNum;\r
698   FILE                      *InFile;\r
699   FILE                      *OutFile;\r
700   CHAR8                     **InputFileName;\r
701   CHAR8                     *OutputFileName;\r
702   CHAR8                     *SectionName;\r
703   CHAR8                     *CompressionName;\r
704   CHAR8                     *StringBuffer;\r
705   EFI_GUID                  VendorGuid = gZeroGuid;\r
706   INT32                     VersionNumber;\r
707   UINT8                     SectType;\r
708   UINT8                     SectCompSubType;\r
709   UINT16                    SectGuidAttribute; \r
710   EFI_COMMON_SECTION_HEADER CommonSect;\r
711   UINT32                    InputLength;\r
712   UINT8                     *FileBuffer;\r
713   EFI_STATUS                Status;\r
714  \r
715   fprintf (stdout, "GenSec tool start.\n");  \r
716   \r
717   InputFileName         = NULL;\r
718   OutputFileName        = NULL;\r
719   SectionName           = NULL;\r
720   CompressionName       = NULL;\r
721   StringBuffer          = "";\r
722 \r
723   InFile                = NULL;\r
724   OutFile               = NULL;\r
725   VersionNumber         = 0;\r
726   InputFileNum          = 0;\r
727   SectType              = EFI_SECTION_ALL;\r
728   SectCompSubType       = 0;\r
729   SectGuidAttribute     = 0;\r
730   FileBuffer            = NULL;\r
731   InputLength           = 0;\r
732   Status                = STATUS_SUCCESS;\r
733   \r
734 \r
735   SetUtilityName (UTILITY_NAME);\r
736   \r
737   if (argc == 1) {\r
738     Usage ();\r
739     return STATUS_ERROR;\r
740   }\r
741 \r
742   //\r
743   // Parse command line\r
744   //\r
745   argc --;\r
746   argv ++;\r
747 \r
748   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
749     Usage();\r
750     return STATUS_ERROR;    \r
751   }\r
752 \r
753   if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--version") == 0)) {\r
754     Version();\r
755     return STATUS_ERROR;    \r
756   }\r
757 \r
758   while (argc > 0) {\r
759     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {\r
760       SectionName = argv[1];\r
761       argc -= 2;\r
762       argv += 2;\r
763       continue; \r
764     }\r
765 \r
766     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
767       OutputFileName = argv[1];\r
768       argc -= 2;\r
769       argv += 2;\r
770       continue; \r
771     }\r
772 \r
773     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {\r
774       CompressionName = argv[1];\r
775       argc -= 2;\r
776       argv += 2;\r
777       continue;\r
778     }\r
779 \r
780     if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendorguid") == 0)) {\r
781       Status = StringToGuid (argv[1], &VendorGuid);\r
782       if (EFI_ERROR (Status)) {\r
783         Error (NULL, 0, 0, NULL, "ERROR: %s is not a formal GUID value.", argv[1]);\r
784         goto Finish;\r
785       }\r
786       argc -= 2;\r
787       argv += 2;\r
788       continue;\r
789     }\r
790 \r
791     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {\r
792       if (stricmp (argv[1], GUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {\r
793         SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
794       } else if (stricmp (argv[1], GUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {\r
795         SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
796       } else {\r
797         Error (NULL, 0, 0, argv[1], "unknown Guid Section Attribute");\r
798         goto Finish;\r
799       }\r
800       argc -= 2;\r
801       argv += 2;\r
802       continue;\r
803     }\r
804 \r
805     if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {\r
806       StringBuffer = argv[1];\r
807       argc -= 2;\r
808       argv += 2;\r
809       continue;\r
810     }\r
811 \r
812     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {\r
813       //\r
814       // Verify string is a integrator number\r
815       //\r
816       for (Index = 0; Index < strlen (argv[1]); Index++) {\r
817         if ((argv[1][Index] != '-') && (isdigit (argv[1][Index]) == 0)) {\r
818           Error (NULL, 0, 0, NULL, "ERROR: %s is not a valid integer.", argv[1]);\r
819           goto Finish;\r
820         }\r
821       }\r
822 \r
823       sscanf (argv[1], "%d", &VersionNumber);\r
824       argc -= 2;\r
825       argv += 2;\r
826       continue;\r
827     }\r
828 \r
829     //\r
830     // Get Input file name\r
831     //\r
832     if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
833       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
834       if (InputFileName == NULL) {\r
835         Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
836         return EFI_OUT_OF_RESOURCES;\r
837       }\r
838 \r
839       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
840     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
841       //\r
842       // InputFileName buffer too small, need to realloc\r
843       //\r
844       InputFileName = (CHAR8 **) realloc (\r
845                                   InputFileName,\r
846                                   (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
847                                   );\r
848 \r
849       if (InputFileName == NULL) {\r
850         Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
851         return EFI_OUT_OF_RESOURCES;\r
852       }\r
853 \r
854       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
855     }\r
856 \r
857     InputFileName[InputFileNum++] = argv[0];\r
858     argc --;\r
859     argv ++;\r
860   }\r
861 \r
862   //\r
863   // Parse all command line parameters to get the corresponding section type.\r
864   //\r
865   if (SectionName == NULL) {\r
866     //\r
867     // No specified Section type, default is SECTION_ALL.\r
868     //\r
869     SectType = EFI_SECTION_ALL;\r
870   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {\r
871     SectType     = EFI_SECTION_COMPRESSION;\r
872     if (CompressionName == NULL) {\r
873       //\r
874       // Default is PI_STD compression algorithm.\r
875       //\r
876       SectCompSubType = EFI_STANDARD_COMPRESSION;\r
877     } else if (stricmp (CompressionName, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {\r
878       SectCompSubType = EFI_NOT_COMPRESSED;\r
879     } else if (stricmp (CompressionName, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {\r
880       SectCompSubType = EFI_STANDARD_COMPRESSION;\r
881     } else {\r
882       Error (NULL, 0, 0, CompressionName, "unknown compression type");\r
883       goto Finish;\r
884     }\r
885   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {\r
886     SectType     = EFI_SECTION_GUID_DEFINED;\r
887 \r
888     if (CompareGuid (&VendorGuid, &gZeroGuid) == 0) {\r
889       memcpy (&VendorGuid, &gEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
890     }\r
891     \r
892     if (SectGuidAttribute == 0) {\r
893       SectGuidAttribute = EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
894     }\r
895   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_PE32]) == 0) {\r
896     SectType = EFI_SECTION_PE32;\r
897   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_PIC]) == 0) {\r
898     SectType = EFI_SECTION_PIC;\r
899   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_TE]) == 0) {\r
900     SectType = EFI_SECTION_TE;\r
901   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {\r
902     SectType = EFI_SECTION_DXE_DEPEX;\r
903   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_VERSION]) == 0) {\r
904     SectType = EFI_SECTION_VERSION;\r
905     if (VersionNumber < 0 || VersionNumber > 9999) {\r
906       Error (NULL, 0, 0, NULL, "%d is illegal version number\n", VersionNumber);\r
907       goto Finish;\r
908     }\r
909   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {\r
910     SectType = EFI_SECTION_USER_INTERFACE;\r
911     if (StringBuffer[0] == '\0') {\r
912       Error (NULL, 0, 0, "user interface string not specified", NULL);\r
913       goto Finish;\r
914     }\r
915   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {\r
916     SectType = EFI_SECTION_COMPATIBILITY16;\r
917   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {\r
918     SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
919   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {\r
920     SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;\r
921   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_RAW]) == 0) {\r
922     SectType = EFI_SECTION_RAW;\r
923   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {\r
924     SectType = EFI_SECTION_PEI_DEPEX;\r
925   } else {\r
926     Error (NULL, 0, 0, SectionName, "unknown section type");\r
927     goto Finish;\r
928   }\r
929   \r
930   if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {\r
931     //\r
932     // The input file are required for those section type.\r
933     //\r
934     if (InputFileNum == 0) {\r
935       Error (NULL, 0, 0, NULL, "No input files is specified.");\r
936       goto Finish;\r
937     }\r
938   }\r
939   \r
940   //\r
941   // Open output file\r
942   //\r
943   if (OutputFileName == NULL) {\r
944     Error (NULL, 0, 0, NULL, "No output file name is specified.");\r
945     goto Finish;\r
946     // OutFile = stdout;\r
947   } else {\r
948     OutFile = fopen (OutputFileName, "wb");\r
949   }\r
950 \r
951   if (OutFile == NULL) {\r
952     Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");\r
953     goto Finish;\r
954   }\r
955   \r
956   //\r
957   // At this point, we've fully validated the command line, and opened appropriate\r
958   // files, so let's go and do what we've been asked to do...\r
959   //\r
960   //\r
961   // Within this switch, build and write out the section header including any\r
962   // section type specific pieces.  If there's an input file, it's tacked on later\r
963   //\r
964   switch (SectType) {\r
965   case EFI_SECTION_COMPRESSION:\r
966     Status = GenSectionCompressionSection (\r
967               InputFileName,\r
968               InputFileNum,\r
969               SectCompSubType,\r
970               OutFile\r
971               );\r
972     break;\r
973 \r
974   case EFI_SECTION_GUID_DEFINED:\r
975     Status = GenSectionGuidDefinedSection (\r
976               InputFileName,\r
977               InputFileNum,\r
978               &VendorGuid,\r
979               SectGuidAttribute,\r
980               OutFile\r
981               );\r
982     break;\r
983 \r
984   case EFI_SECTION_VERSION:\r
985     CommonSect.Type = (EFI_SECTION_TYPE) SectType;\r
986 \r
987     Index           = sizeof (CommonSect);\r
988     //\r
989     // 2 bytes for the build number UINT16\r
990     //\r
991     Index += 2;\r
992     //\r
993     // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
994     //\r
995     Index += (strlen (StringBuffer) * 2) + 2;\r
996     memcpy (&CommonSect.Size, &Index, 3);\r
997     fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);\r
998     fwrite (&VersionNumber, sizeof (UINT16), 1, OutFile);\r
999     Ascii2UnicodeWriteString (StringBuffer, OutFile);\r
1000     break;\r
1001 \r
1002   case EFI_SECTION_USER_INTERFACE:\r
1003     CommonSect.Type = (EFI_SECTION_TYPE) SectType;\r
1004     Index           = sizeof (CommonSect);\r
1005     //\r
1006     // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1007     //\r
1008     Index += (strlen (StringBuffer) * 2) + 2;\r
1009     memcpy (&CommonSect.Size, &Index, 3);\r
1010     fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);\r
1011     Ascii2UnicodeWriteString (StringBuffer, OutFile);\r
1012     break;\r
1013 \r
1014   case EFI_SECTION_ALL:\r
1015     //\r
1016     // read all input file contents into a buffer\r
1017     // first get the size of all file contents\r
1018     //\r
1019     Status = GetSectionContents (\r
1020               InputFileName,\r
1021               InputFileNum,\r
1022               FileBuffer,\r
1023               &InputLength\r
1024               );\r
1025   \r
1026     if (Status == EFI_BUFFER_TOO_SMALL) {\r
1027       FileBuffer = (UINT8 *) malloc (InputLength);\r
1028       if (FileBuffer == NULL) {\r
1029         Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
1030         goto Finish;\r
1031       }\r
1032       //\r
1033       // read all input file contents into a buffer\r
1034       //\r
1035       Status = GetSectionContents (\r
1036                 InputFileName,\r
1037                 InputFileNum,\r
1038                 FileBuffer,\r
1039                 &InputLength\r
1040                 );\r
1041     }\r
1042   \r
1043     if (Status == EFI_SUCCESS) {\r
1044       fwrite (FileBuffer, InputLength, 1, OutFile);\r
1045     }\r
1046 \r
1047     if (FileBuffer != NULL) {\r
1048       free (FileBuffer);\r
1049     }\r
1050     \r
1051     break;\r
1052   default:\r
1053     //\r
1054     // All other section types are caught by default (they're all the same)\r
1055     //\r
1056     Status = GenSectionCommonLeafSection (\r
1057               InputFileName,\r
1058               InputFileNum,\r
1059               SectType,\r
1060               OutFile\r
1061               );\r
1062     break;\r
1063   }\r
1064 \r
1065 Finish:\r
1066   if (InputFileName != NULL) {\r
1067     free (InputFileName);\r
1068   }\r
1069 \r
1070   if (OutFile != NULL) {\r
1071     fclose (OutFile);\r
1072   }\r
1073 \r
1074   fprintf (stdout, "GenSec tool done with return code is 0x%x.\n", GetUtilityStatus ()); \r
1075 \r
1076   return GetUtilityStatus ();\r
1077 }\r