]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenSec/GenSec.c
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / C / GenSec / GenSec.c
CommitLineData
30fdf114 1/** @file\r
97fa0ee9 2Creates output file that is a properly formed section per the PI spec.\r
30fdf114 3\r
6ecab5ad 4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
2e351cbe 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
30fdf114 6\r
30fdf114 7**/\r
9a8d7aa7
FY
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
30fdf114
LG
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
52302d4d 23#include <IndustryStandard/PeImage.h>\r
30fdf114
LG
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
9a8d7aa7
FY
30#include "FvLib.h"\r
31#include "PeCoffLib.h"\r
30fdf114
LG
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
30fdf114
LG
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
52302d4d
LG
77STATIC CHAR8 *mAlignName[] = {\r
78 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",\r
e921f58d
YZ
79 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K",\r
80 "512K", "1M", "2M", "4M", "8M", "16M"\r
52302d4d
LG
81};\r
82\r
30fdf114
LG
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
e8a47801
LG
91typedef struct {\r
92 EFI_GUID_DEFINED_SECTION2 GuidSectionHeader;\r
93 UINT32 CRC32Checksum;\r
94} CRC32_SECTION_HEADER2;\r
95\r
30fdf114
LG
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
f7496d71 100VOID\r
30fdf114
LG
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
f7496d71 113\r
30fdf114
LG
114Returns:\r
115\r
116 None\r
f7496d71
LG
117\r
118--*/\r
30fdf114 119{\r
b36d134f 120 fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
30fdf114
LG
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
f7496d71 148\r
30fdf114
LG
149 //\r
150 // Copyright declaration\r
f7496d71
LG
151 //\r
152 fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");\r
30fdf114
LG
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
fd171542 168 EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\\r
169 if -s option is not given, \n\\r
30fdf114
LG
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
f7496d71 173 if -c option is not given, PI_STD is default type.\n");\r
30fdf114
LG
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
e8a47801 186 Number is an integer value between 0 and 65535\n\\r
30fdf114 187 used in Ver section.\n");\r
52302d4d
LG
188 fprintf (stdout, " --sectionalign SectionAlign\n\\r
189 SectionAlign points to section alignment, which support\n\\r
9a8d7aa7
FY
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
b37b108d
YZ
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
30fdf114
LG
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
f7496d71 212 Write ascii string as unicode string format to FILE\r
30fdf114
LG
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
f7496d71 232}\r
30fdf114
LG
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
f7496d71 242\r
30fdf114 243Routine Description:\r
f7496d71 244\r
30fdf114
LG
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
f7496d71 250\r
30fdf114 251Arguments:\r
f7496d71 252\r
30fdf114 253 InputFileName - Name of the input file.\r
f7496d71 254\r
30fdf114
LG
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
f7496d71 262\r
30fdf114
LG
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
e8a47801 272 UINT32 HeaderLength;\r
30fdf114
LG
273 EFI_COMMON_SECTION_HEADER *CommonSect;\r
274 STATUS Status;\r
275\r
276 if (InputFileNum > 1) {\r
99e55970 277 Error (NULL, 0, 2000, "Invalid parameter", "more than one input file specified");\r
30fdf114
LG
278 return STATUS_ERROR;\r
279 } else if (InputFileNum < 1) {\r
99e55970 280 Error (NULL, 0, 2000, "Invalid parameter", "no input file specified");\r
30fdf114
LG
281 return STATUS_ERROR;\r
282 }\r
283 //\r
284 // Open the input file\r
285 //\r
1be2ed90 286 InFile = fopen (LongFilePath (InputFileName[0]), "rb");\r
30fdf114
LG
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
fd171542 300 DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName[0], (unsigned) InputFileLength);\r
30fdf114
LG
301 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength;\r
302 //\r
303 // Size must fit in 3 bytes\r
304 //\r
e8a47801 305 //if (TotalLength >= MAX_SECTION_SIZE) {\r
99e55970 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
e8a47801
LG
307 // goto Done;\r
308 //}\r
309 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER);\r
30fdf114 310 if (TotalLength >= MAX_SECTION_SIZE) {\r
e8a47801
LG
311 TotalLength = sizeof (EFI_COMMON_SECTION_HEADER2) + InputFileLength;\r
312 HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER2);\r
30fdf114 313 }\r
fd171542 314 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
30fdf114
LG
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
fb0b35e0 320 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
30fdf114
LG
321 goto Done;\r
322 }\r
323 CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer;\r
324 CommonSect->Type = SectionType;\r
e8a47801
LG
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
f7496d71 333\r
30fdf114
LG
334 //\r
335 // read data from the input file.\r
336 //\r
337 if (InputFileLength != 0) {\r
e8a47801 338 if (fread (Buffer + HeaderLength, (size_t) InputFileLength, 1, InFile) != 1) {\r
30fdf114
LG
339 Error (NULL, 0, 0004, "Error reading file", InputFileName[0]);\r
340 goto Done;\r
341 }\r
342 }\r
343\r
344 //\r
f7496d71 345 // Set OutFileBuffer\r
30fdf114
LG
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
52302d4d
LG
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
e921f58d 366 Converts Align String to align value (1~16M).\r
52302d4d
LG
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
30fdf114
LG
396EFI_STATUS\r
397GetSectionContents (\r
398 CHAR8 **InputFileName,\r
52302d4d 399 UINT32 *InputFileAlign,\r
30fdf114
LG
400 UINT32 InputFileNum,\r
401 UINT8 *FileBuffer,\r
402 UINT32 *BufferLength\r
403 )\r
404/*++\r
f7496d71 405\r
30fdf114 406Routine Description:\r
f7496d71 407\r
30fdf114
LG
408 Get the contents of all section files specified in InputFileName\r
409 into FileBuffer.\r
f7496d71 410\r
30fdf114 411Arguments:\r
f7496d71 412\r
30fdf114 413 InputFileName - Name of the input file.\r
52302d4d
LG
414\r
415 InputFileAlign - Alignment required by the input file data.\r
416\r
30fdf114
LG
417 InputFileNum - Number of input files. Should be at least 1.\r
418\r
419 FileBuffer - Output buffer to contain data\r
420\r
f7496d71 421 BufferLength - On input, this is size of the FileBuffer.\r
30fdf114
LG
422 On output, this is the actual length of the data.\r
423\r
424Returns:\r
f7496d71 425\r
30fdf114
LG
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
52302d4d
LG
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
e8a47801 438 EFI_COMMON_SECTION_HEADER2 TempSectHeader;\r
52302d4d
LG
439 EFI_TE_IMAGE_HEADER TeHeader;\r
440 UINT32 TeOffset;\r
441 EFI_GUID_DEFINED_SECTION GuidSectHeader;\r
e8a47801 442 EFI_GUID_DEFINED_SECTION2 GuidSectHeader2;\r
52302d4d 443 UINT32 HeaderSize;\r
30fdf114
LG
444\r
445 if (InputFileNum < 1) {\r
99e55970 446 Error (NULL, 0, 2000, "Invalid parameter", "must specify at least one input file");\r
30fdf114
LG
447 return EFI_INVALID_PARAMETER;\r
448 }\r
449\r
450 if (BufferLength == NULL) {\r
99e55970 451 Error (NULL, 0, 2000, "Invalid parameter", "BufferLength can't be NULL");\r
30fdf114
LG
452 return EFI_INVALID_PARAMETER;\r
453 }\r
454\r
52302d4d
LG
455 Size = 0;\r
456 Offset = 0;\r
457 TeOffset = 0;\r
30fdf114
LG
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
f7496d71
LG
472\r
473 //\r
30fdf114
LG
474 // Open file and read contents\r
475 //\r
1be2ed90 476 InFile = fopen (LongFilePath (InputFileName[Index]), "rb");\r
30fdf114
LG
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
f7496d71 485 DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize);\r
52302d4d
LG
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
e8a47801
LG
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
52302d4d
LG
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
e8a47801
LG
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
52302d4d 521 }\r
f7496d71 522 }\r
52302d4d
LG
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
f7496d71 541\r
52302d4d 542 if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {\r
e8a47801
LG
543 //\r
544 // The maximal alignment is 64K, the raw section size must be less than 0xffffff\r
545 //\r
52302d4d
LG
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
30fdf114
LG
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
52302d4d 563 if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) {\r
30fdf114
LG
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
f7496d71 574\r
30fdf114
LG
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
52302d4d 590 UINT32 *InputFileAlign,\r
30fdf114
LG
591 UINT32 InputFileNum,\r
592 UINT8 SectCompSubType,\r
593 UINT8 **OutFileBuffer\r
594 )\r
595/*++\r
f7496d71 596\r
30fdf114 597Routine Description:\r
f7496d71 598\r
30fdf114
LG
599 Generate an encapsulating section of type EFI_SECTION_COMPRESSION\r
600 Input file must be already sectioned. The function won't validate\r
f7496d71 601 the input files' contents. Caller should hand in files already\r
30fdf114 602 with section header.\r
f7496d71 603\r
30fdf114 604Arguments:\r
f7496d71 605\r
30fdf114 606 InputFileName - Name of the input file.\r
52302d4d
LG
607\r
608 InputFileAlign - Alignment required by the input file data.\r
609\r
30fdf114
LG
610 InputFileNum - Number of input files. Should be at least 1.\r
611\r
f7496d71
LG
612 SectCompSubType - Specify the compression algorithm requested.\r
613\r
30fdf114
LG
614 OutFileBuffer - Buffer pointer to Output file contents\r
615\r
616Returns:\r
f7496d71 617\r
30fdf114
LG
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
e8a47801 627 UINT32 HeaderLength;\r
30fdf114
LG
628 UINT8 *FileBuffer;\r
629 UINT8 *OutputBuffer;\r
630 EFI_STATUS Status;\r
631 EFI_COMPRESSION_SECTION *CompressionSect;\r
e8a47801 632 EFI_COMPRESSION_SECTION2 *CompressionSect2;\r
30fdf114
LG
633 COMPRESS_FUNCTION CompressFunction;\r
634\r
635 InputLength = 0;\r
636 FileBuffer = NULL;\r
637 OutputBuffer = NULL;\r
638 CompressedLength = 0;\r
e8a47801 639 TotalLength = 0;\r
30fdf114
LG
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
52302d4d 646 InputFileAlign,\r
30fdf114
LG
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
fb0b35e0 655 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
30fdf114
LG
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
52302d4d 663 InputFileAlign,\r
30fdf114
LG
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
248fce03
HW
677 if (FileBuffer == NULL) {\r
678 return EFI_OUT_OF_RESOURCES;\r
679 }\r
680\r
30fdf114
LG
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
e8a47801
LG
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
52302d4d
LG
694 //\r
695 // Copy file buffer to the none compressed data.\r
696 //\r
e8a47801 697 OutputBuffer = malloc (TotalLength);\r
52302d4d
LG
698 if (OutputBuffer == NULL) {\r
699 free (FileBuffer);\r
700 return EFI_OUT_OF_RESOURCES;\r
701 }\r
e8a47801
LG
702 memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength);\r
703 free (FileBuffer);\r
52302d4d 704 FileBuffer = OutputBuffer;\r
30fdf114
LG
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
99e55970 712 Error (NULL, 0, 2000, "Invalid parameter", "unknown compression type");\r
30fdf114
LG
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
e8a47801
LG
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
30fdf114
LG
727 if (!OutputBuffer) {\r
728 free (FileBuffer);\r
729 return EFI_OUT_OF_RESOURCES;\r
730 }\r
731\r
e8a47801 732 Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength);\r
30fdf114
LG
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
248fce03
HW
745\r
746 if (FileBuffer == NULL) {\r
747 return EFI_OUT_OF_RESOURCES;\r
748 }\r
30fdf114
LG
749 }\r
750\r
f7496d71 751 DebugMsg (NULL, 0, 9, "comprss file size",\r
fd171542 752 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);\r
e8a47801
LG
753\r
754 //if (TotalLength >= MAX_SECTION_SIZE) {\r
99e55970 755 // Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);\r
e8a47801
LG
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
fd171542 764 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
30fdf114
LG
765\r
766 //\r
767 // Add the section header for the compressed data\r
768 //\r
e8a47801
LG
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
f7496d71 779\r
e8a47801
LG
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
30fdf114
LG
787\r
788 //\r
f7496d71 789 // Set OutFileBuffer\r
30fdf114
LG
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
52302d4d 799 UINT32 *InputFileAlign,\r
30fdf114
LG
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
f7496d71 807\r
30fdf114 808Routine Description:\r
f7496d71 809\r
30fdf114
LG
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
f7496d71 812 the input files' contents. Caller should hand in files already\r
30fdf114 813 with section header.\r
f7496d71 814\r
30fdf114 815Arguments:\r
f7496d71 816\r
30fdf114 817 InputFileName - Name of the input file.\r
f7496d71 818\r
52302d4d
LG
819 InputFileAlign - Alignment required by the input file data.\r
820\r
30fdf114
LG
821 InputFileNum - Number of input files. Should be at least 1.\r
822\r
823 VendorGuid - Specify vendor guid value.\r
824\r
f7496d71
LG
825 DataAttribute - Specify attribute for the vendor guid data.\r
826\r
30fdf114 827 DataHeaderSize- Guided Data Header Size\r
f7496d71 828\r
30fdf114
LG
829 OutFileBuffer - Buffer pointer to Output file contents\r
830\r
831Returns:\r
f7496d71 832\r
30fdf114
LG
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
e8a47801 847 CRC32_SECTION_HEADER2 *Crc32GuidSect2;\r
30fdf114 848 EFI_GUID_DEFINED_SECTION *VendorGuidSect;\r
e8a47801 849 EFI_GUID_DEFINED_SECTION2 *VendorGuidSect2;\r
30fdf114
LG
850\r
851 InputLength = 0;\r
852 Offset = 0;\r
853 FileBuffer = NULL;\r
e8a47801 854 TotalLength = 0;\r
30fdf114
LG
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
52302d4d 862 InputFileAlign,\r
30fdf114
LG
863 InputFileNum,\r
864 FileBuffer,\r
865 &InputLength\r
866 );\r
867\r
868 if (Status == EFI_BUFFER_TOO_SMALL) {\r
e8a47801
LG
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
30fdf114
LG
882 FileBuffer = (UINT8 *) malloc (InputLength + Offset);\r
883 if (FileBuffer == NULL) {\r
fb0b35e0 884 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
30fdf114
LG
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
52302d4d 892 InputFileAlign,\r
30fdf114
LG
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
c52f00d6
HW
908 if (FileBuffer != NULL) {\r
909 free (FileBuffer);\r
910 }\r
30fdf114
LG
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
c52f00d6
HW
915 //\r
916 // InputLength != 0, but FileBuffer == NULL means out of resources.\r
917 //\r
918 if (FileBuffer == NULL) {\r
fb0b35e0 919 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
c52f00d6
HW
920 return EFI_OUT_OF_RESOURCES;\r
921 }\r
922\r
30fdf114
LG
923 //\r
924 // Now data is in FileBuffer + Offset\r
925 //\r
25918452 926 if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {\r
30fdf114
LG
927 //\r
928 // Default Guid section is CRC32.\r
929 //\r
930 Crc32Checksum = 0;\r
931 CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);\r
f7496d71 932\r
30fdf114 933 if (TotalLength >= MAX_SECTION_SIZE) {\r
e8a47801
LG
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
30fdf114 956 }\r
30fdf114 957 } else {\r
30fdf114 958 if (TotalLength >= MAX_SECTION_SIZE) {\r
e8a47801
LG
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
30fdf114 979 }\r
30fdf114 980 }\r
fd171542 981 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
f7496d71 982\r
30fdf114 983 //\r
f7496d71 984 // Set OutFileBuffer\r
30fdf114
LG
985 //\r
986 *OutFileBuffer = FileBuffer;\r
987\r
988 return EFI_SUCCESS;\r
989}\r
990\r
9a8d7aa7
FY
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
30fdf114
LG
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
30fdf114
LG
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
fd171542 1120 int VersionNumber;\r
30fdf114
LG
1121 UINT8 SectType;\r
1122 UINT8 SectCompSubType;\r
f7496d71 1123 UINT16 SectGuidAttribute;\r
30fdf114
LG
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
52302d4d
LG
1131 UINT32 *InputFileAlign;\r
1132 UINT32 InputFileAlignNum;\r
e8a47801 1133 EFI_COMMON_SECTION_HEADER *SectionHeader;\r
b37b108d
YZ
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
52302d4d
LG
1141\r
1142 InputFileAlign = NULL;\r
1143 InputFileAlignNum = 0;\r
30fdf114
LG
1144 InputFileName = NULL;\r
1145 OutputFileName = NULL;\r
1146 SectionName = NULL;\r
1147 CompressionName = NULL;\r
1148 StringBuffer = "";\r
30fdf114
LG
1149 OutFile = NULL;\r
1150 VersionNumber = 0;\r
1151 InputFileNum = 0;\r
1152 SectType = EFI_SECTION_ALL;\r
1153 SectCompSubType = 0;\r
52302d4d 1154 SectGuidAttribute = EFI_GUIDED_SECTION_NONE;\r
30fdf114
LG
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
b37b108d
YZ
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
f7496d71 1169\r
30fdf114 1170 SetUtilityName (UTILITY_NAME);\r
f7496d71 1171\r
30fdf114
LG
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
f7496d71 1187 return STATUS_SUCCESS;\r
30fdf114
LG
1188 }\r
1189\r
1190 if (stricmp (argv[0], "--version") == 0) {\r
1191 Version ();\r
f7496d71 1192 return STATUS_SUCCESS;\r
30fdf114
LG
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
f7496d71 1204 continue;\r
30fdf114
LG
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
f7496d71 1215 continue;\r
30fdf114
LG
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
b37b108d
YZ
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
30fdf114
LG
1249\r
1250 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {\r
67f3d099
YZ
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
30fdf114
LG
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
a709adfa 1304 if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {\r
30fdf114
LG
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
fb0b35e0 1339 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, current input level is %d", (int) LogLevel);\r
30fdf114
LG
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
52302d4d
LG
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
77e4cf5f 1357 goto Finish;\r
52302d4d
LG
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
77e4cf5f 1368 goto Finish;\r
52302d4d
LG
1369 }\r
1370 memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));\r
1371 }\r
9a8d7aa7
FY
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
52302d4d
LG
1380 }\r
1381 argc -= 2;\r
1382 argv += 2;\r
1383 InputFileAlignNum ++;\r
f7496d71 1384 continue;\r
52302d4d
LG
1385 }\r
1386\r
30fdf114
LG
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
fb0b35e0 1393 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
77e4cf5f 1394 goto Finish;\r
30fdf114 1395 }\r
30fdf114
LG
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
fb0b35e0 1407 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
77e4cf5f 1408 goto Finish;\r
30fdf114 1409 }\r
30fdf114
LG
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
52302d4d
LG
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
9a8d7aa7
FY
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
52302d4d 1432\r
30fdf114
LG
1433 VerboseMsg ("%s tool start.", UTILITY_NAME);\r
1434\r
b37b108d
YZ
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
1e6e6e18 1442 goto Finish;\r
b37b108d
YZ
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
c40dbe5e
HW
1449 if (DummyFileBuffer == NULL) {\r
1450 fclose(DummyFile);\r
fb0b35e0 1451 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
c40dbe5e
HW
1452 goto Finish;\r
1453 }\r
1454\r
b37b108d
YZ
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
c40dbe5e 1459 if (InputFileName == NULL) {\r
fb0b35e0 1460 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
c40dbe5e
HW
1461 goto Finish;\r
1462 }\r
b37b108d
YZ
1463 InFile = fopen(LongFilePath(InputFileName[0]), "rb");\r
1464 if (InFile == NULL) {\r
1465 Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);\r
1e6e6e18 1466 goto Finish;\r
b37b108d
YZ
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
c40dbe5e
HW
1473 if (InFileBuffer == NULL) {\r
1474 fclose(InFile);\r
fb0b35e0 1475 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
c40dbe5e
HW
1476 goto Finish;\r
1477 }\r
1478\r
b37b108d
YZ
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
1e6e6e18 1483 if (stricmp((CHAR8 *)DummyFileBuffer, (CHAR8 *)(InFileBuffer + (InFileSize - DummyFileSize))) == 0){\r
b37b108d
YZ
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
6ecab5ad 1492 DummyFileBuffer = NULL;\r
b37b108d
YZ
1493 }\r
1494 if (InFileBuffer != NULL) {\r
1495 free (InFileBuffer);\r
1496 }\r
1497 }\r
1498\r
30fdf114
LG
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
f7496d71 1526\r
30fdf114
LG
1527 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {\r
1528 //\r
1529 // NONE attribute, clear attribute value.\r
1530 //\r
52302d4d 1531 SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;\r
30fdf114 1532 }\r
f7496d71 1533 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",\r
fd171542 1534 (unsigned) VendorGuid.Data1,\r
30fdf114
LG
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
fd171542 1552 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);\r
30fdf114
LG
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
fd171542 1562 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {\r
1563 SectType = EFI_SECTION_SMM_DEPEX;\r
30fdf114
LG
1564 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {\r
1565 SectType = EFI_SECTION_VERSION;\r
e8a47801
LG
1566 if (VersionNumber < 0 || VersionNumber > 65535) {\r
1567 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);\r
30fdf114
LG
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
f7496d71 1592\r
30fdf114
LG
1593 //\r
1594 // GuidValue is only required by Guided section.\r
1595 //\r
248fce03
HW
1596 if ((SectType != EFI_SECTION_GUID_DEFINED) &&\r
1597 (SectionName != NULL) &&\r
1598 (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
30fdf114
LG
1599 fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);\r
1600 }\r
f7496d71 1601\r
30fdf114
LG
1602 //\r
1603 // Check whether there is input file\r
f7496d71 1604 //\r
30fdf114
LG
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
fd171542 1618 VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);\r
30fdf114
LG
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
52302d4d
LG
1637 if (InputFileAlign != NULL) {\r
1638 free (InputFileAlign);\r
1639 InputFileAlign = NULL;\r
1640 }\r
30fdf114
LG
1641 Status = GenSectionCompressionSection (\r
1642 InputFileName,\r
52302d4d 1643 InputFileAlign,\r
30fdf114
LG
1644 InputFileNum,\r
1645 SectCompSubType,\r
1646 &OutFileBuffer\r
1647 );\r
1648 break;\r
1649\r
1650 case EFI_SECTION_GUID_DEFINED:\r
25918452 1651 if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
52302d4d
LG
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
30fdf114
LG
1659 Status = GenSectionGuidDefinedSection (\r
1660 InputFileName,\r
52302d4d 1661 InputFileAlign,\r
30fdf114
LG
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
fb0b35e0 1682 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
30fdf114
LG
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
fd171542 1692 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
30fdf114
LG
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
fb0b35e0 1703 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
30fdf114
LG
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
fd171542 1712 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
30fdf114
LG
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
52302d4d 1722 InputFileAlign,\r
30fdf114
LG
1723 InputFileNum,\r
1724 OutFileBuffer,\r
1725 &InputLength\r
1726 );\r
f7496d71 1727\r
30fdf114
LG
1728 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1729 OutFileBuffer = (UINT8 *) malloc (InputLength);\r
1730 if (OutFileBuffer == NULL) {\r
fb0b35e0 1731 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
30fdf114
LG
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
52302d4d 1739 InputFileAlign,\r
30fdf114
LG
1740 InputFileNum,\r
1741 OutFileBuffer,\r
1742 &InputLength\r
1743 );\r
1744 }\r
fd171542 1745 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);\r
30fdf114
LG
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
f7496d71 1759\r
30fdf114 1760 if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {\r
fd171542 1761 Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);\r
f7496d71 1762 goto Finish;\r
30fdf114
LG
1763 }\r
1764\r
1765 //\r
1766 // Get output file length\r
1767 //\r
1768 if (SectType != EFI_SECTION_ALL) {\r
e8a47801
LG
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
30fdf114 1774 }\r
f7496d71 1775\r
30fdf114
LG
1776 //\r
1777 // Write the output file\r
1778 //\r
1be2ed90 1779 OutFile = fopen (LongFilePath (OutputFileName), "wb");\r
30fdf114
LG
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
52302d4d
LG
1792 if (InputFileAlign != NULL) {\r
1793 free (InputFileAlign);\r
1794 }\r
1795\r
30fdf114
LG
1796 if (OutFileBuffer != NULL) {\r
1797 free (OutFileBuffer);\r
1798 }\r
1799\r
1800 if (OutFile != NULL) {\r
1801 fclose (OutFile);\r
1802 }\r
ae0fbb7f
HW
1803\r
1804 if (DummyFileBuffer != NULL) {\r
1805 free (DummyFileBuffer);\r
1806 }\r
1807\r
30fdf114
LG
1808 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
1809\r
1810 return GetUtilityStatus ();\r
1811}\r