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