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