BaseTools: argument genfds-multi-thread create GenSec command issue
[mirror_edk2.git] / BaseTools / Source / C / GenSec / GenSec.c
CommitLineData
30fdf114 1/** @file\r
97fa0ee9 2Creates output file that is a properly formed section per the PI spec.\r
30fdf114 3\r
6ecab5ad 4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
40d841f6 5This program and the accompanying materials \r
30fdf114
LG
6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php \r
9 \r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
30fdf114 13**/\r
9a8d7aa7
FY
14#ifndef __GNUC__\r
15#include <windows.h>\r
16#include <io.h>\r
17#include <sys/types.h>\r
18#include <sys/stat.h>\r
19#endif\r
30fdf114
LG
20\r
21#include <stdio.h>\r
22#include <stdlib.h>\r
23#include <string.h>\r
24#include <ctype.h>\r
25\r
26#include <Common/UefiBaseTypes.h>\r
27#include <Common/PiFirmwareFile.h>\r
28#include <Protocol/GuidedSectionExtraction.h>\r
52302d4d 29#include <IndustryStandard/PeImage.h>\r
30fdf114
LG
30\r
31#include "CommonLib.h"\r
32#include "Compress.h"\r
33#include "Crc32.h"\r
34#include "EfiUtilityMsgs.h"\r
35#include "ParseInf.h"\r
9a8d7aa7
FY
36#include "FvLib.h"\r
37#include "PeCoffLib.h"\r
30fdf114
LG
38\r
39//\r
40// GenSec Tool Information\r
41//\r
42#define UTILITY_NAME "GenSec"\r
43#define UTILITY_MAJOR_VERSION 0\r
44#define UTILITY_MINOR_VERSION 1\r
45\r
30fdf114
LG
46STATIC CHAR8 *mSectionTypeName[] = {\r
47 NULL, // 0x00 - reserved\r
48 "EFI_SECTION_COMPRESSION", // 0x01\r
49 "EFI_SECTION_GUID_DEFINED", // 0x02\r
50 NULL, // 0x03 - reserved\r
51 NULL, // 0x04 - reserved\r
52 NULL, // 0x05 - reserved\r
53 NULL, // 0x06 - reserved\r
54 NULL, // 0x07 - reserved\r
55 NULL, // 0x08 - reserved\r
56 NULL, // 0x09 - reserved\r
57 NULL, // 0x0A - reserved\r
58 NULL, // 0x0B - reserved\r
59 NULL, // 0x0C - reserved\r
60 NULL, // 0x0D - reserved\r
61 NULL, // 0x0E - reserved\r
62 NULL, // 0x0F - reserved\r
63 "EFI_SECTION_PE32", // 0x10\r
64 "EFI_SECTION_PIC", // 0x11\r
65 "EFI_SECTION_TE", // 0x12\r
66 "EFI_SECTION_DXE_DEPEX", // 0x13\r
67 "EFI_SECTION_VERSION", // 0x14\r
68 "EFI_SECTION_USER_INTERFACE", // 0x15\r
69 "EFI_SECTION_COMPATIBILITY16", // 0x16\r
70 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17\r
71 "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18\r
72 "EFI_SECTION_RAW", // 0x19\r
73 NULL, // 0x1A\r
74 "EFI_SECTION_PEI_DEPEX", // 0x1B\r
75 "EFI_SECTION_SMM_DEPEX" // 0x1C\r
76};\r
77\r
78STATIC CHAR8 *mCompressionTypeName[] = { "PI_NONE", "PI_STD" };\r
79\r
80#define EFI_GUIDED_SECTION_NONE 0x80\r
81STATIC CHAR8 *mGUIDedSectionAttribue[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};\r
82\r
52302d4d
LG
83STATIC CHAR8 *mAlignName[] = {\r
84 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",\r
e921f58d
YZ
85 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K",\r
86 "512K", "1M", "2M", "4M", "8M", "16M"\r
52302d4d
LG
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
e8a47801
LG
97typedef struct {\r
98 EFI_GUID_DEFINED_SECTION2 GuidSectionHeader;\r
99 UINT32 CRC32Checksum;\r
100} CRC32_SECTION_HEADER2;\r
101\r
30fdf114
LG
102STATIC EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
103STATIC EFI_GUID mEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;\r
104\r
105STATIC\r
106VOID \r
107Version (\r
108 VOID\r
109 )\r
110/*++\r
111\r
112Routine Description:\r
113\r
114 Print out version information for this utility.\r
115\r
116Arguments:\r
117\r
118 None\r
119 \r
120Returns:\r
121\r
122 None\r
123 \r
124--*/ \r
125{\r
b36d134f 126 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
30fdf114
LG
127}\r
128\r
129STATIC\r
130VOID\r
131Usage (\r
132 VOID\r
133 )\r
134/*++\r
135\r
136Routine Description:\r
137\r
138 Print Help message.\r
139\r
140Arguments:\r
141\r
142 VOID\r
143\r
144Returns:\r
145\r
146 None\r
147\r
148--*/\r
149{\r
150 //\r
151 // Summary usage\r
152 //\r
153 fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME);\r
154 \r
155 //\r
156 // Copyright declaration\r
157 // \r
67f3d099 158 fprintf (stdout, "Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.\n\n");\r
30fdf114
LG
159\r
160 //\r
161 // Details Option\r
162 //\r
163 fprintf (stdout, "Options:\n");\r
164 fprintf (stdout, " -o FileName, --outputfile FileName\n\\r
165 File is the SectionFile to be created.\n");\r
166 fprintf (stdout, " -s [SectionType], --sectiontype [SectionType]\n\\r
167 SectionType defined in PI spec is one type of\n\\r
168 EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\\r
169 EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\\r
170 EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\\r
171 EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\\r
172 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\\r
173 EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\\r
fd171542 174 EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\\r
175 if -s option is not given, \n\\r
30fdf114
LG
176 EFI_SECTION_ALL is default section type.\n");\r
177 fprintf (stdout, " -c [Type], --compress [Type]\n\\r
178 Compress method type can be PI_NONE or PI_STD.\n\\r
179 if -c option is not given, PI_STD is default type.\n"); \r
180 fprintf (stdout, " -g GuidValue, --vendor GuidValue\n\\r
181 GuidValue is one specific vendor guid value.\n\\r
182 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");\r
183 fprintf (stdout, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\\r
184 GuidHeaderLength is the size of header of guided data\n");\r
185 fprintf (stdout, " -r GuidAttr, --attributes GuidAttr\n\\r
186 GuidAttr is guid section atttributes, which may be\n\\r
187 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\\r
188 if -r option is not given, default PROCESSING_REQUIRED\n");\r
189 fprintf (stdout, " -n String, --name String\n\\r
190 String is a NULL terminated string used in Ui section.\n");\r
191 fprintf (stdout, " -j Number, --buildnumber Number\n\\r
e8a47801 192 Number is an integer value between 0 and 65535\n\\r
30fdf114 193 used in Ver section.\n");\r
52302d4d
LG
194 fprintf (stdout, " --sectionalign SectionAlign\n\\r
195 SectionAlign points to section alignment, which support\n\\r
9a8d7aa7
FY
196 the alignment scope 0~16M. If SectionAlign is specified\n\\r
197 as 0, tool get alignment value from SectionFile. It is\n\\r
198 specified in same order that the section file is input.\n");\r
b37b108d
YZ
199 fprintf (stdout, " --dummy dummyfile\n\\r
200 compare dummpyfile with input_file to decide whether\n\\r
201 need to set PROCESSING_REQUIRED attribute.\n");\r
30fdf114
LG
202 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");\r
203 fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");\r
204 fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");\r
205 fprintf (stdout, " --version Show program's version number and exit.\n");\r
206 fprintf (stdout, " -h, --help Show this help message and exit.\n");\r
207}\r
208\r
209VOID\r
210Ascii2UnicodeString (\r
211 CHAR8 *String,\r
212 CHAR16 *UniString\r
213 )\r
214/*++\r
215\r
216Routine Description:\r
217\r
218 Write ascii string as unicode string format to FILE \r
219\r
220Arguments:\r
221\r
222 String - Pointer to string that is written to FILE.\r
223 UniString - Pointer to unicode string\r
224\r
225Returns:\r
226\r
227 NULL\r
228\r
229--*/\r
230{\r
231 while (*String != '\0') {\r
232 *(UniString++) = (CHAR16) *(String++);\r
233 }\r
234 //\r
235 // End the UniString with a NULL.\r
236 //\r
237 *UniString = '\0';\r
238} \r
239\r
240STATUS\r
241GenSectionCommonLeafSection (\r
242 CHAR8 **InputFileName,\r
243 UINT32 InputFileNum,\r
244 UINT8 SectionType,\r
245 UINT8 **OutFileBuffer\r
246 )\r
247/*++\r
248 \r
249Routine Description:\r
250 \r
251 Generate a leaf section of type other than EFI_SECTION_VERSION\r
252 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.\r
253 The function won't validate the input file's contents. For\r
254 common leaf sections, the input file may be a binary file.\r
255 The utility will add section header to the file.\r
256 \r
257Arguments:\r
258 \r
259 InputFileName - Name of the input file.\r
260 \r
261 InputFileNum - Number of input files. Should be 1 for leaf section.\r
262\r
263 SectionType - A valid section type string\r
264\r
265 OutFileBuffer - Buffer pointer to Output file contents\r
266\r
267Returns:\r
268 \r
269 STATUS_ERROR - can't continue\r
270 STATUS_SUCCESS - successful return\r
271\r
272--*/\r
273{\r
274 UINT32 InputFileLength;\r
275 FILE *InFile;\r
276 UINT8 *Buffer;\r
277 UINT32 TotalLength;\r
e8a47801 278 UINT32 HeaderLength;\r
30fdf114
LG
279 EFI_COMMON_SECTION_HEADER *CommonSect;\r
280 STATUS Status;\r
281\r
282 if (InputFileNum > 1) {\r
99e55970 283 Error (NULL, 0, 2000, "Invalid parameter", "more than one input file specified");\r
30fdf114
LG
284 return STATUS_ERROR;\r
285 } else if (InputFileNum < 1) {\r
99e55970 286 Error (NULL, 0, 2000, "Invalid parameter", "no input file specified");\r
30fdf114
LG
287 return STATUS_ERROR;\r
288 }\r
289 //\r
290 // Open the input file\r
291 //\r
1be2ed90 292 InFile = fopen (LongFilePath (InputFileName[0]), "rb");\r
30fdf114
LG
293 if (InFile == NULL) {\r
294 Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);\r
295 return STATUS_ERROR;\r
296 }\r
297\r
298 Status = STATUS_ERROR;\r
299 Buffer = NULL;\r
300 //\r
301 // Seek to the end of the input file so we can determine its size\r
302 //\r
303 fseek (InFile, 0, SEEK_END);\r
304 InputFileLength = ftell (InFile);\r
305 fseek (InFile, 0, SEEK_SET);\r
fd171542 306 DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName[0], (unsigned) InputFileLength);\r
30fdf114
LG
307 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength;\r
308 //\r
309 // Size must fit in 3 bytes\r
310 //\r
e8a47801 311 //if (TotalLength >= MAX_SECTION_SIZE) {\r
99e55970 312 // Error (NULL, 0, 2000, "Invalid parameter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20);\r
e8a47801
LG
313 // goto Done;\r
314 //}\r
315 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER);\r
30fdf114 316 if (TotalLength >= MAX_SECTION_SIZE) {\r
e8a47801
LG
317 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER2) + InputFileLength;\r
318 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER2);\r
30fdf114 319 }\r
fd171542 320 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
30fdf114
LG
321 //\r
322 // Fill in the fields in the local section header structure\r
323 //\r
324 Buffer = (UINT8 *) malloc ((size_t) TotalLength);\r
325 if (Buffer == NULL) {\r
326 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated"); \r
327 goto Done;\r
328 }\r
329 CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer;\r
330 CommonSect->Type = SectionType;\r
e8a47801
LG
331 if (TotalLength < MAX_SECTION_SIZE) {\r
332 CommonSect->Size[0] = (UINT8) (TotalLength & 0xff);\r
333 CommonSect->Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);\r
334 CommonSect->Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
335 } else {\r
336 memset(CommonSect->Size, 0xff, sizeof(UINT8) * 3);\r
337 ((EFI_COMMON_SECTION_HEADER2 *)CommonSect)->ExtendedSize = TotalLength;\r
338 }\r
30fdf114
LG
339 \r
340 //\r
341 // read data from the input file.\r
342 //\r
343 if (InputFileLength != 0) {\r
e8a47801 344 if (fread (Buffer + HeaderLength, (size_t) InputFileLength, 1, InFile) != 1) {\r
30fdf114
LG
345 Error (NULL, 0, 0004, "Error reading file", InputFileName[0]);\r
346 goto Done;\r
347 }\r
348 }\r
349\r
350 //\r
351 // Set OutFileBuffer \r
352 //\r
353 *OutFileBuffer = Buffer;\r
354 Status = STATUS_SUCCESS;\r
355\r
356Done:\r
357 fclose (InFile);\r
358\r
359 return Status;\r
360}\r
361\r
52302d4d
LG
362STATIC\r
363EFI_STATUS\r
364StringtoAlignment (\r
365 IN CHAR8 *AlignBuffer,\r
366 OUT UINT32 *AlignNumber\r
367 )\r
368/*++\r
369\r
370Routine Description:\r
371\r
e921f58d 372 Converts Align String to align value (1~16M).\r
52302d4d
LG
373\r
374Arguments:\r
375\r
376 AlignBuffer - Pointer to Align string.\r
377 AlignNumber - Pointer to Align value.\r
378\r
379Returns:\r
380\r
381 EFI_SUCCESS Successfully convert align string to align value.\r
382 EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.\r
383\r
384--*/\r
385{\r
386 UINT32 Index = 0;\r
387 //\r
388 // Check AlignBuffer\r
389 //\r
390 if (AlignBuffer == NULL) {\r
391 return EFI_INVALID_PARAMETER;\r
392 }\r
393 for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) {\r
394 if (stricmp (AlignBuffer, mAlignName [Index]) == 0) {\r
395 *AlignNumber = 1 << Index;\r
396 return EFI_SUCCESS;\r
397 }\r
398 }\r
399 return EFI_INVALID_PARAMETER;\r
400}\r
401\r
30fdf114
LG
402EFI_STATUS\r
403GetSectionContents (\r
404 CHAR8 **InputFileName,\r
52302d4d 405 UINT32 *InputFileAlign,\r
30fdf114
LG
406 UINT32 InputFileNum,\r
407 UINT8 *FileBuffer,\r
408 UINT32 *BufferLength\r
409 )\r
410/*++\r
411 \r
412Routine Description:\r
413 \r
414 Get the contents of all section files specified in InputFileName\r
415 into FileBuffer.\r
416 \r
417Arguments:\r
418 \r
419 InputFileName - Name of the input file.\r
52302d4d
LG
420\r
421 InputFileAlign - Alignment required by the input file data.\r
422\r
30fdf114
LG
423 InputFileNum - Number of input files. Should be at least 1.\r
424\r
425 FileBuffer - Output buffer to contain data\r
426\r
427 BufferLength - On input, this is size of the FileBuffer. \r
428 On output, this is the actual length of the data.\r
429\r
430Returns:\r
431 \r
432 EFI_SUCCESS on successful return\r
433 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.\r
434 EFI_ABORTED if unable to open input file.\r
435 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.\r
436--*/\r
437{\r
52302d4d
LG
438 UINT32 Size;\r
439 UINT32 Offset;\r
440 UINT32 FileSize;\r
441 UINT32 Index;\r
442 FILE *InFile;\r
443 EFI_COMMON_SECTION_HEADER *SectHeader;\r
e8a47801 444 EFI_COMMON_SECTION_HEADER2 TempSectHeader;\r
52302d4d
LG
445 EFI_TE_IMAGE_HEADER TeHeader;\r
446 UINT32 TeOffset;\r
447 EFI_GUID_DEFINED_SECTION GuidSectHeader;\r
e8a47801 448 EFI_GUID_DEFINED_SECTION2 GuidSectHeader2;\r
52302d4d 449 UINT32 HeaderSize;\r
30fdf114
LG
450\r
451 if (InputFileNum < 1) {\r
99e55970 452 Error (NULL, 0, 2000, "Invalid parameter", "must specify at least one input file");\r
30fdf114
LG
453 return EFI_INVALID_PARAMETER;\r
454 }\r
455\r
456 if (BufferLength == NULL) {\r
99e55970 457 Error (NULL, 0, 2000, "Invalid parameter", "BufferLength can't be NULL");\r
30fdf114
LG
458 return EFI_INVALID_PARAMETER;\r
459 }\r
460\r
52302d4d
LG
461 Size = 0;\r
462 Offset = 0;\r
463 TeOffset = 0;\r
30fdf114
LG
464 //\r
465 // Go through our array of file names and copy their contents\r
466 // to the output buffer.\r
467 //\r
468 for (Index = 0; Index < InputFileNum; Index++) {\r
469 //\r
470 // make sure section ends on a DWORD boundary\r
471 //\r
472 while ((Size & 0x03) != 0) {\r
473 if (FileBuffer != NULL && Size < *BufferLength) {\r
474 FileBuffer[Size] = 0;\r
475 }\r
476 Size++;\r
477 }\r
478 \r
479 // \r
480 // Open file and read contents\r
481 //\r
1be2ed90 482 InFile = fopen (LongFilePath (InputFileName[Index]), "rb");\r
30fdf114
LG
483 if (InFile == NULL) {\r
484 Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);\r
485 return EFI_ABORTED;\r
486 }\r
487\r
488 fseek (InFile, 0, SEEK_END);\r
489 FileSize = ftell (InFile);\r
490 fseek (InFile, 0, SEEK_SET);\r
fd171542 491 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
492 //\r
493 // Adjust section buffer when section alignment is required.\r
494 //\r
495 if (InputFileAlign != NULL) {\r
496 //\r
497 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.\r
498 //\r
499 TeOffset = 0;\r
e8a47801
LG
500 //\r
501 // The section might be EFI_COMMON_SECTION_HEADER2\r
502 // But only Type needs to be checked\r
503 //\r
504 if (FileSize >= MAX_SECTION_SIZE) {\r
505 HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);\r
506 } else {\r
507 HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);\r
508 }\r
509 fread (&TempSectHeader, 1, HeaderSize, InFile);\r
52302d4d
LG
510 if (TempSectHeader.Type == EFI_SECTION_TE) {\r
511 fread (&TeHeader, 1, sizeof (TeHeader), InFile);\r
512 if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
513 TeOffset = TeHeader.StrippedSize - sizeof (TeHeader);\r
514 }\r
515 } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) {\r
516 fseek (InFile, 0, SEEK_SET);\r
e8a47801
LG
517 if (FileSize >= MAX_SECTION_SIZE) {\r
518 fread (&GuidSectHeader2, 1, sizeof (GuidSectHeader2), InFile);\r
519 if ((GuidSectHeader2.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {\r
520 HeaderSize = GuidSectHeader2.DataOffset;\r
521 }\r
522 } else {\r
523 fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile);\r
524 if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {\r
525 HeaderSize = GuidSectHeader.DataOffset;\r
526 }\r
52302d4d
LG
527 }\r
528 } \r
529\r
530 fseek (InFile, 0, SEEK_SET);\r
531\r
532 //\r
533 // Revert TeOffset to the converse value relative to Alignment\r
534 // This is to assure the original PeImage Header at Alignment.\r
535 //\r
536 if (TeOffset != 0) {\r
537 TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]);\r
538 TeOffset = TeOffset % InputFileAlign [Index];\r
539 }\r
540\r
541 //\r
542 // make sure section data meet its alignment requirement by adding one raw pad section.\r
543 //\r
544 if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) {\r
545 Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);\r
546 Offset = Offset - Size - HeaderSize - TeOffset;\r
547 \r
548 if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {\r
e8a47801
LG
549 //\r
550 // The maximal alignment is 64K, the raw section size must be less than 0xffffff\r
551 //\r
52302d4d
LG
552 memset (FileBuffer + Size, 0, Offset);\r
553 SectHeader = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size);\r
554 SectHeader->Type = EFI_SECTION_RAW;\r
555 SectHeader->Size[0] = (UINT8) (Offset & 0xff);\r
556 SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8);\r
557 SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);\r
558 }\r
559 DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset);\r
560\r
561 Size = Size + Offset;\r
562 }\r
563 }\r
564\r
30fdf114
LG
565 //\r
566 // Now read the contents of the file into the buffer\r
567 // Buffer must be enough to contain the file content.\r
568 //\r
52302d4d 569 if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) {\r
30fdf114
LG
570 if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {\r
571 Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);\r
572 fclose (InFile);\r
573 return EFI_ABORTED;\r
574 }\r
575 }\r
576\r
577 fclose (InFile);\r
578 Size += FileSize;\r
579 }\r
580 \r
581 //\r
582 // Set the real required buffer size.\r
583 //\r
584 if (Size > *BufferLength) {\r
585 *BufferLength = Size;\r
586 return EFI_BUFFER_TOO_SMALL;\r
587 } else {\r
588 *BufferLength = Size;\r
589 return EFI_SUCCESS;\r
590 }\r
591}\r
592\r
593EFI_STATUS\r
594GenSectionCompressionSection (\r
595 CHAR8 **InputFileName,\r
52302d4d 596 UINT32 *InputFileAlign,\r
30fdf114
LG
597 UINT32 InputFileNum,\r
598 UINT8 SectCompSubType,\r
599 UINT8 **OutFileBuffer\r
600 )\r
601/*++\r
602 \r
603Routine Description:\r
604 \r
605 Generate an encapsulating section of type EFI_SECTION_COMPRESSION\r
606 Input file must be already sectioned. The function won't validate\r
607 the input files' contents. Caller should hand in files already \r
608 with section header.\r
609 \r
610Arguments:\r
611 \r
612 InputFileName - Name of the input file.\r
52302d4d
LG
613\r
614 InputFileAlign - Alignment required by the input file data.\r
615\r
30fdf114
LG
616 InputFileNum - Number of input files. Should be at least 1.\r
617\r
618 SectCompSubType - Specify the compression algorithm requested. \r
619 \r
620 OutFileBuffer - Buffer pointer to Output file contents\r
621\r
622Returns:\r
623 \r
624 EFI_SUCCESS on successful return\r
625 EFI_INVALID_PARAMETER if InputFileNum is less than 1\r
626 EFI_ABORTED if unable to open input file.\r
627 EFI_OUT_OF_RESOURCES No resource to complete the operation.\r
628--*/\r
629{\r
630 UINT32 TotalLength;\r
631 UINT32 InputLength;\r
632 UINT32 CompressedLength;\r
e8a47801 633 UINT32 HeaderLength;\r
30fdf114
LG
634 UINT8 *FileBuffer;\r
635 UINT8 *OutputBuffer;\r
636 EFI_STATUS Status;\r
637 EFI_COMPRESSION_SECTION *CompressionSect;\r
e8a47801 638 EFI_COMPRESSION_SECTION2 *CompressionSect2;\r
30fdf114
LG
639 COMPRESS_FUNCTION CompressFunction;\r
640\r
641 InputLength = 0;\r
642 FileBuffer = NULL;\r
643 OutputBuffer = NULL;\r
644 CompressedLength = 0;\r
e8a47801 645 TotalLength = 0;\r
30fdf114
LG
646 //\r
647 // read all input file contents into a buffer\r
648 // first get the size of all file contents\r
649 //\r
650 Status = GetSectionContents (\r
651 InputFileName,\r
52302d4d 652 InputFileAlign,\r
30fdf114
LG
653 InputFileNum,\r
654 FileBuffer,\r
655 &InputLength\r
656 );\r
657\r
658 if (Status == EFI_BUFFER_TOO_SMALL) {\r
659 FileBuffer = (UINT8 *) malloc (InputLength);\r
660 if (FileBuffer == NULL) {\r
661 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
662 return EFI_OUT_OF_RESOURCES;\r
663 }\r
664 //\r
665 // read all input file contents into a buffer\r
666 //\r
667 Status = GetSectionContents (\r
668 InputFileName,\r
52302d4d 669 InputFileAlign,\r
30fdf114
LG
670 InputFileNum,\r
671 FileBuffer,\r
672 &InputLength\r
673 );\r
674 }\r
675\r
676 if (EFI_ERROR (Status)) {\r
677 if (FileBuffer != NULL) {\r
678 free (FileBuffer);\r
679 }\r
680 return Status;\r
681 }\r
682\r
248fce03
HW
683 if (FileBuffer == NULL) {\r
684 return EFI_OUT_OF_RESOURCES;\r
685 }\r
686\r
30fdf114
LG
687 CompressFunction = NULL;\r
688\r
689 //\r
690 // Now data is in FileBuffer, compress the data\r
691 //\r
692 switch (SectCompSubType) {\r
693 case EFI_NOT_COMPRESSED:\r
694 CompressedLength = InputLength;\r
e8a47801
LG
695 HeaderLength = sizeof (EFI_COMPRESSION_SECTION);\r
696 if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {\r
697 HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);\r
698 }\r
699 TotalLength = CompressedLength + HeaderLength;\r
52302d4d
LG
700 //\r
701 // Copy file buffer to the none compressed data.\r
702 //\r
e8a47801 703 OutputBuffer = malloc (TotalLength);\r
52302d4d
LG
704 if (OutputBuffer == NULL) {\r
705 free (FileBuffer);\r
706 return EFI_OUT_OF_RESOURCES;\r
707 }\r
e8a47801
LG
708 memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength);\r
709 free (FileBuffer);\r
52302d4d 710 FileBuffer = OutputBuffer;\r
30fdf114
LG
711 break;\r
712\r
713 case EFI_STANDARD_COMPRESSION:\r
714 CompressFunction = (COMPRESS_FUNCTION) EfiCompress;\r
715 break;\r
716\r
717 default:\r
99e55970 718 Error (NULL, 0, 2000, "Invalid parameter", "unknown compression type");\r
30fdf114
LG
719 free (FileBuffer);\r
720 return EFI_ABORTED;\r
721 }\r
722\r
723 if (CompressFunction != NULL) {\r
724\r
725 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);\r
726 if (Status == EFI_BUFFER_TOO_SMALL) {\r
e8a47801
LG
727 HeaderLength = sizeof (EFI_COMPRESSION_SECTION);\r
728 if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {\r
729 HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);\r
730 }\r
731 TotalLength = CompressedLength + HeaderLength;\r
732 OutputBuffer = malloc (TotalLength);\r
30fdf114
LG
733 if (!OutputBuffer) {\r
734 free (FileBuffer);\r
735 return EFI_OUT_OF_RESOURCES;\r
736 }\r
737\r
e8a47801 738 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength);\r
30fdf114
LG
739 }\r
740\r
741 free (FileBuffer);\r
742 FileBuffer = OutputBuffer;\r
743\r
744 if (EFI_ERROR (Status)) {\r
745 if (FileBuffer != NULL) {\r
746 free (FileBuffer);\r
747 }\r
748\r
749 return Status;\r
750 }\r
248fce03
HW
751\r
752 if (FileBuffer == NULL) {\r
753 return EFI_OUT_OF_RESOURCES;\r
754 }\r
30fdf114
LG
755 }\r
756\r
757 DebugMsg (NULL, 0, 9, "comprss file size", \r
fd171542 758 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);\r
e8a47801
LG
759\r
760 //if (TotalLength >= MAX_SECTION_SIZE) {\r
99e55970 761 // Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);\r
e8a47801
LG
762 // if (FileBuffer != NULL) {\r
763 // free (FileBuffer);\r
764 // }\r
765 // if (OutputBuffer != NULL) {\r
766 // free (OutputBuffer);\r
767 // }\r
768 // return STATUS_ERROR;\r
769 //}\r
fd171542 770 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
30fdf114
LG
771\r
772 //\r
773 // Add the section header for the compressed data\r
774 //\r
e8a47801
LG
775 if (TotalLength >= MAX_SECTION_SIZE) {\r
776 CompressionSect2 = (EFI_COMPRESSION_SECTION2 *)FileBuffer;\r
777\r
778 memset(CompressionSect2->CommonHeader.Size, 0xff, sizeof(UINT8) * 3);\r
779 CompressionSect2->CommonHeader.Type = EFI_SECTION_COMPRESSION;\r
780 CompressionSect2->CommonHeader.ExtendedSize = TotalLength;\r
781 CompressionSect2->CompressionType = SectCompSubType;\r
782 CompressionSect2->UncompressedLength = InputLength;\r
783 } else {\r
784 CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;\r
785 \r
786 CompressionSect->CommonHeader.Type = EFI_SECTION_COMPRESSION;\r
787 CompressionSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);\r
788 CompressionSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);\r
789 CompressionSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
790 CompressionSect->CompressionType = SectCompSubType;\r
791 CompressionSect->UncompressedLength = InputLength;\r
792 }\r
30fdf114
LG
793\r
794 //\r
795 // Set OutFileBuffer \r
796 //\r
797 *OutFileBuffer = FileBuffer;\r
798\r
799 return EFI_SUCCESS;\r
800}\r
801\r
802EFI_STATUS\r
803GenSectionGuidDefinedSection (\r
804 CHAR8 **InputFileName,\r
52302d4d 805 UINT32 *InputFileAlign,\r
30fdf114
LG
806 UINT32 InputFileNum,\r
807 EFI_GUID *VendorGuid,\r
808 UINT16 DataAttribute,\r
809 UINT32 DataHeaderSize,\r
810 UINT8 **OutFileBuffer\r
811 )\r
812/*++\r
813 \r
814Routine Description:\r
815 \r
816 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED\r
817 Input file must be already sectioned. The function won't validate\r
818 the input files' contents. Caller should hand in files already \r
819 with section header.\r
820 \r
821Arguments:\r
822 \r
823 InputFileName - Name of the input file.\r
824 \r
52302d4d
LG
825 InputFileAlign - Alignment required by the input file data.\r
826\r
30fdf114
LG
827 InputFileNum - Number of input files. Should be at least 1.\r
828\r
829 VendorGuid - Specify vendor guid value.\r
830\r
831 DataAttribute - Specify attribute for the vendor guid data. \r
832 \r
833 DataHeaderSize- Guided Data Header Size\r
834 \r
835 OutFileBuffer - Buffer pointer to Output file contents\r
836\r
837Returns:\r
838 \r
839 EFI_SUCCESS on successful return\r
840 EFI_INVALID_PARAMETER if InputFileNum is less than 1\r
841 EFI_ABORTED if unable to open input file.\r
842 EFI_OUT_OF_RESOURCES No resource to complete the operation.\r
843\r
844--*/\r
845{\r
846 UINT32 TotalLength;\r
847 UINT32 InputLength;\r
848 UINT32 Offset;\r
849 UINT8 *FileBuffer;\r
850 UINT32 Crc32Checksum;\r
851 EFI_STATUS Status;\r
852 CRC32_SECTION_HEADER *Crc32GuidSect;\r
e8a47801 853 CRC32_SECTION_HEADER2 *Crc32GuidSect2;\r
30fdf114 854 EFI_GUID_DEFINED_SECTION *VendorGuidSect;\r
e8a47801 855 EFI_GUID_DEFINED_SECTION2 *VendorGuidSect2;\r
30fdf114
LG
856\r
857 InputLength = 0;\r
858 Offset = 0;\r
859 FileBuffer = NULL;\r
e8a47801 860 TotalLength = 0;\r
30fdf114
LG
861\r
862 //\r
863 // read all input file contents into a buffer\r
864 // first get the size of all file contents\r
865 //\r
866 Status = GetSectionContents (\r
867 InputFileName,\r
52302d4d 868 InputFileAlign,\r
30fdf114
LG
869 InputFileNum,\r
870 FileBuffer,\r
871 &InputLength\r
872 );\r
873\r
874 if (Status == EFI_BUFFER_TOO_SMALL) {\r
e8a47801
LG
875 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {\r
876 Offset = sizeof (CRC32_SECTION_HEADER);\r
877 if (InputLength + Offset >= MAX_SECTION_SIZE) {\r
878 Offset = sizeof (CRC32_SECTION_HEADER2);\r
879 }\r
880 } else {\r
881 Offset = sizeof (EFI_GUID_DEFINED_SECTION);\r
882 if (InputLength + Offset >= MAX_SECTION_SIZE) {\r
883 Offset = sizeof (EFI_GUID_DEFINED_SECTION2);\r
884 }\r
885 }\r
886 TotalLength = InputLength + Offset;\r
887\r
30fdf114
LG
888 FileBuffer = (UINT8 *) malloc (InputLength + Offset);\r
889 if (FileBuffer == NULL) {\r
890 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
891 return EFI_OUT_OF_RESOURCES;\r
892 }\r
893 //\r
894 // read all input file contents into a buffer\r
895 //\r
896 Status = GetSectionContents (\r
897 InputFileName,\r
52302d4d 898 InputFileAlign,\r
30fdf114
LG
899 InputFileNum,\r
900 FileBuffer + Offset,\r
901 &InputLength\r
902 );\r
903 }\r
904\r
905 if (EFI_ERROR (Status)) {\r
906 if (FileBuffer != NULL) {\r
907 free (FileBuffer);\r
908 }\r
909 Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);\r
910 return Status;\r
911 }\r
912\r
913 if (InputLength == 0) {\r
c52f00d6
HW
914 if (FileBuffer != NULL) {\r
915 free (FileBuffer);\r
916 }\r
30fdf114
LG
917 Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);\r
918 return EFI_NOT_FOUND;\r
919 }\r
920\r
c52f00d6
HW
921 //\r
922 // InputLength != 0, but FileBuffer == NULL means out of resources.\r
923 //\r
924 if (FileBuffer == NULL) {\r
925 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
926 return EFI_OUT_OF_RESOURCES;\r
927 }\r
928\r
30fdf114
LG
929 //\r
930 // Now data is in FileBuffer + Offset\r
931 //\r
25918452 932 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {\r
30fdf114
LG
933 //\r
934 // Default Guid section is CRC32.\r
935 //\r
936 Crc32Checksum = 0;\r
937 CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);\r
e8a47801 938 \r
30fdf114 939 if (TotalLength >= MAX_SECTION_SIZE) {\r
e8a47801
LG
940 Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer;\r
941 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;\r
942 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) 0xff;\r
943 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) 0xff;\r
944 Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) 0xff;\r
945 Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength;\r
946 memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
947 Crc32GuidSect2->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
948 Crc32GuidSect2->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER2);\r
949 Crc32GuidSect2->CRC32Checksum = Crc32Checksum;\r
950 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset);\r
951 } else {\r
952 Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;\r
953 Crc32GuidSect->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;\r
954 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);\r
955 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);\r
956 Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
957 memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
958 Crc32GuidSect->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
959 Crc32GuidSect->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER);\r
960 Crc32GuidSect->CRC32Checksum = Crc32Checksum;\r
961 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);\r
30fdf114 962 }\r
30fdf114 963 } else {\r
30fdf114 964 if (TotalLength >= MAX_SECTION_SIZE) {\r
e8a47801
LG
965 VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer;\r
966 VendorGuidSect2->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;\r
967 VendorGuidSect2->CommonHeader.Size[0] = (UINT8) 0xff;\r
968 VendorGuidSect2->CommonHeader.Size[1] = (UINT8) 0xff;\r
969 VendorGuidSect2->CommonHeader.Size[2] = (UINT8) 0xff;\r
970 VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2);\r
971 memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));\r
972 VendorGuidSect2->Attributes = DataAttribute;\r
973 VendorGuidSect2->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize);\r
974 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset);\r
975 } else {\r
976 VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;\r
977 VendorGuidSect->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;\r
978 VendorGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);\r
979 VendorGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);\r
980 VendorGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
981 memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));\r
982 VendorGuidSect->Attributes = DataAttribute;\r
983 VendorGuidSect->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);\r
984 DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);\r
30fdf114 985 }\r
30fdf114 986 }\r
fd171542 987 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
30fdf114
LG
988 \r
989 //\r
990 // Set OutFileBuffer \r
991 //\r
992 *OutFileBuffer = FileBuffer;\r
993\r
994 return EFI_SUCCESS;\r
995}\r
996\r
9a8d7aa7
FY
997EFI_STATUS\r
998FfsRebaseImageRead (\r
999 IN VOID *FileHandle,\r
1000 IN UINTN FileOffset,\r
1001 IN OUT UINT32 *ReadSize,\r
1002 OUT VOID *Buffer\r
1003 )\r
1004 /*++\r
1005\r
1006 Routine Description:\r
1007\r
1008 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
1009\r
1010 Arguments:\r
1011\r
1012 FileHandle - The handle to the PE/COFF file\r
1013\r
1014 FileOffset - The offset, in bytes, into the file to read\r
1015\r
1016 ReadSize - The number of bytes to read from the file starting at FileOffset\r
1017\r
1018 Buffer - A pointer to the buffer to read the data into.\r
1019\r
1020 Returns:\r
1021\r
1022 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
1023\r
1024 --*/\r
1025{\r
1026 CHAR8 *Destination8;\r
1027 CHAR8 *Source8;\r
1028 UINT32 Length;\r
1029\r
1030 Destination8 = Buffer;\r
1031 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
1032 Length = *ReadSize;\r
1033 while (Length--) {\r
1034 *(Destination8++) = *(Source8++);\r
1035 }\r
1036\r
1037 return EFI_SUCCESS;\r
1038}\r
1039\r
1040STATIC\r
1041EFI_STATUS\r
1042GetAlignmentFromFile(char *InFile, UINT32 *Alignment)\r
1043 /*\r
1044 InFile is input file for getting alignment\r
1045 return the alignment\r
1046 */\r
1047{\r
1048 FILE *InFileHandle;\r
1049 UINT8 *PeFileBuffer;\r
1050 UINTN PeFileSize;\r
1051 UINT32 CurSecHdrSize;\r
1052 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
1053 EFI_COMMON_SECTION_HEADER *CommonHeader;\r
1054 EFI_STATUS Status;\r
1055\r
1056 InFileHandle = NULL;\r
1057 PeFileBuffer = NULL;\r
1058 *Alignment = 0;\r
1059\r
1060 memset (&ImageContext, 0, sizeof (ImageContext));\r
1061\r
1062 InFileHandle = fopen(LongFilePath(InFile), "rb");\r
1063 if (InFileHandle == NULL){\r
1064 Error (NULL, 0, 0001, "Error opening file", InFile);\r
1065 return EFI_ABORTED;\r
1066 }\r
1067 PeFileSize = _filelength (fileno(InFileHandle));\r
1068 PeFileBuffer = (UINT8 *) malloc (PeFileSize);\r
1069 if (PeFileBuffer == NULL) {\r
1070 fclose (InFileHandle);\r
1071 Error(NULL, 0, 4001, "Resource", "memory cannot be allocated of %s", InFileHandle);\r
1072 return EFI_OUT_OF_RESOURCES;\r
1073 }\r
1074 fread (PeFileBuffer, sizeof (UINT8), PeFileSize, InFileHandle);\r
1075 fclose (InFileHandle);\r
1076 CommonHeader = (EFI_COMMON_SECTION_HEADER *) PeFileBuffer;\r
1077 CurSecHdrSize = GetSectionHeaderLength(CommonHeader);\r
1078 ImageContext.Handle = (VOID *) ((UINTN)PeFileBuffer + CurSecHdrSize);\r
1079 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)FfsRebaseImageRead;\r
1080 Status = PeCoffLoaderGetImageInfo(&ImageContext);\r
1081 if (EFI_ERROR (Status)) {\r
1082 Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and return status is %x", InFile, (int) Status);\r
1083 return Status;\r
1084 }\r
1085 *Alignment = ImageContext.SectionAlignment;\r
1086 // Free the allocated memory resource\r
1087 if (PeFileBuffer != NULL) {\r
1088 free (PeFileBuffer);\r
1089 PeFileBuffer = NULL;\r
1090 }\r
1091 return EFI_SUCCESS;\r
1092}\r
1093\r
30fdf114
LG
1094int\r
1095main (\r
1096 int argc,\r
1097 char *argv[]\r
1098 )\r
1099/*++\r
1100\r
1101Routine Description:\r
1102\r
1103 Main\r
1104\r
1105Arguments:\r
1106\r
1107 command line parameters\r
1108\r
1109Returns:\r
1110\r
1111 EFI_SUCCESS Section header successfully generated and section concatenated.\r
1112 EFI_ABORTED Could not generate the section\r
1113 EFI_OUT_OF_RESOURCES No resource to complete the operation.\r
1114\r
1115--*/\r
1116{\r
1117 UINT32 Index;\r
1118 UINT32 InputFileNum;\r
30fdf114
LG
1119 FILE *OutFile;\r
1120 CHAR8 **InputFileName;\r
1121 CHAR8 *OutputFileName;\r
1122 CHAR8 *SectionName;\r
1123 CHAR8 *CompressionName;\r
1124 CHAR8 *StringBuffer;\r
1125 EFI_GUID VendorGuid = mZeroGuid;\r
fd171542 1126 int VersionNumber;\r
30fdf114
LG
1127 UINT8 SectType;\r
1128 UINT8 SectCompSubType;\r
1129 UINT16 SectGuidAttribute; \r
1130 UINT64 SectGuidHeaderLength;\r
1131 EFI_VERSION_SECTION *VersionSect;\r
1132 EFI_USER_INTERFACE_SECTION *UiSect;\r
1133 UINT32 InputLength;\r
1134 UINT8 *OutFileBuffer;\r
1135 EFI_STATUS Status;\r
1136 UINT64 LogLevel;\r
52302d4d
LG
1137 UINT32 *InputFileAlign;\r
1138 UINT32 InputFileAlignNum;\r
e8a47801 1139 EFI_COMMON_SECTION_HEADER *SectionHeader;\r
b37b108d
YZ
1140 CHAR8 *DummyFileName;\r
1141 FILE *DummyFile;\r
1142 UINTN DummyFileSize;\r
1143 UINT8 *DummyFileBuffer;\r
1144 FILE *InFile;\r
1145 UINT8 *InFileBuffer;\r
1146 UINTN InFileSize;\r
52302d4d
LG
1147\r
1148 InputFileAlign = NULL;\r
1149 InputFileAlignNum = 0;\r
30fdf114
LG
1150 InputFileName = NULL;\r
1151 OutputFileName = NULL;\r
1152 SectionName = NULL;\r
1153 CompressionName = NULL;\r
1154 StringBuffer = "";\r
30fdf114
LG
1155 OutFile = NULL;\r
1156 VersionNumber = 0;\r
1157 InputFileNum = 0;\r
1158 SectType = EFI_SECTION_ALL;\r
1159 SectCompSubType = 0;\r
52302d4d 1160 SectGuidAttribute = EFI_GUIDED_SECTION_NONE;\r
30fdf114
LG
1161 OutFileBuffer = NULL;\r
1162 InputLength = 0;\r
1163 Status = STATUS_SUCCESS;\r
1164 LogLevel = 0;\r
1165 SectGuidHeaderLength = 0;\r
1166 VersionSect = NULL;\r
1167 UiSect = NULL;\r
b37b108d
YZ
1168 DummyFileSize = 0;\r
1169 DummyFileName = NULL;\r
1170 DummyFile = NULL;\r
1171 DummyFileBuffer = NULL;\r
1172 InFile = NULL;\r
1173 InFileSize = 0;\r
1174 InFileBuffer = NULL;\r
30fdf114
LG
1175 \r
1176 SetUtilityName (UTILITY_NAME);\r
1177 \r
1178 if (argc == 1) {\r
1179 Error (NULL, 0, 1001, "Missing options", "No options input");\r
1180 Usage ();\r
1181 return STATUS_ERROR;\r
1182 }\r
1183\r
1184 //\r
1185 // Parse command line\r
1186 //\r
1187 argc --;\r
1188 argv ++;\r
1189\r
1190 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
1191 Version ();\r
1192 Usage ();\r
1193 return STATUS_SUCCESS; \r
1194 }\r
1195\r
1196 if (stricmp (argv[0], "--version") == 0) {\r
1197 Version ();\r
1198 return STATUS_SUCCESS; \r
1199 }\r
1200\r
1201 while (argc > 0) {\r
1202 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {\r
1203 SectionName = argv[1];\r
1204 if (SectionName == NULL) {\r
1205 Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");\r
1206 goto Finish;\r
1207 }\r
1208 argc -= 2;\r
1209 argv += 2;\r
1210 continue; \r
1211 }\r
1212\r
1213 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
1214 OutputFileName = argv[1];\r
1215 if (OutputFileName == NULL) {\r
1216 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");\r
1217 goto Finish;\r
1218 }\r
1219 argc -= 2;\r
1220 argv += 2;\r
1221 continue; \r
1222 }\r
1223\r
1224 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {\r
1225 CompressionName = argv[1];\r
1226 if (CompressionName == NULL) {\r
1227 Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");\r
1228 goto Finish;\r
1229 }\r
1230 argc -= 2;\r
1231 argv += 2;\r
1232 continue;\r
1233 }\r
1234\r
1235 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {\r
1236 Status = StringToGuid (argv[1], &VendorGuid);\r
1237 if (EFI_ERROR (Status)) {\r
1238 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1239 goto Finish;\r
1240 }\r
1241 argc -= 2;\r
1242 argv += 2;\r
1243 continue;\r
1244 }\r
b37b108d
YZ
1245 if (stricmp (argv[0], "--dummy") == 0) {\r
1246 DummyFileName = argv[1];\r
1247 if (DummyFileName == NULL) {\r
1248 Error (NULL, 0, 1003, "Invalid option value", "Dummy file can't be NULL");\r
1249 goto Finish;\r
1250 }\r
1251 argc -= 2;\r
1252 argv += 2;\r
1253 continue;\r
1254 }\r
30fdf114
LG
1255\r
1256 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {\r
67f3d099
YZ
1257 if (argv[1] == NULL) {\r
1258 Error (NULL, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL");\r
1259 goto Finish;\r
1260 }\r
30fdf114
LG
1261 if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {\r
1262 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
1263 } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {\r
1264 SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
1265 } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {\r
1266 //\r
1267 // NONE attribute\r
1268 //\r
1269 SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;\r
1270 } else {\r
1271 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1272 goto Finish;\r
1273 }\r
1274 argc -= 2;\r
1275 argv += 2;\r
1276 continue;\r
1277 }\r
1278\r
1279 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {\r
1280 Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);\r
1281 if (EFI_ERROR (Status)) {\r
1282 Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);\r
1283 goto Finish;\r
1284 }\r
1285 argc -= 2;\r
1286 argv += 2;\r
1287 continue;\r
1288 }\r
1289\r
1290 if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {\r
1291 StringBuffer = argv[1];\r
1292 if (StringBuffer == NULL) {\r
1293 Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");\r
1294 goto Finish;\r
1295 }\r
1296 argc -= 2;\r
1297 argv += 2;\r
1298 continue;\r
1299 }\r
1300\r
1301 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {\r
1302 if (argv[1] == NULL) {\r
1303 Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");\r
1304 goto Finish;\r
1305 }\r
1306 //\r
1307 // Verify string is a integrator number\r
1308 //\r
1309 for (Index = 0; Index < strlen (argv[1]); Index++) {\r
a709adfa 1310 if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {\r
30fdf114
LG
1311 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1312 goto Finish;\r
1313 }\r
1314 }\r
1315\r
1316 sscanf (argv[1], "%d", &VersionNumber);\r
1317 argc -= 2;\r
1318 argv += 2;\r
1319 continue;\r
1320 }\r
1321\r
1322 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
1323 SetPrintLevel (VERBOSE_LOG_LEVEL);\r
1324 VerboseMsg ("Verbose output Mode Set!");\r
1325 argc --;\r
1326 argv ++;\r
1327 continue;\r
1328 }\r
1329\r
1330 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
1331 SetPrintLevel (KEY_LOG_LEVEL);\r
1332 KeyMsg ("Quiet output Mode Set!");\r
1333 argc --;\r
1334 argv ++;\r
1335 continue;\r
1336 }\r
1337\r
1338 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
1339 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
1340 if (EFI_ERROR (Status)) {\r
1341 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1342 goto Finish;\r
1343 }\r
1344 if (LogLevel > 9) {\r
fd171542 1345 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel);\r
30fdf114
LG
1346 goto Finish;\r
1347 }\r
1348 SetPrintLevel (LogLevel);\r
1349 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
1350 argc -= 2;\r
1351 argv += 2;\r
1352 continue;\r
1353 }\r
1354\r
52302d4d
LG
1355 //\r
1356 // Section File alignment requirement\r
1357 //\r
1358 if (stricmp (argv[0], "--sectionalign") == 0) {\r
1359 if (InputFileAlignNum == 0) {\r
1360 InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
1361 if (InputFileAlign == NULL) {\r
1362 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
77e4cf5f 1363 goto Finish;\r
52302d4d
LG
1364 }\r
1365 memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
1366 } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1367 InputFileAlign = (UINT32 *) realloc (\r
1368 InputFileAlign,\r
1369 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)\r
1370 );\r
1371\r
1372 if (InputFileAlign == NULL) {\r
1373 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
77e4cf5f 1374 goto Finish;\r
52302d4d
LG
1375 }\r
1376 memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));\r
1377 }\r
9a8d7aa7
FY
1378 if (stricmp(argv[1], "0") == 0) {\r
1379 InputFileAlign[InputFileAlignNum] = 0;\r
1380 } else {\r
1381 Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));\r
1382 if (EFI_ERROR (Status)) {\r
1383 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1384 goto Finish;\r
1385 }\r
52302d4d
LG
1386 }\r
1387 argc -= 2;\r
1388 argv += 2;\r
1389 InputFileAlignNum ++;\r
1390 continue; \r
1391 }\r
1392\r
30fdf114
LG
1393 //\r
1394 // Get Input file name\r
1395 //\r
1396 if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
1397 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
1398 if (InputFileName == NULL) {\r
1399 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
77e4cf5f 1400 goto Finish;\r
30fdf114 1401 }\r
30fdf114
LG
1402 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1403 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1404 //\r
1405 // InputFileName buffer too small, need to realloc\r
1406 //\r
1407 InputFileName = (CHAR8 **) realloc (\r
1408 InputFileName,\r
1409 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
1410 );\r
1411\r
1412 if (InputFileName == NULL) {\r
1413 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
77e4cf5f 1414 goto Finish;\r
30fdf114 1415 }\r
30fdf114
LG
1416 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1417 }\r
1418\r
1419 InputFileName[InputFileNum++] = argv[0];\r
1420 argc --;\r
1421 argv ++;\r
1422 }\r
1423\r
52302d4d
LG
1424 if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {\r
1425 Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");\r
1426 goto Finish;\r
1427 }\r
9a8d7aa7
FY
1428 for (Index = 0; Index < InputFileAlignNum; Index++)\r
1429 {\r
1430 if (InputFileAlign[Index] == 0) {\r
1431 Status = GetAlignmentFromFile(InputFileName[Index], &(InputFileAlign[Index]));\r
1432 if (EFI_ERROR(Status)) {\r
1433 Error (NULL, 0, 1003, "Fail to get Alignment from %s", InputFileName[InputFileNum]);\r
1434 goto Finish;\r
1435 }\r
1436 }\r
1437 }\r
52302d4d 1438\r
30fdf114
LG
1439 VerboseMsg ("%s tool start.", UTILITY_NAME);\r
1440\r
b37b108d
YZ
1441 if (DummyFileName != NULL) {\r
1442 //\r
1443 // Open file and read contents\r
1444 //\r
1445 DummyFile = fopen (LongFilePath (DummyFileName), "rb");\r
1446 if (DummyFile == NULL) {\r
1447 Error (NULL, 0, 0001, "Error opening file", DummyFileName);\r
1e6e6e18 1448 goto Finish;\r
b37b108d
YZ
1449 }\r
1450\r
1451 fseek (DummyFile, 0, SEEK_END);\r
1452 DummyFileSize = ftell (DummyFile);\r
1453 fseek (DummyFile, 0, SEEK_SET);\r
1454 DummyFileBuffer = (UINT8 *) malloc (DummyFileSize);\r
c40dbe5e
HW
1455 if (DummyFileBuffer == NULL) {\r
1456 fclose(DummyFile);\r
1457 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1458 goto Finish;\r
1459 }\r
1460\r
b37b108d
YZ
1461 fread(DummyFileBuffer, 1, DummyFileSize, DummyFile);\r
1462 fclose(DummyFile);\r
1463 DebugMsg (NULL, 0, 9, "Dummy files", "the dummy file name is %s and the size is %u bytes", DummyFileName, (unsigned) DummyFileSize);\r
1464\r
c40dbe5e
HW
1465 if (InputFileName == NULL) {\r
1466 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1467 goto Finish;\r
1468 }\r
b37b108d
YZ
1469 InFile = fopen(LongFilePath(InputFileName[0]), "rb");\r
1470 if (InFile == NULL) {\r
1471 Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);\r
1e6e6e18 1472 goto Finish;\r
b37b108d
YZ
1473 }\r
1474\r
1475 fseek (InFile, 0, SEEK_END);\r
1476 InFileSize = ftell (InFile);\r
1477 fseek (InFile, 0, SEEK_SET);\r
1478 InFileBuffer = (UINT8 *) malloc (InFileSize);\r
c40dbe5e
HW
1479 if (InFileBuffer == NULL) {\r
1480 fclose(InFile);\r
1481 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1482 goto Finish;\r
1483 }\r
1484\r
b37b108d
YZ
1485 fread(InFileBuffer, 1, InFileSize, InFile);\r
1486 fclose(InFile);\r
1487 DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[0], (unsigned) InFileSize);\r
1488 if (InFileSize > DummyFileSize){\r
1e6e6e18 1489 if (stricmp((CHAR8 *)DummyFileBuffer, (CHAR8 *)(InFileBuffer + (InFileSize - DummyFileSize))) == 0){\r
b37b108d
YZ
1490 SectGuidHeaderLength = InFileSize - DummyFileSize;\r
1491 }\r
1492 }\r
1493 if (SectGuidHeaderLength == 0) {\r
1494 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
1495 }\r
1496 if (DummyFileBuffer != NULL) {\r
1497 free (DummyFileBuffer);\r
6ecab5ad 1498 DummyFileBuffer = NULL;\r
b37b108d
YZ
1499 }\r
1500 if (InFileBuffer != NULL) {\r
1501 free (InFileBuffer);\r
1502 }\r
1503 }\r
1504\r
30fdf114
LG
1505 //\r
1506 // Parse all command line parameters to get the corresponding section type.\r
1507 //\r
1508 VerboseMsg ("Section type is %s", SectionName);\r
1509 if (SectionName == NULL) {\r
1510 //\r
1511 // No specified Section type, default is SECTION_ALL.\r
1512 //\r
1513 SectType = EFI_SECTION_ALL;\r
1514 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {\r
1515 SectType = EFI_SECTION_COMPRESSION;\r
1516 if (CompressionName == NULL) {\r
1517 //\r
1518 // Default is PI_STD compression algorithm.\r
1519 //\r
1520 SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1521 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {\r
1522 SectCompSubType = EFI_NOT_COMPRESSED;\r
1523 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {\r
1524 SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1525 } else {\r
1526 Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);\r
1527 goto Finish;\r
1528 }\r
1529 VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);\r
1530 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {\r
1531 SectType = EFI_SECTION_GUID_DEFINED;\r
30fdf114 1532 \r
30fdf114
LG
1533 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {\r
1534 //\r
1535 // NONE attribute, clear attribute value.\r
1536 //\r
52302d4d 1537 SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;\r
30fdf114
LG
1538 }\r
1539 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", \r
fd171542 1540 (unsigned) VendorGuid.Data1,\r
30fdf114
LG
1541 VendorGuid.Data2,\r
1542 VendorGuid.Data3,\r
1543 VendorGuid.Data4[0],\r
1544 VendorGuid.Data4[1],\r
1545 VendorGuid.Data4[2],\r
1546 VendorGuid.Data4[3],\r
1547 VendorGuid.Data4[4],\r
1548 VendorGuid.Data4[5],\r
1549 VendorGuid.Data4[6],\r
1550 VendorGuid.Data4[7]);\r
1551 if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {\r
1552 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);\r
1553 }\r
1554 if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {\r
1555 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);\r
1556 }\r
1557 if (SectGuidHeaderLength != 0) {\r
fd171542 1558 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);\r
30fdf114
LG
1559 }\r
1560 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {\r
1561 SectType = EFI_SECTION_PE32;\r
1562 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {\r
1563 SectType = EFI_SECTION_PIC;\r
1564 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {\r
1565 SectType = EFI_SECTION_TE;\r
1566 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {\r
1567 SectType = EFI_SECTION_DXE_DEPEX;\r
fd171542 1568 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {\r
1569 SectType = EFI_SECTION_SMM_DEPEX;\r
30fdf114
LG
1570 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {\r
1571 SectType = EFI_SECTION_VERSION;\r
e8a47801
LG
1572 if (VersionNumber < 0 || VersionNumber > 65535) {\r
1573 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);\r
30fdf114
LG
1574 goto Finish;\r
1575 }\r
1576 VerboseMsg ("Version section number is %d", VersionNumber);\r
1577 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {\r
1578 SectType = EFI_SECTION_USER_INTERFACE;\r
1579 if (StringBuffer[0] == '\0') {\r
1580 Error (NULL, 0, 1001, "Missing option", "user interface string");\r
1581 goto Finish;\r
1582 }\r
1583 VerboseMsg ("UI section string name is %s", StringBuffer);\r
1584 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {\r
1585 SectType = EFI_SECTION_COMPATIBILITY16;\r
1586 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {\r
1587 SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
1588 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {\r
1589 SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;\r
1590 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {\r
1591 SectType = EFI_SECTION_RAW;\r
1592 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {\r
1593 SectType = EFI_SECTION_PEI_DEPEX;\r
1594 } else {\r
1595 Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);\r
1596 goto Finish;\r
1597 }\r
1598 \r
1599 //\r
1600 // GuidValue is only required by Guided section.\r
1601 //\r
248fce03
HW
1602 if ((SectType != EFI_SECTION_GUID_DEFINED) &&\r
1603 (SectionName != NULL) &&\r
1604 (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
30fdf114
LG
1605 fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);\r
1606 }\r
1607 \r
1608 //\r
1609 // Check whether there is input file\r
1610 // \r
1611 if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {\r
1612 //\r
1613 // The input file are required for other section type.\r
1614 //\r
1615 if (InputFileNum == 0) {\r
1616 Error (NULL, 0, 1001, "Missing options", "Input files");\r
1617 goto Finish;\r
1618 }\r
1619 }\r
1620 //\r
1621 // Check whether there is output file\r
1622 //\r
1623 for (Index = 0; Index < InputFileNum; Index ++) {\r
fd171542 1624 VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);\r
30fdf114
LG
1625 }\r
1626 if (OutputFileName == NULL) {\r
1627 Error (NULL, 0, 1001, "Missing options", "Output file");\r
1628 goto Finish;\r
1629 // OutFile = stdout;\r
1630 }\r
1631 VerboseMsg ("Output file name is %s", OutputFileName);\r
1632\r
1633 //\r
1634 // At this point, we've fully validated the command line, and opened appropriate\r
1635 // files, so let's go and do what we've been asked to do...\r
1636 //\r
1637 //\r
1638 // Within this switch, build and write out the section header including any\r
1639 // section type specific pieces. If there's an input file, it's tacked on later\r
1640 //\r
1641 switch (SectType) {\r
1642 case EFI_SECTION_COMPRESSION:\r
52302d4d
LG
1643 if (InputFileAlign != NULL) {\r
1644 free (InputFileAlign);\r
1645 InputFileAlign = NULL;\r
1646 }\r
30fdf114
LG
1647 Status = GenSectionCompressionSection (\r
1648 InputFileName,\r
52302d4d 1649 InputFileAlign,\r
30fdf114
LG
1650 InputFileNum,\r
1651 SectCompSubType,\r
1652 &OutFileBuffer\r
1653 );\r
1654 break;\r
1655\r
1656 case EFI_SECTION_GUID_DEFINED:\r
25918452 1657 if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
52302d4d
LG
1658 //\r
1659 // Only process alignment for the default known CRC32 guided section.\r
1660 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.\r
1661 //\r
1662 free (InputFileAlign);\r
1663 InputFileAlign = NULL;\r
1664 }\r
30fdf114
LG
1665 Status = GenSectionGuidDefinedSection (\r
1666 InputFileName,\r
52302d4d 1667 InputFileAlign,\r
30fdf114
LG
1668 InputFileNum,\r
1669 &VendorGuid,\r
1670 SectGuidAttribute,\r
1671 (UINT32) SectGuidHeaderLength,\r
1672 &OutFileBuffer\r
1673 );\r
1674 break;\r
1675\r
1676 case EFI_SECTION_VERSION:\r
1677 Index = sizeof (EFI_COMMON_SECTION_HEADER);\r
1678 //\r
1679 // 2 bytes for the build number UINT16\r
1680 //\r
1681 Index += 2;\r
1682 //\r
1683 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1684 //\r
1685 Index += (strlen (StringBuffer) * 2) + 2;\r
1686 OutFileBuffer = (UINT8 *) malloc (Index);\r
1687 if (OutFileBuffer == NULL) {\r
1688 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1689 goto Finish;\r
1690 }\r
1691 VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;\r
1692 VersionSect->CommonHeader.Type = SectType;\r
1693 VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);\r
1694 VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);\r
1695 VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);\r
1696 VersionSect->BuildNumber = (UINT16) VersionNumber;\r
1697 Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);\r
fd171542 1698 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
30fdf114
LG
1699 break;\r
1700\r
1701 case EFI_SECTION_USER_INTERFACE:\r
1702 Index = sizeof (EFI_COMMON_SECTION_HEADER);\r
1703 //\r
1704 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1705 //\r
1706 Index += (strlen (StringBuffer) * 2) + 2;\r
1707 OutFileBuffer = (UINT8 *) malloc (Index);\r
1708 if (OutFileBuffer == NULL) {\r
1709 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1710 goto Finish;\r
1711 }\r
1712 UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;\r
1713 UiSect->CommonHeader.Type = SectType;\r
1714 UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);\r
1715 UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);\r
1716 UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);\r
1717 Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);\r
fd171542 1718 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
30fdf114
LG
1719 break;\r
1720\r
1721 case EFI_SECTION_ALL:\r
1722 //\r
1723 // read all input file contents into a buffer\r
1724 // first get the size of all file contents\r
1725 //\r
1726 Status = GetSectionContents (\r
1727 InputFileName,\r
52302d4d 1728 InputFileAlign,\r
30fdf114
LG
1729 InputFileNum,\r
1730 OutFileBuffer,\r
1731 &InputLength\r
1732 );\r
1733 \r
1734 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1735 OutFileBuffer = (UINT8 *) malloc (InputLength);\r
1736 if (OutFileBuffer == NULL) {\r
1737 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1738 goto Finish;\r
1739 }\r
1740 //\r
1741 // read all input file contents into a buffer\r
1742 //\r
1743 Status = GetSectionContents (\r
1744 InputFileName,\r
52302d4d 1745 InputFileAlign,\r
30fdf114
LG
1746 InputFileNum,\r
1747 OutFileBuffer,\r
1748 &InputLength\r
1749 );\r
1750 }\r
fd171542 1751 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);\r
30fdf114
LG
1752 break;\r
1753 default:\r
1754 //\r
1755 // All other section types are caught by default (they're all the same)\r
1756 //\r
1757 Status = GenSectionCommonLeafSection (\r
1758 InputFileName,\r
1759 InputFileNum,\r
1760 SectType,\r
1761 &OutFileBuffer\r
1762 );\r
1763 break;\r
1764 }\r
1765 \r
1766 if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {\r
fd171542 1767 Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);\r
30fdf114
LG
1768 goto Finish;\r
1769 }\r
1770\r
1771 //\r
1772 // Get output file length\r
1773 //\r
1774 if (SectType != EFI_SECTION_ALL) {\r
e8a47801
LG
1775 SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer;\r
1776 InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff;\r
1777 if (InputLength == 0xffffff) {\r
1778 InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;\r
1779 }\r
30fdf114
LG
1780 }\r
1781 \r
1782 //\r
1783 // Write the output file\r
1784 //\r
1be2ed90 1785 OutFile = fopen (LongFilePath (OutputFileName), "wb");\r
30fdf114
LG
1786 if (OutFile == NULL) {\r
1787 Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);\r
1788 goto Finish;\r
1789 }\r
1790\r
1791 fwrite (OutFileBuffer, InputLength, 1, OutFile);\r
1792\r
1793Finish:\r
1794 if (InputFileName != NULL) {\r
1795 free (InputFileName);\r
1796 }\r
1797\r
52302d4d
LG
1798 if (InputFileAlign != NULL) {\r
1799 free (InputFileAlign);\r
1800 }\r
1801\r
30fdf114
LG
1802 if (OutFileBuffer != NULL) {\r
1803 free (OutFileBuffer);\r
1804 }\r
1805\r
1806 if (OutFile != NULL) {\r
1807 fclose (OutFile);\r
1808 }\r
ae0fbb7f
HW
1809\r
1810 if (DummyFileBuffer != NULL) {\r
1811 free (DummyFileBuffer);\r
1812 }\r
1813\r
30fdf114
LG
1814 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
1815\r
1816 return GetUtilityStatus ();\r
1817}\r