]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenSec/GenSec.c
Sync EDKII BaseTools to BaseTools project r1903.
[mirror_edk2.git] / BaseTools / Source / C / GenSec / GenSec.c
CommitLineData
30fdf114
LG
1/** @file\r
2\r
52302d4d 3Copyright (c) 2004 - 2010, Intel Corporation \r
30fdf114
LG
4All rights reserved. This program and the accompanying materials \r
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
121 fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
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
788 if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {\r
789 Offset = sizeof (CRC32_SECTION_HEADER);\r
790 } else {\r
791 Offset = sizeof (EFI_GUID_DEFINED_SECTION);\r
792 }\r
793\r
794 //\r
795 // read all input file contents into a buffer\r
796 // first get the size of all file contents\r
797 //\r
798 Status = GetSectionContents (\r
799 InputFileName,\r
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
840 if (CompareGuid (VendorGuid, &mEfiCrc32SectionGuid) == 0) {\r
841 //\r
842 // Default Guid section is CRC32.\r
843 //\r
844 Crc32Checksum = 0;\r
845 CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);\r
846\r
847 TotalLength = InputLength + sizeof (CRC32_SECTION_HEADER);\r
848 if (TotalLength >= MAX_SECTION_SIZE) {\r
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
918 FILE *InFile;\r
919 FILE *OutFile;\r
920 CHAR8 **InputFileName;\r
921 CHAR8 *OutputFileName;\r
922 CHAR8 *SectionName;\r
923 CHAR8 *CompressionName;\r
924 CHAR8 *StringBuffer;\r
925 EFI_GUID VendorGuid = mZeroGuid;\r
fd171542 926 int VersionNumber;\r
30fdf114
LG
927 UINT8 SectType;\r
928 UINT8 SectCompSubType;\r
929 UINT16 SectGuidAttribute; \r
930 UINT64 SectGuidHeaderLength;\r
931 EFI_VERSION_SECTION *VersionSect;\r
932 EFI_USER_INTERFACE_SECTION *UiSect;\r
933 UINT32 InputLength;\r
934 UINT8 *OutFileBuffer;\r
935 EFI_STATUS Status;\r
936 UINT64 LogLevel;\r
52302d4d
LG
937 UINT32 *InputFileAlign;\r
938 UINT32 InputFileAlignNum;\r
939\r
940 InputFileAlign = NULL;\r
941 InputFileAlignNum = 0;\r
30fdf114
LG
942 InputFileName = NULL;\r
943 OutputFileName = NULL;\r
944 SectionName = NULL;\r
945 CompressionName = NULL;\r
946 StringBuffer = "";\r
947 InFile = NULL;\r
948 OutFile = NULL;\r
949 VersionNumber = 0;\r
950 InputFileNum = 0;\r
951 SectType = EFI_SECTION_ALL;\r
952 SectCompSubType = 0;\r
52302d4d 953 SectGuidAttribute = EFI_GUIDED_SECTION_NONE;\r
30fdf114
LG
954 OutFileBuffer = NULL;\r
955 InputLength = 0;\r
956 Status = STATUS_SUCCESS;\r
957 LogLevel = 0;\r
958 SectGuidHeaderLength = 0;\r
959 VersionSect = NULL;\r
960 UiSect = NULL;\r
961 \r
962 SetUtilityName (UTILITY_NAME);\r
963 \r
964 if (argc == 1) {\r
965 Error (NULL, 0, 1001, "Missing options", "No options input");\r
966 Usage ();\r
967 return STATUS_ERROR;\r
968 }\r
969\r
970 //\r
971 // Parse command line\r
972 //\r
973 argc --;\r
974 argv ++;\r
975\r
976 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
977 Version ();\r
978 Usage ();\r
979 return STATUS_SUCCESS; \r
980 }\r
981\r
982 if (stricmp (argv[0], "--version") == 0) {\r
983 Version ();\r
984 return STATUS_SUCCESS; \r
985 }\r
986\r
987 while (argc > 0) {\r
988 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {\r
989 SectionName = argv[1];\r
990 if (SectionName == NULL) {\r
991 Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");\r
992 goto Finish;\r
993 }\r
994 argc -= 2;\r
995 argv += 2;\r
996 continue; \r
997 }\r
998\r
999 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
1000 OutputFileName = argv[1];\r
1001 if (OutputFileName == NULL) {\r
1002 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");\r
1003 goto Finish;\r
1004 }\r
1005 argc -= 2;\r
1006 argv += 2;\r
1007 continue; \r
1008 }\r
1009\r
1010 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {\r
1011 CompressionName = argv[1];\r
1012 if (CompressionName == NULL) {\r
1013 Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");\r
1014 goto Finish;\r
1015 }\r
1016 argc -= 2;\r
1017 argv += 2;\r
1018 continue;\r
1019 }\r
1020\r
1021 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {\r
1022 Status = StringToGuid (argv[1], &VendorGuid);\r
1023 if (EFI_ERROR (Status)) {\r
1024 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1025 goto Finish;\r
1026 }\r
1027 argc -= 2;\r
1028 argv += 2;\r
1029 continue;\r
1030 }\r
1031\r
1032 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {\r
1033 if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {\r
1034 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
1035 } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {\r
1036 SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
1037 } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {\r
1038 //\r
1039 // NONE attribute\r
1040 //\r
1041 SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;\r
1042 } else {\r
1043 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1044 goto Finish;\r
1045 }\r
1046 argc -= 2;\r
1047 argv += 2;\r
1048 continue;\r
1049 }\r
1050\r
1051 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {\r
1052 Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);\r
1053 if (EFI_ERROR (Status)) {\r
1054 Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);\r
1055 goto Finish;\r
1056 }\r
1057 argc -= 2;\r
1058 argv += 2;\r
1059 continue;\r
1060 }\r
1061\r
1062 if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {\r
1063 StringBuffer = argv[1];\r
1064 if (StringBuffer == NULL) {\r
1065 Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");\r
1066 goto Finish;\r
1067 }\r
1068 argc -= 2;\r
1069 argv += 2;\r
1070 continue;\r
1071 }\r
1072\r
1073 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {\r
1074 if (argv[1] == NULL) {\r
1075 Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");\r
1076 goto Finish;\r
1077 }\r
1078 //\r
1079 // Verify string is a integrator number\r
1080 //\r
1081 for (Index = 0; Index < strlen (argv[1]); Index++) {\r
a709adfa 1082 if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {\r
30fdf114
LG
1083 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1084 goto Finish;\r
1085 }\r
1086 }\r
1087\r
1088 sscanf (argv[1], "%d", &VersionNumber);\r
1089 argc -= 2;\r
1090 argv += 2;\r
1091 continue;\r
1092 }\r
1093\r
1094 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
1095 SetPrintLevel (VERBOSE_LOG_LEVEL);\r
1096 VerboseMsg ("Verbose output Mode Set!");\r
1097 argc --;\r
1098 argv ++;\r
1099 continue;\r
1100 }\r
1101\r
1102 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
1103 SetPrintLevel (KEY_LOG_LEVEL);\r
1104 KeyMsg ("Quiet output Mode Set!");\r
1105 argc --;\r
1106 argv ++;\r
1107 continue;\r
1108 }\r
1109\r
1110 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
1111 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
1112 if (EFI_ERROR (Status)) {\r
1113 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1114 goto Finish;\r
1115 }\r
1116 if (LogLevel > 9) {\r
fd171542 1117 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel);\r
30fdf114
LG
1118 goto Finish;\r
1119 }\r
1120 SetPrintLevel (LogLevel);\r
1121 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
1122 argc -= 2;\r
1123 argv += 2;\r
1124 continue;\r
1125 }\r
1126\r
52302d4d
LG
1127 //\r
1128 // Section File alignment requirement\r
1129 //\r
1130 if (stricmp (argv[0], "--sectionalign") == 0) {\r
1131 if (InputFileAlignNum == 0) {\r
1132 InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
1133 if (InputFileAlign == NULL) {\r
1134 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1135 return 1;\r
1136 }\r
1137 memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
1138 } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1139 InputFileAlign = (UINT32 *) realloc (\r
1140 InputFileAlign,\r
1141 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)\r
1142 );\r
1143\r
1144 if (InputFileAlign == NULL) {\r
1145 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1146 return 1;\r
1147 }\r
1148 memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));\r
1149 }\r
1150 \r
1151 Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));\r
1152 if (EFI_ERROR (Status)) {\r
1153 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1154 goto Finish;\r
1155 }\r
1156 argc -= 2;\r
1157 argv += 2;\r
1158 InputFileAlignNum ++;\r
1159 continue; \r
1160 }\r
1161\r
30fdf114
LG
1162 //\r
1163 // Get Input file name\r
1164 //\r
1165 if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
1166 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
1167 if (InputFileName == NULL) {\r
1168 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1169 return 1;\r
1170 }\r
30fdf114
LG
1171 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1172 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1173 //\r
1174 // InputFileName buffer too small, need to realloc\r
1175 //\r
1176 InputFileName = (CHAR8 **) realloc (\r
1177 InputFileName,\r
1178 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
1179 );\r
1180\r
1181 if (InputFileName == NULL) {\r
1182 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1183 return 1;\r
1184 }\r
30fdf114
LG
1185 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1186 }\r
1187\r
1188 InputFileName[InputFileNum++] = argv[0];\r
1189 argc --;\r
1190 argv ++;\r
1191 }\r
1192\r
52302d4d
LG
1193 if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {\r
1194 Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");\r
1195 goto Finish;\r
1196 }\r
1197\r
30fdf114
LG
1198 VerboseMsg ("%s tool start.", UTILITY_NAME);\r
1199\r
1200 //\r
1201 // Parse all command line parameters to get the corresponding section type.\r
1202 //\r
1203 VerboseMsg ("Section type is %s", SectionName);\r
1204 if (SectionName == NULL) {\r
1205 //\r
1206 // No specified Section type, default is SECTION_ALL.\r
1207 //\r
1208 SectType = EFI_SECTION_ALL;\r
1209 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {\r
1210 SectType = EFI_SECTION_COMPRESSION;\r
1211 if (CompressionName == NULL) {\r
1212 //\r
1213 // Default is PI_STD compression algorithm.\r
1214 //\r
1215 SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1216 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {\r
1217 SectCompSubType = EFI_NOT_COMPRESSED;\r
1218 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {\r
1219 SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1220 } else {\r
1221 Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);\r
1222 goto Finish;\r
1223 }\r
1224 VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);\r
1225 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {\r
1226 SectType = EFI_SECTION_GUID_DEFINED;\r
1227\r
1228 if (CompareGuid (&VendorGuid, &mZeroGuid) == 0) {\r
1229 memcpy (&VendorGuid, &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
1230 }\r
1231 \r
30fdf114
LG
1232 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {\r
1233 //\r
1234 // NONE attribute, clear attribute value.\r
1235 //\r
52302d4d 1236 SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;\r
30fdf114
LG
1237 }\r
1238 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", \r
fd171542 1239 (unsigned) VendorGuid.Data1,\r
30fdf114
LG
1240 VendorGuid.Data2,\r
1241 VendorGuid.Data3,\r
1242 VendorGuid.Data4[0],\r
1243 VendorGuid.Data4[1],\r
1244 VendorGuid.Data4[2],\r
1245 VendorGuid.Data4[3],\r
1246 VendorGuid.Data4[4],\r
1247 VendorGuid.Data4[5],\r
1248 VendorGuid.Data4[6],\r
1249 VendorGuid.Data4[7]);\r
1250 if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {\r
1251 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);\r
1252 }\r
1253 if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {\r
1254 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);\r
1255 }\r
1256 if (SectGuidHeaderLength != 0) {\r
fd171542 1257 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);\r
30fdf114
LG
1258 }\r
1259 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {\r
1260 SectType = EFI_SECTION_PE32;\r
1261 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {\r
1262 SectType = EFI_SECTION_PIC;\r
1263 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {\r
1264 SectType = EFI_SECTION_TE;\r
1265 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {\r
1266 SectType = EFI_SECTION_DXE_DEPEX;\r
fd171542 1267 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {\r
1268 SectType = EFI_SECTION_SMM_DEPEX;\r
30fdf114
LG
1269 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {\r
1270 SectType = EFI_SECTION_VERSION;\r
1271 if (VersionNumber < 0 || VersionNumber > 9999) {\r
1272 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~9999", VersionNumber);\r
1273 goto Finish;\r
1274 }\r
1275 VerboseMsg ("Version section number is %d", VersionNumber);\r
1276 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {\r
1277 SectType = EFI_SECTION_USER_INTERFACE;\r
1278 if (StringBuffer[0] == '\0') {\r
1279 Error (NULL, 0, 1001, "Missing option", "user interface string");\r
1280 goto Finish;\r
1281 }\r
1282 VerboseMsg ("UI section string name is %s", StringBuffer);\r
1283 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {\r
1284 SectType = EFI_SECTION_COMPATIBILITY16;\r
1285 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {\r
1286 SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
1287 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {\r
1288 SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;\r
1289 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {\r
1290 SectType = EFI_SECTION_RAW;\r
1291 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {\r
1292 SectType = EFI_SECTION_PEI_DEPEX;\r
1293 } else {\r
1294 Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);\r
1295 goto Finish;\r
1296 }\r
1297 \r
1298 //\r
1299 // GuidValue is only required by Guided section.\r
1300 //\r
1301 if ((SectType != EFI_SECTION_GUID_DEFINED) && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
1302 fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);\r
1303 }\r
1304 \r
1305 //\r
1306 // Check whether there is input file\r
1307 // \r
1308 if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {\r
1309 //\r
1310 // The input file are required for other section type.\r
1311 //\r
1312 if (InputFileNum == 0) {\r
1313 Error (NULL, 0, 1001, "Missing options", "Input files");\r
1314 goto Finish;\r
1315 }\r
1316 }\r
1317 //\r
1318 // Check whether there is output file\r
1319 //\r
1320 for (Index = 0; Index < InputFileNum; Index ++) {\r
fd171542 1321 VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);\r
30fdf114
LG
1322 }\r
1323 if (OutputFileName == NULL) {\r
1324 Error (NULL, 0, 1001, "Missing options", "Output file");\r
1325 goto Finish;\r
1326 // OutFile = stdout;\r
1327 }\r
1328 VerboseMsg ("Output file name is %s", OutputFileName);\r
1329\r
1330 //\r
1331 // At this point, we've fully validated the command line, and opened appropriate\r
1332 // files, so let's go and do what we've been asked to do...\r
1333 //\r
1334 //\r
1335 // Within this switch, build and write out the section header including any\r
1336 // section type specific pieces. If there's an input file, it's tacked on later\r
1337 //\r
1338 switch (SectType) {\r
1339 case EFI_SECTION_COMPRESSION:\r
52302d4d
LG
1340 if (InputFileAlign != NULL) {\r
1341 free (InputFileAlign);\r
1342 InputFileAlign = NULL;\r
1343 }\r
30fdf114
LG
1344 Status = GenSectionCompressionSection (\r
1345 InputFileName,\r
52302d4d 1346 InputFileAlign,\r
30fdf114
LG
1347 InputFileNum,\r
1348 SectCompSubType,\r
1349 &OutFileBuffer\r
1350 );\r
1351 break;\r
1352\r
1353 case EFI_SECTION_GUID_DEFINED:\r
52302d4d
LG
1354 if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mEfiCrc32SectionGuid) != 0)) {\r
1355 //\r
1356 // Only process alignment for the default known CRC32 guided section.\r
1357 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.\r
1358 //\r
1359 free (InputFileAlign);\r
1360 InputFileAlign = NULL;\r
1361 }\r
30fdf114
LG
1362 Status = GenSectionGuidDefinedSection (\r
1363 InputFileName,\r
52302d4d 1364 InputFileAlign,\r
30fdf114
LG
1365 InputFileNum,\r
1366 &VendorGuid,\r
1367 SectGuidAttribute,\r
1368 (UINT32) SectGuidHeaderLength,\r
1369 &OutFileBuffer\r
1370 );\r
1371 break;\r
1372\r
1373 case EFI_SECTION_VERSION:\r
1374 Index = sizeof (EFI_COMMON_SECTION_HEADER);\r
1375 //\r
1376 // 2 bytes for the build number UINT16\r
1377 //\r
1378 Index += 2;\r
1379 //\r
1380 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1381 //\r
1382 Index += (strlen (StringBuffer) * 2) + 2;\r
1383 OutFileBuffer = (UINT8 *) malloc (Index);\r
1384 if (OutFileBuffer == NULL) {\r
1385 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1386 goto Finish;\r
1387 }\r
1388 VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;\r
1389 VersionSect->CommonHeader.Type = SectType;\r
1390 VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);\r
1391 VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);\r
1392 VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);\r
1393 VersionSect->BuildNumber = (UINT16) VersionNumber;\r
1394 Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);\r
fd171542 1395 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
30fdf114
LG
1396 break;\r
1397\r
1398 case EFI_SECTION_USER_INTERFACE:\r
1399 Index = sizeof (EFI_COMMON_SECTION_HEADER);\r
1400 //\r
1401 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1402 //\r
1403 Index += (strlen (StringBuffer) * 2) + 2;\r
1404 OutFileBuffer = (UINT8 *) malloc (Index);\r
1405 if (OutFileBuffer == NULL) {\r
1406 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1407 goto Finish;\r
1408 }\r
1409 UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;\r
1410 UiSect->CommonHeader.Type = SectType;\r
1411 UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);\r
1412 UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);\r
1413 UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);\r
1414 Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);\r
fd171542 1415 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
30fdf114
LG
1416 break;\r
1417\r
1418 case EFI_SECTION_ALL:\r
1419 //\r
1420 // read all input file contents into a buffer\r
1421 // first get the size of all file contents\r
1422 //\r
1423 Status = GetSectionContents (\r
1424 InputFileName,\r
52302d4d 1425 InputFileAlign,\r
30fdf114
LG
1426 InputFileNum,\r
1427 OutFileBuffer,\r
1428 &InputLength\r
1429 );\r
1430 \r
1431 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1432 OutFileBuffer = (UINT8 *) malloc (InputLength);\r
1433 if (OutFileBuffer == NULL) {\r
1434 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1435 goto Finish;\r
1436 }\r
1437 //\r
1438 // read all input file contents into a buffer\r
1439 //\r
1440 Status = GetSectionContents (\r
1441 InputFileName,\r
52302d4d 1442 InputFileAlign,\r
30fdf114
LG
1443 InputFileNum,\r
1444 OutFileBuffer,\r
1445 &InputLength\r
1446 );\r
1447 }\r
fd171542 1448 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);\r
30fdf114
LG
1449 break;\r
1450 default:\r
1451 //\r
1452 // All other section types are caught by default (they're all the same)\r
1453 //\r
1454 Status = GenSectionCommonLeafSection (\r
1455 InputFileName,\r
1456 InputFileNum,\r
1457 SectType,\r
1458 &OutFileBuffer\r
1459 );\r
1460 break;\r
1461 }\r
1462 \r
1463 if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {\r
fd171542 1464 Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);\r
30fdf114
LG
1465 goto Finish;\r
1466 }\r
1467\r
1468 //\r
1469 // Get output file length\r
1470 //\r
1471 if (SectType != EFI_SECTION_ALL) {\r
1472 InputLength = SECTION_SIZE (OutFileBuffer);\r
1473 }\r
1474 \r
1475 //\r
1476 // Write the output file\r
1477 //\r
1478 OutFile = fopen (OutputFileName, "wb");\r
1479 if (OutFile == NULL) {\r
1480 Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);\r
1481 goto Finish;\r
1482 }\r
1483\r
1484 fwrite (OutFileBuffer, InputLength, 1, OutFile);\r
1485\r
1486Finish:\r
1487 if (InputFileName != NULL) {\r
1488 free (InputFileName);\r
1489 }\r
1490\r
52302d4d
LG
1491 if (InputFileAlign != NULL) {\r
1492 free (InputFileAlign);\r
1493 }\r
1494\r
30fdf114
LG
1495 if (OutFileBuffer != NULL) {\r
1496 free (OutFileBuffer);\r
1497 }\r
1498\r
1499 if (OutFile != NULL) {\r
1500 fclose (OutFile);\r
1501 }\r
1502 \r
1503 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
1504\r
1505 return GetUtilityStatus ();\r
1506}\r