]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/C/GenSec/GenSec.c
BaseTools: argument genfds-multi-thread create GenSec command issue
[mirror_edk2.git] / BaseTools / Source / C / GenSec / GenSec.c
... / ...
CommitLineData
1/** @file\r
2Creates output file that is a properly formed section per the PI spec.\r
3\r
4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials \r
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
13**/\r
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
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
29#include <IndustryStandard/PeImage.h>\r
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
36#include "FvLib.h"\r
37#include "PeCoffLib.h"\r
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
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
83STATIC CHAR8 *mAlignName[] = {\r
84 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",\r
85 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K",\r
86 "512K", "1M", "2M", "4M", "8M", "16M"\r
87};\r
88\r
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
97typedef struct {\r
98 EFI_GUID_DEFINED_SECTION2 GuidSectionHeader;\r
99 UINT32 CRC32Checksum;\r
100} CRC32_SECTION_HEADER2;\r
101\r
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
126 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
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
158 fprintf (stdout, "Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.\n\n");\r
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
174 EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\\r
175 if -s option is not given, \n\\r
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
192 Number is an integer value between 0 and 65535\n\\r
193 used in Ver section.\n");\r
194 fprintf (stdout, " --sectionalign SectionAlign\n\\r
195 SectionAlign points to section alignment, which support\n\\r
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
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
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
278 UINT32 HeaderLength;\r
279 EFI_COMMON_SECTION_HEADER *CommonSect;\r
280 STATUS Status;\r
281\r
282 if (InputFileNum > 1) {\r
283 Error (NULL, 0, 2000, "Invalid parameter", "more than one input file specified");\r
284 return STATUS_ERROR;\r
285 } else if (InputFileNum < 1) {\r
286 Error (NULL, 0, 2000, "Invalid parameter", "no input file specified");\r
287 return STATUS_ERROR;\r
288 }\r
289 //\r
290 // Open the input file\r
291 //\r
292 InFile = fopen (LongFilePath (InputFileName[0]), "rb");\r
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
306 DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName[0], (unsigned) InputFileLength);\r
307 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength;\r
308 //\r
309 // Size must fit in 3 bytes\r
310 //\r
311 //if (TotalLength >= MAX_SECTION_SIZE) {\r
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
313 // goto Done;\r
314 //}\r
315 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER);\r
316 if (TotalLength >= MAX_SECTION_SIZE) {\r
317 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER2) + InputFileLength;\r
318 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER2);\r
319 }\r
320 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
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
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
339 \r
340 //\r
341 // read data from the input file.\r
342 //\r
343 if (InputFileLength != 0) {\r
344 if (fread (Buffer + HeaderLength, (size_t) InputFileLength, 1, InFile) != 1) {\r
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
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
372 Converts Align String to align value (1~16M).\r
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
402EFI_STATUS\r
403GetSectionContents (\r
404 CHAR8 **InputFileName,\r
405 UINT32 *InputFileAlign,\r
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
420\r
421 InputFileAlign - Alignment required by the input file data.\r
422\r
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
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
444 EFI_COMMON_SECTION_HEADER2 TempSectHeader;\r
445 EFI_TE_IMAGE_HEADER TeHeader;\r
446 UINT32 TeOffset;\r
447 EFI_GUID_DEFINED_SECTION GuidSectHeader;\r
448 EFI_GUID_DEFINED_SECTION2 GuidSectHeader2;\r
449 UINT32 HeaderSize;\r
450\r
451 if (InputFileNum < 1) {\r
452 Error (NULL, 0, 2000, "Invalid parameter", "must specify at least one input file");\r
453 return EFI_INVALID_PARAMETER;\r
454 }\r
455\r
456 if (BufferLength == NULL) {\r
457 Error (NULL, 0, 2000, "Invalid parameter", "BufferLength can't be NULL");\r
458 return EFI_INVALID_PARAMETER;\r
459 }\r
460\r
461 Size = 0;\r
462 Offset = 0;\r
463 TeOffset = 0;\r
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
482 InFile = fopen (LongFilePath (InputFileName[Index]), "rb");\r
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
491 DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize); \r
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
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
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
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
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
549 //\r
550 // The maximal alignment is 64K, the raw section size must be less than 0xffffff\r
551 //\r
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
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
569 if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) {\r
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
596 UINT32 *InputFileAlign,\r
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
613\r
614 InputFileAlign - Alignment required by the input file data.\r
615\r
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
633 UINT32 HeaderLength;\r
634 UINT8 *FileBuffer;\r
635 UINT8 *OutputBuffer;\r
636 EFI_STATUS Status;\r
637 EFI_COMPRESSION_SECTION *CompressionSect;\r
638 EFI_COMPRESSION_SECTION2 *CompressionSect2;\r
639 COMPRESS_FUNCTION CompressFunction;\r
640\r
641 InputLength = 0;\r
642 FileBuffer = NULL;\r
643 OutputBuffer = NULL;\r
644 CompressedLength = 0;\r
645 TotalLength = 0;\r
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
652 InputFileAlign,\r
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
669 InputFileAlign,\r
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
683 if (FileBuffer == NULL) {\r
684 return EFI_OUT_OF_RESOURCES;\r
685 }\r
686\r
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
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
700 //\r
701 // Copy file buffer to the none compressed data.\r
702 //\r
703 OutputBuffer = malloc (TotalLength);\r
704 if (OutputBuffer == NULL) {\r
705 free (FileBuffer);\r
706 return EFI_OUT_OF_RESOURCES;\r
707 }\r
708 memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength);\r
709 free (FileBuffer);\r
710 FileBuffer = OutputBuffer;\r
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
718 Error (NULL, 0, 2000, "Invalid parameter", "unknown compression type");\r
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
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
733 if (!OutputBuffer) {\r
734 free (FileBuffer);\r
735 return EFI_OUT_OF_RESOURCES;\r
736 }\r
737\r
738 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength);\r
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
751\r
752 if (FileBuffer == NULL) {\r
753 return EFI_OUT_OF_RESOURCES;\r
754 }\r
755 }\r
756\r
757 DebugMsg (NULL, 0, 9, "comprss file size", \r
758 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);\r
759\r
760 //if (TotalLength >= MAX_SECTION_SIZE) {\r
761 // Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);\r
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
770 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
771\r
772 //\r
773 // Add the section header for the compressed data\r
774 //\r
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
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
805 UINT32 *InputFileAlign,\r
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
825 InputFileAlign - Alignment required by the input file data.\r
826\r
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
853 CRC32_SECTION_HEADER2 *Crc32GuidSect2;\r
854 EFI_GUID_DEFINED_SECTION *VendorGuidSect;\r
855 EFI_GUID_DEFINED_SECTION2 *VendorGuidSect2;\r
856\r
857 InputLength = 0;\r
858 Offset = 0;\r
859 FileBuffer = NULL;\r
860 TotalLength = 0;\r
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
868 InputFileAlign,\r
869 InputFileNum,\r
870 FileBuffer,\r
871 &InputLength\r
872 );\r
873\r
874 if (Status == EFI_BUFFER_TOO_SMALL) {\r
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
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
898 InputFileAlign,\r
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
914 if (FileBuffer != NULL) {\r
915 free (FileBuffer);\r
916 }\r
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
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
929 //\r
930 // Now data is in FileBuffer + Offset\r
931 //\r
932 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {\r
933 //\r
934 // Default Guid section is CRC32.\r
935 //\r
936 Crc32Checksum = 0;\r
937 CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);\r
938 \r
939 if (TotalLength >= MAX_SECTION_SIZE) {\r
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
962 }\r
963 } else {\r
964 if (TotalLength >= MAX_SECTION_SIZE) {\r
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
985 }\r
986 }\r
987 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
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
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
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
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
1126 int VersionNumber;\r
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
1137 UINT32 *InputFileAlign;\r
1138 UINT32 InputFileAlignNum;\r
1139 EFI_COMMON_SECTION_HEADER *SectionHeader;\r
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
1147\r
1148 InputFileAlign = NULL;\r
1149 InputFileAlignNum = 0;\r
1150 InputFileName = NULL;\r
1151 OutputFileName = NULL;\r
1152 SectionName = NULL;\r
1153 CompressionName = NULL;\r
1154 StringBuffer = "";\r
1155 OutFile = NULL;\r
1156 VersionNumber = 0;\r
1157 InputFileNum = 0;\r
1158 SectType = EFI_SECTION_ALL;\r
1159 SectCompSubType = 0;\r
1160 SectGuidAttribute = EFI_GUIDED_SECTION_NONE;\r
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
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
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
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
1255\r
1256 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {\r
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
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
1310 if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {\r
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
1345 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel);\r
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
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
1363 goto Finish;\r
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
1374 goto Finish;\r
1375 }\r
1376 memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));\r
1377 }\r
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
1386 }\r
1387 argc -= 2;\r
1388 argv += 2;\r
1389 InputFileAlignNum ++;\r
1390 continue; \r
1391 }\r
1392\r
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
1400 goto Finish;\r
1401 }\r
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
1414 goto Finish;\r
1415 }\r
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
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
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
1438\r
1439 VerboseMsg ("%s tool start.", UTILITY_NAME);\r
1440\r
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
1448 goto Finish;\r
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
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
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
1465 if (InputFileName == NULL) {\r
1466 Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
1467 goto Finish;\r
1468 }\r
1469 InFile = fopen(LongFilePath(InputFileName[0]), "rb");\r
1470 if (InFile == NULL) {\r
1471 Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);\r
1472 goto Finish;\r
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
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
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
1489 if (stricmp((CHAR8 *)DummyFileBuffer, (CHAR8 *)(InFileBuffer + (InFileSize - DummyFileSize))) == 0){\r
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
1498 DummyFileBuffer = NULL;\r
1499 }\r
1500 if (InFileBuffer != NULL) {\r
1501 free (InFileBuffer);\r
1502 }\r
1503 }\r
1504\r
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
1532 \r
1533 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {\r
1534 //\r
1535 // NONE attribute, clear attribute value.\r
1536 //\r
1537 SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;\r
1538 }\r
1539 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", \r
1540 (unsigned) VendorGuid.Data1,\r
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
1558 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);\r
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
1568 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {\r
1569 SectType = EFI_SECTION_SMM_DEPEX;\r
1570 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {\r
1571 SectType = EFI_SECTION_VERSION;\r
1572 if (VersionNumber < 0 || VersionNumber > 65535) {\r
1573 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);\r
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
1602 if ((SectType != EFI_SECTION_GUID_DEFINED) &&\r
1603 (SectionName != NULL) &&\r
1604 (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
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
1624 VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);\r
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
1643 if (InputFileAlign != NULL) {\r
1644 free (InputFileAlign);\r
1645 InputFileAlign = NULL;\r
1646 }\r
1647 Status = GenSectionCompressionSection (\r
1648 InputFileName,\r
1649 InputFileAlign,\r
1650 InputFileNum,\r
1651 SectCompSubType,\r
1652 &OutFileBuffer\r
1653 );\r
1654 break;\r
1655\r
1656 case EFI_SECTION_GUID_DEFINED:\r
1657 if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
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
1665 Status = GenSectionGuidDefinedSection (\r
1666 InputFileName,\r
1667 InputFileAlign,\r
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
1698 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
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
1718 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
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
1728 InputFileAlign,\r
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
1745 InputFileAlign,\r
1746 InputFileNum,\r
1747 OutFileBuffer,\r
1748 &InputLength\r
1749 );\r
1750 }\r
1751 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);\r
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
1767 Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);\r
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
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
1780 }\r
1781 \r
1782 //\r
1783 // Write the output file\r
1784 //\r
1785 OutFile = fopen (LongFilePath (OutputFileName), "wb");\r
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
1798 if (InputFileAlign != NULL) {\r
1799 free (InputFileAlign);\r
1800 }\r
1801\r
1802 if (OutFileBuffer != NULL) {\r
1803 free (OutFileBuffer);\r
1804 }\r
1805\r
1806 if (OutFile != NULL) {\r
1807 fclose (OutFile);\r
1808 }\r
1809\r
1810 if (DummyFileBuffer != NULL) {\r
1811 free (DummyFileBuffer);\r
1812 }\r
1813\r
1814 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
1815\r
1816 return GetUtilityStatus ();\r
1817}\r