]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/C/GenSec/GenSec.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 attributes, 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 dummyfile 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
992GenSectionSubtypeGuidSection (\r
993 CHAR8 **InputFileName,\r
994 UINT32 *InputFileAlign,\r
995 UINT32 InputFileNum,\r
996 EFI_GUID *SubTypeGuid,\r
997 UINT8 **OutFileBuffer\r
998 )\r
999/*++\r
1000\r
1001Routine Description:\r
1002\r
1003 Generate a section of type EFI_SECTION_FREEFORM_SUBTYPE_GUID\r
1004 The function won't validate the input file contents.\r
1005 The utility will add section header to the file.\r
1006\r
1007Arguments:\r
1008\r
1009 InputFileName - Name of the input file.\r
1010\r
1011 InputFileAlign - Alignment required by the input file data.\r
1012\r
1013 InputFileNum - Number of input files. Should be 1 for this section.\r
1014\r
1015 SubTypeGuid - Specify vendor guid value.\r
1016\r
1017 OutFileBuffer - Buffer pointer to Output file contents\r
1018\r
1019Returns:\r
1020\r
1021 EFI_SUCCESS on successful return\r
1022 EFI_INVALID_PARAMETER if InputFileNum is less than 1\r
1023 EFI_ABORTED if unable to open input file.\r
1024 EFI_OUT_OF_RESOURCES No resource to complete the operation.\r
1025\r
1026--*/\r
1027{\r
1028 UINT32 TotalLength;\r
1029 UINT32 InputLength;\r
1030 UINT32 Offset;\r
1031 UINT8 *FileBuffer;\r
1032 EFI_STATUS Status;\r
1033 EFI_FREEFORM_SUBTYPE_GUID_SECTION *SubtypeGuidSect;\r
1034 EFI_FREEFORM_SUBTYPE_GUID_SECTION2 *SubtypeGuidSect2;\r
1035\r
1036\r
1037 InputLength = 0;\r
1038 Offset = 0;\r
1039 FileBuffer = NULL;\r
1040 TotalLength = 0;\r
1041\r
1042 if (InputFileNum > 1) {\r
1043 Error (NULL, 0, 2000, "Invalid parameter", "more than one input file specified");\r
1044 return STATUS_ERROR;\r
1045 } else if (InputFileNum < 1) {\r
1046 Error (NULL, 0, 2000, "Invalid parameter", "no input file specified");\r
1047 return STATUS_ERROR;\r
1048 }\r
1049\r
1050 //\r
1051 // read all input file contents into a buffer\r
1052 // first get the size of all file contents\r
1053 //\r
1054 Status = GetSectionContents (\r
1055 InputFileName,\r
1056 InputFileAlign,\r
1057 InputFileNum,\r
1058 FileBuffer,\r
1059 &InputLength\r
1060 );\r
1061\r
1062 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1063 Offset = sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION);\r
1064 if (InputLength + Offset >= MAX_SECTION_SIZE) {\r
1065 Offset = sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION2);\r
1066 }\r
1067 TotalLength = InputLength + Offset;\r
1068\r
1069 FileBuffer = (UINT8 *) malloc (InputLength + Offset);\r
1070 if (FileBuffer == NULL) {\r
1071 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
1072 return EFI_OUT_OF_RESOURCES;\r
1073 }\r
1074 //\r
1075 // read all input file contents into a buffer\r
1076 //\r
1077 Status = GetSectionContents (\r
1078 InputFileName,\r
1079 InputFileAlign,\r
1080 InputFileNum,\r
1081 FileBuffer + Offset,\r
1082 &InputLength\r
1083 );\r
1084 }\r
1085\r
1086 if (EFI_ERROR (Status)) {\r
1087 if (FileBuffer != NULL) {\r
1088 free (FileBuffer);\r
1089 }\r
1090 Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);\r
1091 return Status;\r
1092 }\r
1093\r
1094 if (InputLength == 0) {\r
1095 if (FileBuffer != NULL) {\r
1096 free (FileBuffer);\r
1097 }\r
1098 Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", *InputFileName);\r
1099 return EFI_NOT_FOUND;\r
1100 }\r
1101\r
1102 //\r
1103 // InputLength != 0, but FileBuffer == NULL means out of resources.\r
1104 //\r
1105 if (FileBuffer == NULL) {\r
1106 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
1107 return EFI_OUT_OF_RESOURCES;\r
1108 }\r
1109\r
1110 //\r
1111 // Now data is in FileBuffer + Offset\r
1112 //\r
1113 if (TotalLength >= MAX_SECTION_SIZE) {\r
1114 SubtypeGuidSect2 = (EFI_FREEFORM_SUBTYPE_GUID_SECTION2 *) FileBuffer;\r
1115 SubtypeGuidSect2->CommonHeader.Type = EFI_SECTION_FREEFORM_SUBTYPE_GUID;\r
1116 SubtypeGuidSect2->CommonHeader.Size[0] = (UINT8) 0xff;\r
1117 SubtypeGuidSect2->CommonHeader.Size[1] = (UINT8) 0xff;\r
1118 SubtypeGuidSect2->CommonHeader.Size[2] = (UINT8) 0xff;\r
1119 SubtypeGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION2);\r
1120 memcpy (&(SubtypeGuidSect2->SubTypeGuid), SubTypeGuid, sizeof (EFI_GUID));\r
1121 } else {\r
1122 SubtypeGuidSect = (EFI_FREEFORM_SUBTYPE_GUID_SECTION *) FileBuffer;\r
1123 SubtypeGuidSect->CommonHeader.Type = EFI_SECTION_FREEFORM_SUBTYPE_GUID;\r
1124 SubtypeGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);\r
1125 SubtypeGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);\r
1126 SubtypeGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);\r
1127 memcpy (&(SubtypeGuidSect->SubTypeGuid), SubTypeGuid, sizeof (EFI_GUID));\r
1128 }\r
1129\r
1130 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);\r
1131\r
1132 //\r
1133 // Set OutFileBuffer\r
1134 //\r
1135 *OutFileBuffer = FileBuffer;\r
1136\r
1137 return EFI_SUCCESS;\r
1138}\r
1139\r
1140EFI_STATUS\r
1141FfsRebaseImageRead (\r
1142 IN VOID *FileHandle,\r
1143 IN UINTN FileOffset,\r
1144 IN OUT UINT32 *ReadSize,\r
1145 OUT VOID *Buffer\r
1146 )\r
1147 /*++\r
1148\r
1149 Routine Description:\r
1150\r
1151 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
1152\r
1153 Arguments:\r
1154\r
1155 FileHandle - The handle to the PE/COFF file\r
1156\r
1157 FileOffset - The offset, in bytes, into the file to read\r
1158\r
1159 ReadSize - The number of bytes to read from the file starting at FileOffset\r
1160\r
1161 Buffer - A pointer to the buffer to read the data into.\r
1162\r
1163 Returns:\r
1164\r
1165 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
1166\r
1167 --*/\r
1168{\r
1169 CHAR8 *Destination8;\r
1170 CHAR8 *Source8;\r
1171 UINT32 Length;\r
1172\r
1173 Destination8 = Buffer;\r
1174 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
1175 Length = *ReadSize;\r
1176 while (Length--) {\r
1177 *(Destination8++) = *(Source8++);\r
1178 }\r
1179\r
1180 return EFI_SUCCESS;\r
1181}\r
1182\r
1183STATIC\r
1184EFI_STATUS\r
1185GetAlignmentFromFile(char *InFile, UINT32 *Alignment)\r
1186 /*\r
1187 InFile is input file for getting alignment\r
1188 return the alignment\r
1189 */\r
1190{\r
1191 FILE *InFileHandle;\r
1192 UINT8 *PeFileBuffer;\r
1193 UINTN PeFileSize;\r
1194 UINT32 CurSecHdrSize;\r
1195 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
1196 EFI_COMMON_SECTION_HEADER *CommonHeader;\r
1197 EFI_STATUS Status;\r
1198\r
1199 InFileHandle = NULL;\r
1200 PeFileBuffer = NULL;\r
1201 *Alignment = 0;\r
1202\r
1203 memset (&ImageContext, 0, sizeof (ImageContext));\r
1204\r
1205 InFileHandle = fopen(LongFilePath(InFile), "rb");\r
1206 if (InFileHandle == NULL){\r
1207 Error (NULL, 0, 0001, "Error opening file", InFile);\r
1208 return EFI_ABORTED;\r
1209 }\r
1210 PeFileSize = _filelength (fileno(InFileHandle));\r
1211 PeFileBuffer = (UINT8 *) malloc (PeFileSize);\r
1212 if (PeFileBuffer == NULL) {\r
1213 fclose (InFileHandle);\r
1214 Error(NULL, 0, 4001, "Resource", "memory cannot be allocated for %s", InFile);\r
1215 return EFI_OUT_OF_RESOURCES;\r
1216 }\r
1217 fread (PeFileBuffer, sizeof (UINT8), PeFileSize, InFileHandle);\r
1218 fclose (InFileHandle);\r
1219 CommonHeader = (EFI_COMMON_SECTION_HEADER *) PeFileBuffer;\r
1220 CurSecHdrSize = GetSectionHeaderLength(CommonHeader);\r
1221 ImageContext.Handle = (VOID *) ((UINTN)PeFileBuffer + CurSecHdrSize);\r
1222 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)FfsRebaseImageRead;\r
1223 Status = PeCoffLoaderGetImageInfo(&ImageContext);\r
1224 if (EFI_ERROR (Status)) {\r
1225 Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and return status is %x", InFile, (int) Status);\r
1226 return Status;\r
1227 }\r
1228 *Alignment = ImageContext.SectionAlignment;\r
1229 // Free the allocated memory resource\r
1230 if (PeFileBuffer != NULL) {\r
1231 free (PeFileBuffer);\r
1232 PeFileBuffer = NULL;\r
1233 }\r
1234 return EFI_SUCCESS;\r
1235}\r
1236\r
1237int\r
1238main (\r
1239 int argc,\r
1240 char *argv[]\r
1241 )\r
1242/*++\r
1243\r
1244Routine Description:\r
1245\r
1246 Main\r
1247\r
1248Arguments:\r
1249\r
1250 command line parameters\r
1251\r
1252Returns:\r
1253\r
1254 EFI_SUCCESS Section header successfully generated and section concatenated.\r
1255 EFI_ABORTED Could not generate the section\r
1256 EFI_OUT_OF_RESOURCES No resource to complete the operation.\r
1257\r
1258--*/\r
1259{\r
1260 UINT32 Index;\r
1261 UINT32 InputFileNum;\r
1262 FILE *OutFile;\r
1263 CHAR8 **InputFileName;\r
1264 CHAR8 *OutputFileName;\r
1265 CHAR8 *SectionName;\r
1266 CHAR8 *CompressionName;\r
1267 CHAR8 *StringBuffer;\r
1268 EFI_GUID VendorGuid = mZeroGuid;\r
1269 int VersionNumber;\r
1270 UINT8 SectType;\r
1271 UINT8 SectCompSubType;\r
1272 UINT16 SectGuidAttribute;\r
1273 UINT64 SectGuidHeaderLength;\r
1274 EFI_VERSION_SECTION *VersionSect;\r
1275 EFI_USER_INTERFACE_SECTION *UiSect;\r
1276 UINT32 InputLength;\r
1277 UINT8 *OutFileBuffer;\r
1278 EFI_STATUS Status;\r
1279 UINT64 LogLevel;\r
1280 UINT32 *InputFileAlign;\r
1281 UINT32 InputFileAlignNum;\r
1282 EFI_COMMON_SECTION_HEADER *SectionHeader;\r
1283 CHAR8 *DummyFileName;\r
1284 FILE *DummyFile;\r
1285 UINTN DummyFileSize;\r
1286 UINT8 *DummyFileBuffer;\r
1287 FILE *InFile;\r
1288 UINT8 *InFileBuffer;\r
1289 UINTN InFileSize;\r
1290\r
1291 InputFileAlign = NULL;\r
1292 InputFileAlignNum = 0;\r
1293 InputFileName = NULL;\r
1294 OutputFileName = NULL;\r
1295 SectionName = NULL;\r
1296 CompressionName = NULL;\r
1297 StringBuffer = "";\r
1298 OutFile = NULL;\r
1299 VersionNumber = 0;\r
1300 InputFileNum = 0;\r
1301 SectType = EFI_SECTION_ALL;\r
1302 SectCompSubType = 0;\r
1303 SectGuidAttribute = EFI_GUIDED_SECTION_NONE;\r
1304 OutFileBuffer = NULL;\r
1305 InputLength = 0;\r
1306 Status = STATUS_SUCCESS;\r
1307 LogLevel = 0;\r
1308 SectGuidHeaderLength = 0;\r
1309 VersionSect = NULL;\r
1310 UiSect = NULL;\r
1311 DummyFileSize = 0;\r
1312 DummyFileName = NULL;\r
1313 DummyFile = NULL;\r
1314 DummyFileBuffer = NULL;\r
1315 InFile = NULL;\r
1316 InFileSize = 0;\r
1317 InFileBuffer = NULL;\r
1318\r
1319 SetUtilityName (UTILITY_NAME);\r
1320\r
1321 if (argc == 1) {\r
1322 Error (NULL, 0, 1001, "Missing options", "No options input");\r
1323 Usage ();\r
1324 return STATUS_ERROR;\r
1325 }\r
1326\r
1327 //\r
1328 // Parse command line\r
1329 //\r
1330 argc --;\r
1331 argv ++;\r
1332\r
1333 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
1334 Version ();\r
1335 Usage ();\r
1336 return STATUS_SUCCESS;\r
1337 }\r
1338\r
1339 if (stricmp (argv[0], "--version") == 0) {\r
1340 Version ();\r
1341 return STATUS_SUCCESS;\r
1342 }\r
1343\r
1344 while (argc > 0) {\r
1345 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {\r
1346 SectionName = argv[1];\r
1347 if (SectionName == NULL) {\r
1348 Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");\r
1349 goto Finish;\r
1350 }\r
1351 argc -= 2;\r
1352 argv += 2;\r
1353 continue;\r
1354 }\r
1355\r
1356 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
1357 OutputFileName = argv[1];\r
1358 if (OutputFileName == NULL) {\r
1359 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");\r
1360 goto Finish;\r
1361 }\r
1362 argc -= 2;\r
1363 argv += 2;\r
1364 continue;\r
1365 }\r
1366\r
1367 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {\r
1368 CompressionName = argv[1];\r
1369 if (CompressionName == NULL) {\r
1370 Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");\r
1371 goto Finish;\r
1372 }\r
1373 argc -= 2;\r
1374 argv += 2;\r
1375 continue;\r
1376 }\r
1377\r
1378 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {\r
1379 Status = StringToGuid (argv[1], &VendorGuid);\r
1380 if (EFI_ERROR (Status)) {\r
1381 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1382 goto Finish;\r
1383 }\r
1384 argc -= 2;\r
1385 argv += 2;\r
1386 continue;\r
1387 }\r
1388 if (stricmp (argv[0], "--dummy") == 0) {\r
1389 DummyFileName = argv[1];\r
1390 if (DummyFileName == NULL) {\r
1391 Error (NULL, 0, 1003, "Invalid option value", "Dummy file can't be NULL");\r
1392 goto Finish;\r
1393 }\r
1394 argc -= 2;\r
1395 argv += 2;\r
1396 continue;\r
1397 }\r
1398\r
1399 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {\r
1400 if (argv[1] == NULL) {\r
1401 Error (NULL, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL");\r
1402 goto Finish;\r
1403 }\r
1404 if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {\r
1405 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
1406 } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {\r
1407 SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;\r
1408 } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {\r
1409 //\r
1410 // NONE attribute\r
1411 //\r
1412 SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;\r
1413 } else {\r
1414 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1415 goto Finish;\r
1416 }\r
1417 argc -= 2;\r
1418 argv += 2;\r
1419 continue;\r
1420 }\r
1421\r
1422 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {\r
1423 Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);\r
1424 if (EFI_ERROR (Status)) {\r
1425 Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);\r
1426 goto Finish;\r
1427 }\r
1428 argc -= 2;\r
1429 argv += 2;\r
1430 continue;\r
1431 }\r
1432\r
1433 if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {\r
1434 StringBuffer = argv[1];\r
1435 if (StringBuffer == NULL) {\r
1436 Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");\r
1437 goto Finish;\r
1438 }\r
1439 argc -= 2;\r
1440 argv += 2;\r
1441 continue;\r
1442 }\r
1443\r
1444 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {\r
1445 if (argv[1] == NULL) {\r
1446 Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");\r
1447 goto Finish;\r
1448 }\r
1449 //\r
1450 // Verify string is a integrator number\r
1451 //\r
1452 for (Index = 0; Index < strlen (argv[1]); Index++) {\r
1453 if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {\r
1454 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1455 goto Finish;\r
1456 }\r
1457 }\r
1458\r
1459 sscanf (argv[1], "%d", &VersionNumber);\r
1460 argc -= 2;\r
1461 argv += 2;\r
1462 continue;\r
1463 }\r
1464\r
1465 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
1466 SetPrintLevel (VERBOSE_LOG_LEVEL);\r
1467 VerboseMsg ("Verbose output Mode Set!");\r
1468 argc --;\r
1469 argv ++;\r
1470 continue;\r
1471 }\r
1472\r
1473 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
1474 SetPrintLevel (KEY_LOG_LEVEL);\r
1475 KeyMsg ("Quiet output Mode Set!");\r
1476 argc --;\r
1477 argv ++;\r
1478 continue;\r
1479 }\r
1480\r
1481 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
1482 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
1483 if (EFI_ERROR (Status)) {\r
1484 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1485 goto Finish;\r
1486 }\r
1487 if (LogLevel > 9) {\r
1488 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, current input level is %d", (int) LogLevel);\r
1489 goto Finish;\r
1490 }\r
1491 SetPrintLevel (LogLevel);\r
1492 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
1493 argc -= 2;\r
1494 argv += 2;\r
1495 continue;\r
1496 }\r
1497\r
1498 //\r
1499 // Section File alignment requirement\r
1500 //\r
1501 if (stricmp (argv[0], "--sectionalign") == 0) {\r
1502 if (InputFileAlignNum == 0) {\r
1503 InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
1504 if (InputFileAlign == NULL) {\r
1505 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1506 goto Finish;\r
1507 }\r
1508 memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
1509 } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1510 InputFileAlign = (UINT32 *) realloc (\r
1511 InputFileAlign,\r
1512 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)\r
1513 );\r
1514\r
1515 if (InputFileAlign == NULL) {\r
1516 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1517 goto Finish;\r
1518 }\r
1519 memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));\r
1520 }\r
1521 if (stricmp(argv[1], "0") == 0) {\r
1522 InputFileAlign[InputFileAlignNum] = 0;\r
1523 } else {\r
1524 Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));\r
1525 if (EFI_ERROR (Status)) {\r
1526 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1527 goto Finish;\r
1528 }\r
1529 }\r
1530 argc -= 2;\r
1531 argv += 2;\r
1532 InputFileAlignNum ++;\r
1533 continue;\r
1534 }\r
1535\r
1536 //\r
1537 // Get Input file name\r
1538 //\r
1539 if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
1540 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
1541 if (InputFileName == NULL) {\r
1542 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
1543 goto Finish;\r
1544 }\r
1545 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1546 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1547 //\r
1548 // InputFileName buffer too small, need to realloc\r
1549 //\r
1550 InputFileName = (CHAR8 **) realloc (\r
1551 InputFileName,\r
1552 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
1553 );\r
1554\r
1555 if (InputFileName == NULL) {\r
1556 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
1557 goto Finish;\r
1558 }\r
1559 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1560 }\r
1561\r
1562 InputFileName[InputFileNum++] = argv[0];\r
1563 argc --;\r
1564 argv ++;\r
1565 }\r
1566\r
1567 if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {\r
1568 Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");\r
1569 goto Finish;\r
1570 }\r
1571 for (Index = 0; Index < InputFileAlignNum; Index++)\r
1572 {\r
1573 if (InputFileAlign[Index] == 0) {\r
1574 Status = GetAlignmentFromFile(InputFileName[Index], &(InputFileAlign[Index]));\r
1575 if (EFI_ERROR(Status)) {\r
1576 Error (NULL, 0, 1003, "Fail to get Alignment from %s", InputFileName[InputFileNum]);\r
1577 goto Finish;\r
1578 }\r
1579 }\r
1580 }\r
1581\r
1582 VerboseMsg ("%s tool start.", UTILITY_NAME);\r
1583\r
1584 if (DummyFileName != NULL) {\r
1585 //\r
1586 // Open file and read contents\r
1587 //\r
1588 DummyFile = fopen (LongFilePath (DummyFileName), "rb");\r
1589 if (DummyFile == NULL) {\r
1590 Error (NULL, 0, 0001, "Error opening file", DummyFileName);\r
1591 goto Finish;\r
1592 }\r
1593\r
1594 fseek (DummyFile, 0, SEEK_END);\r
1595 DummyFileSize = ftell (DummyFile);\r
1596 fseek (DummyFile, 0, SEEK_SET);\r
1597 DummyFileBuffer = (UINT8 *) malloc (DummyFileSize);\r
1598 if (DummyFileBuffer == NULL) {\r
1599 fclose(DummyFile);\r
1600 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
1601 goto Finish;\r
1602 }\r
1603\r
1604 fread(DummyFileBuffer, 1, DummyFileSize, DummyFile);\r
1605 fclose(DummyFile);\r
1606 DebugMsg (NULL, 0, 9, "Dummy files", "the dummy file name is %s and the size is %u bytes", DummyFileName, (unsigned) DummyFileSize);\r
1607\r
1608 if (InputFileName == NULL) {\r
1609 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
1610 goto Finish;\r
1611 }\r
1612 InFile = fopen(LongFilePath(InputFileName[0]), "rb");\r
1613 if (InFile == NULL) {\r
1614 Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);\r
1615 goto Finish;\r
1616 }\r
1617\r
1618 fseek (InFile, 0, SEEK_END);\r
1619 InFileSize = ftell (InFile);\r
1620 fseek (InFile, 0, SEEK_SET);\r
1621 InFileBuffer = (UINT8 *) malloc (InFileSize);\r
1622 if (InFileBuffer == NULL) {\r
1623 fclose(InFile);\r
1624 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
1625 goto Finish;\r
1626 }\r
1627\r
1628 fread(InFileBuffer, 1, InFileSize, InFile);\r
1629 fclose(InFile);\r
1630 DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[0], (unsigned) InFileSize);\r
1631 if (InFileSize > DummyFileSize){\r
1632 if (stricmp((CHAR8 *)DummyFileBuffer, (CHAR8 *)(InFileBuffer + (InFileSize - DummyFileSize))) == 0){\r
1633 SectGuidHeaderLength = InFileSize - DummyFileSize;\r
1634 }\r
1635 }\r
1636 if (SectGuidHeaderLength == 0) {\r
1637 SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
1638 }\r
1639 if (DummyFileBuffer != NULL) {\r
1640 free (DummyFileBuffer);\r
1641 DummyFileBuffer = NULL;\r
1642 }\r
1643 if (InFileBuffer != NULL) {\r
1644 free (InFileBuffer);\r
1645 }\r
1646 }\r
1647\r
1648 //\r
1649 // Parse all command line parameters to get the corresponding section type.\r
1650 //\r
1651 VerboseMsg ("Section type is %s", SectionName);\r
1652 if (SectionName == NULL) {\r
1653 //\r
1654 // No specified Section type, default is SECTION_ALL.\r
1655 //\r
1656 SectType = EFI_SECTION_ALL;\r
1657 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {\r
1658 SectType = EFI_SECTION_COMPRESSION;\r
1659 if (CompressionName == NULL) {\r
1660 //\r
1661 // Default is PI_STD compression algorithm.\r
1662 //\r
1663 SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1664 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {\r
1665 SectCompSubType = EFI_NOT_COMPRESSED;\r
1666 } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {\r
1667 SectCompSubType = EFI_STANDARD_COMPRESSION;\r
1668 } else {\r
1669 Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);\r
1670 goto Finish;\r
1671 }\r
1672 VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);\r
1673 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {\r
1674 SectType = EFI_SECTION_GUID_DEFINED;\r
1675\r
1676 if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {\r
1677 //\r
1678 // NONE attribute, clear attribute value.\r
1679 //\r
1680 SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;\r
1681 }\r
1682 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",\r
1683 (unsigned) VendorGuid.Data1,\r
1684 VendorGuid.Data2,\r
1685 VendorGuid.Data3,\r
1686 VendorGuid.Data4[0],\r
1687 VendorGuid.Data4[1],\r
1688 VendorGuid.Data4[2],\r
1689 VendorGuid.Data4[3],\r
1690 VendorGuid.Data4[4],\r
1691 VendorGuid.Data4[5],\r
1692 VendorGuid.Data4[6],\r
1693 VendorGuid.Data4[7]);\r
1694 if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {\r
1695 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);\r
1696 }\r
1697 if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {\r
1698 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);\r
1699 }\r
1700 if (SectGuidHeaderLength != 0) {\r
1701 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);\r
1702 }\r
1703 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {\r
1704 SectType = EFI_SECTION_PE32;\r
1705 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {\r
1706 SectType = EFI_SECTION_PIC;\r
1707 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {\r
1708 SectType = EFI_SECTION_TE;\r
1709 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {\r
1710 SectType = EFI_SECTION_DXE_DEPEX;\r
1711 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {\r
1712 SectType = EFI_SECTION_SMM_DEPEX;\r
1713 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {\r
1714 SectType = EFI_SECTION_VERSION;\r
1715 if (VersionNumber < 0 || VersionNumber > 65535) {\r
1716 Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);\r
1717 goto Finish;\r
1718 }\r
1719 VerboseMsg ("Version section number is %d", VersionNumber);\r
1720 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {\r
1721 SectType = EFI_SECTION_USER_INTERFACE;\r
1722 if (StringBuffer[0] == '\0') {\r
1723 Error (NULL, 0, 1001, "Missing option", "user interface string");\r
1724 goto Finish;\r
1725 }\r
1726 VerboseMsg ("UI section string name is %s", StringBuffer);\r
1727 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {\r
1728 SectType = EFI_SECTION_COMPATIBILITY16;\r
1729 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {\r
1730 SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
1731 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {\r
1732 SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;\r
1733 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {\r
1734 SectType = EFI_SECTION_RAW;\r
1735 } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {\r
1736 SectType = EFI_SECTION_PEI_DEPEX;\r
1737 } else {\r
1738 Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);\r
1739 goto Finish;\r
1740 }\r
1741\r
1742 //\r
1743 // GuidValue is only required by Guided section and SubtypeGuid section.\r
1744 //\r
1745 if ((SectType != EFI_SECTION_GUID_DEFINED) && (SectType != EFI_SECTION_FREEFORM_SUBTYPE_GUID) &&\r
1746 (SectionName != NULL) &&\r
1747 (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
1748 fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);\r
1749 }\r
1750\r
1751 //\r
1752 // Check whether there is GUID for the SubtypeGuid section\r
1753 //\r
1754 if ((SectType == EFI_SECTION_FREEFORM_SUBTYPE_GUID) && (CompareGuid (&VendorGuid, &mZeroGuid) == 0)) {\r
1755 Error (NULL, 0, 1001, "Missing options", "GUID");\r
1756 goto Finish;\r
1757 }\r
1758\r
1759 //\r
1760 // Check whether there is input file\r
1761 //\r
1762 if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {\r
1763 //\r
1764 // The input file are required for other section type.\r
1765 //\r
1766 if (InputFileNum == 0) {\r
1767 Error (NULL, 0, 1001, "Missing options", "Input files");\r
1768 goto Finish;\r
1769 }\r
1770 }\r
1771 //\r
1772 // Check whether there is output file\r
1773 //\r
1774 for (Index = 0; Index < InputFileNum; Index ++) {\r
1775 VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);\r
1776 }\r
1777 if (OutputFileName == NULL) {\r
1778 Error (NULL, 0, 1001, "Missing options", "Output file");\r
1779 goto Finish;\r
1780 // OutFile = stdout;\r
1781 }\r
1782 VerboseMsg ("Output file name is %s", OutputFileName);\r
1783\r
1784 //\r
1785 // At this point, we've fully validated the command line, and opened appropriate\r
1786 // files, so let's go and do what we've been asked to do...\r
1787 //\r
1788 //\r
1789 // Within this switch, build and write out the section header including any\r
1790 // section type specific pieces. If there's an input file, it's tacked on later\r
1791 //\r
1792 switch (SectType) {\r
1793 case EFI_SECTION_COMPRESSION:\r
1794 if (InputFileAlign != NULL) {\r
1795 free (InputFileAlign);\r
1796 InputFileAlign = NULL;\r
1797 }\r
1798 Status = GenSectionCompressionSection (\r
1799 InputFileName,\r
1800 InputFileAlign,\r
1801 InputFileNum,\r
1802 SectCompSubType,\r
1803 &OutFileBuffer\r
1804 );\r
1805 break;\r
1806\r
1807 case EFI_SECTION_GUID_DEFINED:\r
1808 if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {\r
1809 //\r
1810 // Only process alignment for the default known CRC32 guided section.\r
1811 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.\r
1812 //\r
1813 free (InputFileAlign);\r
1814 InputFileAlign = NULL;\r
1815 }\r
1816 Status = GenSectionGuidDefinedSection (\r
1817 InputFileName,\r
1818 InputFileAlign,\r
1819 InputFileNum,\r
1820 &VendorGuid,\r
1821 SectGuidAttribute,\r
1822 (UINT32) SectGuidHeaderLength,\r
1823 &OutFileBuffer\r
1824 );\r
1825 break;\r
1826\r
1827 case EFI_SECTION_FREEFORM_SUBTYPE_GUID:\r
1828 Status = GenSectionSubtypeGuidSection (\r
1829 InputFileName,\r
1830 InputFileAlign,\r
1831 InputFileNum,\r
1832 &VendorGuid,\r
1833 &OutFileBuffer\r
1834 );\r
1835 break;\r
1836\r
1837 case EFI_SECTION_VERSION:\r
1838 Index = sizeof (EFI_COMMON_SECTION_HEADER);\r
1839 //\r
1840 // 2 bytes for the build number UINT16\r
1841 //\r
1842 Index += 2;\r
1843 //\r
1844 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1845 //\r
1846 Index += (strlen (StringBuffer) * 2) + 2;\r
1847 OutFileBuffer = (UINT8 *) malloc (Index);\r
1848 if (OutFileBuffer == NULL) {\r
1849 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
1850 goto Finish;\r
1851 }\r
1852 VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;\r
1853 VersionSect->CommonHeader.Type = SectType;\r
1854 VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);\r
1855 VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);\r
1856 VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);\r
1857 VersionSect->BuildNumber = (UINT16) VersionNumber;\r
1858 Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);\r
1859 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
1860 break;\r
1861\r
1862 case EFI_SECTION_USER_INTERFACE:\r
1863 Index = sizeof (EFI_COMMON_SECTION_HEADER);\r
1864 //\r
1865 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.\r
1866 //\r
1867 Index += (strlen (StringBuffer) * 2) + 2;\r
1868 OutFileBuffer = (UINT8 *) malloc (Index);\r
1869 if (OutFileBuffer == NULL) {\r
1870 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
1871 goto Finish;\r
1872 }\r
1873 UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;\r
1874 UiSect->CommonHeader.Type = SectType;\r
1875 UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);\r
1876 UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);\r
1877 UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);\r
1878 Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);\r
1879 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);\r
1880 break;\r
1881\r
1882 case EFI_SECTION_ALL:\r
1883 //\r
1884 // read all input file contents into a buffer\r
1885 // first get the size of all file contents\r
1886 //\r
1887 Status = GetSectionContents (\r
1888 InputFileName,\r
1889 InputFileAlign,\r
1890 InputFileNum,\r
1891 OutFileBuffer,\r
1892 &InputLength\r
1893 );\r
1894\r
1895 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1896 OutFileBuffer = (UINT8 *) malloc (InputLength);\r
1897 if (OutFileBuffer == NULL) {\r
1898 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");\r
1899 goto Finish;\r
1900 }\r
1901 //\r
1902 // read all input file contents into a buffer\r
1903 //\r
1904 Status = GetSectionContents (\r
1905 InputFileName,\r
1906 InputFileAlign,\r
1907 InputFileNum,\r
1908 OutFileBuffer,\r
1909 &InputLength\r
1910 );\r
1911 }\r
1912 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);\r
1913 break;\r
1914 default:\r
1915 //\r
1916 // All other section types are caught by default (they're all the same)\r
1917 //\r
1918 Status = GenSectionCommonLeafSection (\r
1919 InputFileName,\r
1920 InputFileNum,\r
1921 SectType,\r
1922 &OutFileBuffer\r
1923 );\r
1924 break;\r
1925 }\r
1926\r
1927 if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {\r
1928 Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);\r
1929 goto Finish;\r
1930 }\r
1931\r
1932 //\r
1933 // Get output file length\r
1934 //\r
1935 if (SectType != EFI_SECTION_ALL) {\r
1936 SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer;\r
1937 InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff;\r
1938 if (InputLength == 0xffffff) {\r
1939 InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;\r
1940 }\r
1941 }\r
1942\r
1943 //\r
1944 // Write the output file\r
1945 //\r
1946 OutFile = fopen (LongFilePath (OutputFileName), "wb");\r
1947 if (OutFile == NULL) {\r
1948 Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);\r
1949 goto Finish;\r
1950 }\r
1951\r
1952 fwrite (OutFileBuffer, InputLength, 1, OutFile);\r
1953\r
1954Finish:\r
1955 if (InputFileName != NULL) {\r
1956 free (InputFileName);\r
1957 }\r
1958\r
1959 if (InputFileAlign != NULL) {\r
1960 free (InputFileAlign);\r
1961 }\r
1962\r
1963 if (OutFileBuffer != NULL) {\r
1964 free (OutFileBuffer);\r
1965 }\r
1966\r
1967 if (OutFile != NULL) {\r
1968 fclose (OutFile);\r
1969 }\r
1970\r
1971 if (DummyFileBuffer != NULL) {\r
1972 free (DummyFileBuffer);\r
1973 }\r
1974\r
1975 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
1976\r
1977 return GetUtilityStatus ();\r
1978}\r