Clean up include directory.
[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   BOOLEAN                   AllocatedFlag;\r
714   EFI_STATUS                Status;\r
715  \r
716   fprintf (stdout, "GenSec tool start.\n");  \r
717   \r
718   InputFileName         = NULL;\r
719   OutputFileName        = NULL;\r
720   SectionName           = NULL;\r
721   CompressionName       = NULL;\r
722   StringBuffer          = "";\r
723 \r
724   InFile                = NULL;\r
725   OutFile               = NULL;\r
726   VersionNumber         = 0;\r
727   InputFileNum          = 0;\r
728   SectType              = EFI_SECTION_ALL;\r
729   SectCompSubType       = 0;\r
730   SectGuidAttribute     = 0;\r
731   FileBuffer            = NULL;\r
732   InputLength           = 0;\r
733   AllocatedFlag         = FALSE;\r
734   Status                = STATUS_SUCCESS;\r
735   \r
736 \r
737   SetUtilityName (UTILITY_NAME);\r
738   \r
739   if (argc == 1) {\r
740     Usage ();\r
741     return STATUS_ERROR;\r
742   }\r
743 \r
744   //\r
745   // Parse command line\r
746   //\r
747   argc --;\r
748   argv ++;\r
749 \r
750   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
751     Usage();\r
752     return STATUS_ERROR;    \r
753   }\r
754 \r
755   if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--version") == 0)) {\r
756     Version();\r
757     return STATUS_ERROR;    \r
758   }\r
759 \r
760   while (argc > 0) {\r
761     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {\r
762       SectionName = argv[1];\r
763       argc -= 2;\r
764       argv += 2;\r
765       continue; \r
766     }\r
767 \r
768     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
769       OutputFileName = argv[1];\r
770       argc -= 2;\r
771       argv += 2;\r
772       continue; \r
773     }\r
774 \r
775     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {\r
776       CompressionName = argv[1];\r
777       argc -= 2;\r
778       argv += 2;\r
779       continue;\r
780     }\r
781 \r
782     if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendorguid") == 0)) {\r
783       Status = StringToGuid (argv[1], &VendorGuid);\r
784       if (EFI_ERROR (Status)) {\r
785         Error (NULL, 0, 0, NULL, "ERROR: %s is not a formal GUID value.", argv[1]);\r
786         goto Finish;\r
787       }\r
788       argc -= 2;\r
789       argv += 2;\r
790       continue;\r
791     }\r
792 \r
793     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {\r
794       if (stricmp (argv[1], GUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {\r
795         SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
796       } else if (stricmp (argv[1], GUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {\r
797         SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
798       } else {\r
799         Error (NULL, 0, 0, argv[1], "unknown Guid Section Attribute");\r
800         goto Finish;\r
801       }\r
802       argc -= 2;\r
803       argv += 2;\r
804       continue;\r
805     }\r
806 \r
807     if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {\r
808       StringBuffer = argv[1];\r
809       argc -= 2;\r
810       argv += 2;\r
811       continue;\r
812     }\r
813 \r
814     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {\r
815       //\r
816       // Verify string is a integrator number\r
817       //\r
818       for (Index = 0; Index < strlen (argv[1]); Index++) {\r
819         if ((argv[1][Index] != '-') && (isdigit (argv[1][Index]) == 0)) {\r
820           Error (NULL, 0, 0, NULL, "ERROR: %s is not a valid integer.", argv[1]);\r
821           goto Finish;\r
822         }\r
823       }\r
824 \r
825       sscanf (argv[1], "%d", &VersionNumber);\r
826       argc -= 2;\r
827       argv += 2;\r
828       continue;\r
829     }\r
830 \r
831     //\r
832     // Get Input file name\r
833     //\r
834     if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
835       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
836       if (InputFileName == NULL) {\r
837         Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
838         return EFI_OUT_OF_RESOURCES;\r
839       }\r
840 \r
841       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
842     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
843       //\r
844       // InputFileName buffer too small, need to realloc\r
845       //\r
846       InputFileName = (CHAR8 **) realloc (\r
847                                   InputFileName,\r
848                                   (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
849                                   );\r
850 \r
851       if (InputFileName == NULL) {\r
852         Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
853         return EFI_OUT_OF_RESOURCES;\r
854       }\r
855 \r
856       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
857     }\r
858 \r
859     InputFileName[InputFileNum++] = argv[0];\r
860     argc --;\r
861     argv ++;\r
862   }\r
863 \r
864   //\r
865   // Parse all command line parameters to get the corresponding section type.\r
866   //\r
867   if (SectionName == NULL) {\r
868     //\r
869     // No specified Section type, default is SECTION_ALL.\r
870     //\r
871     SectType = EFI_SECTION_ALL;\r
872   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {\r
873     SectType     = EFI_SECTION_COMPRESSION;\r
874     if (CompressionName == NULL) {\r
875       //\r
876       // Default is PI_STD compression algorithm.\r
877       //\r
878       SectCompSubType = EFI_STANDARD_COMPRESSION;\r
879     } else if (stricmp (CompressionName, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {\r
880       SectCompSubType = EFI_NOT_COMPRESSED;\r
881     } else if (stricmp (CompressionName, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {\r
882       SectCompSubType = EFI_STANDARD_COMPRESSION;\r
883     } else {\r
884       Error (NULL, 0, 0, CompressionName, "unknown compression type");\r
885       goto Finish;\r
886     }\r
887   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {\r
888     SectType     = EFI_SECTION_GUID_DEFINED;\r
889 \r
890     if (CompareGuid (&VendorGuid, &gZeroGuid) == 0) {\r
891       memcpy (&VendorGuid, &gEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
892     }\r
893     \r
894     if (SectGuidAttribute == 0) {\r
895       SectGuidAttribute = EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
896     }\r
897   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_PE32]) == 0) {\r
898     SectType = EFI_SECTION_PE32;\r
899   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_PIC]) == 0) {\r
900     SectType = EFI_SECTION_PIC;\r
901   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_TE]) == 0) {\r
902     SectType = EFI_SECTION_TE;\r
903   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {\r
904     SectType = EFI_SECTION_DXE_DEPEX;\r
905   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_VERSION]) == 0) {\r
906     SectType = EFI_SECTION_VERSION;\r
907     if (VersionNumber < 0 || VersionNumber > 9999) {\r
908       Error (NULL, 0, 0, NULL, "%d is illegal version number\n", VersionNumber);\r
909       goto Finish;\r
910     }\r
911   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {\r
912     SectType = EFI_SECTION_USER_INTERFACE;\r
913     if (StringBuffer[0] == '\0') {\r
914       Error (NULL, 0, 0, "user interface string not specified", NULL);\r
915       goto Finish;\r
916     }\r
917   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {\r
918     SectType = EFI_SECTION_COMPATIBILITY16;\r
919   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {\r
920     SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
921   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {\r
922     SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;\r
923   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_RAW]) == 0) {\r
924     SectType = EFI_SECTION_RAW;\r
925   } else if (stricmp (SectionName, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {\r
926     SectType = EFI_SECTION_PEI_DEPEX;\r
927   } else {\r
928     Error (NULL, 0, 0, SectionName, "unknown section type");\r
929     goto Finish;\r
930   }\r
931   \r
932   if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {\r
933     //\r
934     // The input file are required for those section type.\r
935     // The file are from stdin.\r
936     //\r
937     if (InputFileNum == 0) {\r
938       Error (NULL, 0, 0, NULL, "No input files is specified.");\r
939       goto Finish;\r
940     }\r
941   }\r
942   \r
943   //\r
944   // Open output file\r
945   //\r
946   if (OutputFileName == NULL) {\r
947     Error (NULL, 0, 0, NULL, "No output file name is specified.");\r
948     goto Finish;\r
949     // OutFile = stdout;\r
950   } else {\r
951     OutFile = fopen (OutputFileName, "wb");\r
952   }\r
953 \r
954   if (OutFile == NULL) {\r
955     Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");\r
956     goto Finish;\r
957   }\r
958   \r
959   //\r
960   // At this point, we've fully validated the command line, and opened appropriate\r
961   // files, so let's go and do what we've been asked to do...\r
962   //\r
963   //\r
964   // Within this switch, build and write out the section header including any\r
965   // section type specific pieces.  If there's an input file, it's tacked on later\r
966   //\r
967   switch (SectType) {\r
968   case EFI_SECTION_COMPRESSION:\r
969     Status = GenSectionCompressionSection (\r
970               InputFileName,\r
971               InputFileNum,\r
972               SectCompSubType,\r
973               OutFile\r
974               );\r
975     break;\r
976 \r
977   case EFI_SECTION_GUID_DEFINED:\r
978     Status = GenSectionGuidDefinedSection (\r
979               InputFileName,\r
980               InputFileNum,\r
981               &VendorGuid,\r
982               SectGuidAttribute,\r
983               OutFile\r
984               );\r
985     break;\r
986 \r
987   case EFI_SECTION_VERSION:\r
988     CommonSect.Type = (EFI_SECTION_TYPE) SectType;\r
989 \r
990     Index           = sizeof (CommonSect);\r
991     //\r
992     // 2 bytes for the build number UINT16\r
993     //\r
994     Index += 2;\r
995     //\r
996     // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
997     //\r
998     Index += (strlen (StringBuffer) * 2) + 2;\r
999     memcpy (&CommonSect.Size, &Index, 3);\r
1000     fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);\r
1001     fwrite (&VersionNumber, sizeof (UINT16), 1, OutFile);\r
1002     Ascii2UnicodeWriteString (StringBuffer, OutFile);\r
1003     break;\r
1004 \r
1005   case EFI_SECTION_USER_INTERFACE:\r
1006     CommonSect.Type = (EFI_SECTION_TYPE) SectType;\r
1007     Index           = sizeof (CommonSect);\r
1008     //\r
1009     // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1010     //\r
1011     Index += (strlen (StringBuffer) * 2) + 2;\r
1012     memcpy (&CommonSect.Size, &Index, 3);\r
1013     fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);\r
1014     Ascii2UnicodeWriteString (StringBuffer, OutFile);\r
1015     break;\r
1016 \r
1017   case EFI_SECTION_ALL:\r
1018     //\r
1019     // read all input file contents into a buffer\r
1020     // first get the size of all file contents\r
1021     //\r
1022     Status = GetSectionContents (\r
1023               InputFileName,\r
1024               InputFileNum,\r
1025               FileBuffer,\r
1026               &InputLength\r
1027               );\r
1028   \r
1029     if (Status == EFI_BUFFER_TOO_SMALL) {\r
1030       FileBuffer = (UINT8 *) malloc (InputLength);\r
1031       if (FileBuffer == NULL) {\r
1032         Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
1033         goto Finish;\r
1034       }\r
1035       //\r
1036       // read all input file contents into a buffer\r
1037       //\r
1038       Status = GetSectionContents (\r
1039                 InputFileName,\r
1040                 InputFileNum,\r
1041                 FileBuffer,\r
1042                 &InputLength\r
1043                 );\r
1044     }\r
1045   \r
1046     if (Status == EFI_SUCCESS) {\r
1047       fwrite (FileBuffer, InputLength, 1, OutFile);\r
1048     }\r
1049 \r
1050     if (FileBuffer != NULL) {\r
1051       free (FileBuffer);\r
1052     }\r
1053     \r
1054     break;\r
1055   default:\r
1056     //\r
1057     // All other section types are caught by default (they're all the same)\r
1058     //\r
1059     Status = GenSectionCommonLeafSection (\r
1060               InputFileName,\r
1061               InputFileNum,\r
1062               SectType,\r
1063               OutFile\r
1064               );\r
1065     break;\r
1066   }\r
1067 \r
1068 Finish:\r
1069   if (AllocatedFlag == TRUE) {\r
1070     for (Index = 0; Index < InputFileNum; Index ++) {\r
1071       free (InputFileName[Index]);\r
1072     }\r
1073   }\r
1074 \r
1075   if (InputFileName != NULL) {\r
1076     free (InputFileName);\r
1077   }\r
1078 \r
1079   if (OutFile != NULL) {\r
1080     fclose (OutFile);\r
1081   }\r
1082 \r
1083   fprintf (stdout, "GenSec tool done with return code is 0x%x.\n", GetUtilityStatus ()); \r
1084 \r
1085   return GetUtilityStatus ();\r
1086 }\r