2 Creates output file that is a properly formed section per the PI spec.
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <sys/types.h>
20 #include <Common/UefiBaseTypes.h>
21 #include <Common/PiFirmwareFile.h>
22 #include <Protocol/GuidedSectionExtraction.h>
23 #include <IndustryStandard/PeImage.h>
25 #include "CommonLib.h"
28 #include "EfiUtilityMsgs.h"
31 #include "PeCoffLib.h"
34 // GenSec Tool Information
36 #define UTILITY_NAME "GenSec"
37 #define UTILITY_MAJOR_VERSION 0
38 #define UTILITY_MINOR_VERSION 1
40 STATIC CHAR8
*mSectionTypeName
[] = {
41 NULL
, // 0x00 - reserved
42 "EFI_SECTION_COMPRESSION", // 0x01
43 "EFI_SECTION_GUID_DEFINED", // 0x02
44 NULL
, // 0x03 - reserved
45 NULL
, // 0x04 - reserved
46 NULL
, // 0x05 - reserved
47 NULL
, // 0x06 - reserved
48 NULL
, // 0x07 - reserved
49 NULL
, // 0x08 - reserved
50 NULL
, // 0x09 - reserved
51 NULL
, // 0x0A - reserved
52 NULL
, // 0x0B - reserved
53 NULL
, // 0x0C - reserved
54 NULL
, // 0x0D - reserved
55 NULL
, // 0x0E - reserved
56 NULL
, // 0x0F - reserved
57 "EFI_SECTION_PE32", // 0x10
58 "EFI_SECTION_PIC", // 0x11
59 "EFI_SECTION_TE", // 0x12
60 "EFI_SECTION_DXE_DEPEX", // 0x13
61 "EFI_SECTION_VERSION", // 0x14
62 "EFI_SECTION_USER_INTERFACE", // 0x15
63 "EFI_SECTION_COMPATIBILITY16", // 0x16
64 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17
65 "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18
66 "EFI_SECTION_RAW", // 0x19
68 "EFI_SECTION_PEI_DEPEX", // 0x1B
69 "EFI_SECTION_SMM_DEPEX" // 0x1C
72 STATIC CHAR8
*mCompressionTypeName
[] = { "PI_NONE", "PI_STD" };
74 #define EFI_GUIDED_SECTION_NONE 0x80
75 STATIC CHAR8
*mGUIDedSectionAttribue
[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};
77 STATIC CHAR8
*mAlignName
[] = {
78 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
79 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K",
80 "512K", "1M", "2M", "4M", "8M", "16M"
84 // Crc32 GUID section related definitions.
87 EFI_GUID_DEFINED_SECTION GuidSectionHeader
;
89 } CRC32_SECTION_HEADER
;
92 EFI_GUID_DEFINED_SECTION2 GuidSectionHeader
;
94 } CRC32_SECTION_HEADER2
;
96 STATIC EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
97 STATIC EFI_GUID mEfiCrc32SectionGuid
= EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID
;
108 Print out version information for this utility.
120 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
147 fprintf (stdout
, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME
);
150 // Copyright declaration
152 fprintf (stdout
, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
157 fprintf (stdout
, "Options:\n");
158 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
159 File is the SectionFile to be created.\n");
160 fprintf (stdout
, " -s [SectionType], --sectiontype [SectionType]\n\
161 SectionType defined in PI spec is one type of\n\
162 EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\
163 EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\
164 EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\
165 EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\
166 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\
167 EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\
168 EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\
169 if -s option is not given, \n\
170 EFI_SECTION_ALL is default section type.\n");
171 fprintf (stdout
, " -c [Type], --compress [Type]\n\
172 Compress method type can be PI_NONE or PI_STD.\n\
173 if -c option is not given, PI_STD is default type.\n");
174 fprintf (stdout
, " -g GuidValue, --vendor GuidValue\n\
175 GuidValue is one specific vendor guid value.\n\
176 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
177 fprintf (stdout
, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
178 GuidHeaderLength is the size of header of guided data\n");
179 fprintf (stdout
, " -r GuidAttr, --attributes GuidAttr\n\
180 GuidAttr is guid section attributes, which may be\n\
181 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
182 if -r option is not given, default PROCESSING_REQUIRED\n");
183 fprintf (stdout
, " -n String, --name String\n\
184 String is a NULL terminated string used in Ui section.\n");
185 fprintf (stdout
, " -j Number, --buildnumber Number\n\
186 Number is an integer value between 0 and 65535\n\
187 used in Ver section.\n");
188 fprintf (stdout
, " --sectionalign SectionAlign\n\
189 SectionAlign points to section alignment, which support\n\
190 the alignment scope 0~16M. If SectionAlign is specified\n\
191 as 0, tool get alignment value from SectionFile. It is\n\
192 specified in same order that the section file is input.\n");
193 fprintf (stdout
, " --dummy dummyfile\n\
194 compare dummyfile with input_file to decide whether\n\
195 need to set PROCESSING_REQUIRED attribute.\n");
196 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
197 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
198 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
199 fprintf (stdout
, " --version Show program's version number and exit.\n");
200 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
204 Ascii2UnicodeString (
212 Write ascii string as unicode string format to FILE
216 String - Pointer to string that is written to FILE.
217 UniString - Pointer to unicode string
225 while (*String
!= '\0') {
226 *(UniString
++) = (CHAR16
) *(String
++);
229 // End the UniString with a NULL.
235 GenSectionCommonLeafSection (
236 CHAR8
**InputFileName
,
239 UINT8
**OutFileBuffer
245 Generate a leaf section of type other than EFI_SECTION_VERSION
246 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
247 The function won't validate the input file's contents. For
248 common leaf sections, the input file may be a binary file.
249 The utility will add section header to the file.
253 InputFileName - Name of the input file.
255 InputFileNum - Number of input files. Should be 1 for leaf section.
257 SectionType - A valid section type string
259 OutFileBuffer - Buffer pointer to Output file contents
263 STATUS_ERROR - can't continue
264 STATUS_SUCCESS - successful return
268 UINT32 InputFileLength
;
273 EFI_COMMON_SECTION_HEADER
*CommonSect
;
276 if (InputFileNum
> 1) {
277 Error (NULL
, 0, 2000, "Invalid parameter", "more than one input file specified");
279 } else if (InputFileNum
< 1) {
280 Error (NULL
, 0, 2000, "Invalid parameter", "no input file specified");
284 // Open the input file
286 InFile
= fopen (LongFilePath (InputFileName
[0]), "rb");
287 if (InFile
== NULL
) {
288 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[0]);
292 Status
= STATUS_ERROR
;
295 // Seek to the end of the input file so we can determine its size
297 fseek (InFile
, 0, SEEK_END
);
298 InputFileLength
= ftell (InFile
);
299 fseek (InFile
, 0, SEEK_SET
);
300 DebugMsg (NULL
, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName
[0], (unsigned) InputFileLength
);
301 TotalLength
= sizeof (EFI_COMMON_SECTION_HEADER
) + InputFileLength
;
303 // Size must fit in 3 bytes
305 //if (TotalLength >= MAX_SECTION_SIZE) {
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);
309 HeaderLength
= sizeof (EFI_COMMON_SECTION_HEADER
);
310 if (TotalLength
>= MAX_SECTION_SIZE
) {
311 TotalLength
= sizeof (EFI_COMMON_SECTION_HEADER2
) + InputFileLength
;
312 HeaderLength
= sizeof (EFI_COMMON_SECTION_HEADER2
);
314 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
316 // Fill in the fields in the local section header structure
318 Buffer
= (UINT8
*) malloc ((size_t) TotalLength
);
319 if (Buffer
== NULL
) {
320 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
323 CommonSect
= (EFI_COMMON_SECTION_HEADER
*) Buffer
;
324 CommonSect
->Type
= SectionType
;
325 if (TotalLength
< MAX_SECTION_SIZE
) {
326 CommonSect
->Size
[0] = (UINT8
) (TotalLength
& 0xff);
327 CommonSect
->Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
328 CommonSect
->Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
330 memset(CommonSect
->Size
, 0xff, sizeof(UINT8
) * 3);
331 ((EFI_COMMON_SECTION_HEADER2
*)CommonSect
)->ExtendedSize
= TotalLength
;
335 // read data from the input file.
337 if (InputFileLength
!= 0) {
338 if (fread (Buffer
+ HeaderLength
, (size_t) InputFileLength
, 1, InFile
) != 1) {
339 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[0]);
347 *OutFileBuffer
= Buffer
;
348 Status
= STATUS_SUCCESS
;
359 IN CHAR8
*AlignBuffer
,
360 OUT UINT32
*AlignNumber
366 Converts Align String to align value (1~16M).
370 AlignBuffer - Pointer to Align string.
371 AlignNumber - Pointer to Align value.
375 EFI_SUCCESS Successfully convert align string to align value.
376 EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.
384 if (AlignBuffer
== NULL
) {
385 return EFI_INVALID_PARAMETER
;
387 for (Index
= 0; Index
< sizeof (mAlignName
) / sizeof (CHAR8
*); Index
++) {
388 if (stricmp (AlignBuffer
, mAlignName
[Index
]) == 0) {
389 *AlignNumber
= 1 << Index
;
393 return EFI_INVALID_PARAMETER
;
398 CHAR8
**InputFileName
,
399 UINT32
*InputFileAlign
,
408 Get the contents of all section files specified in InputFileName
413 InputFileName - Name of the input file.
415 InputFileAlign - Alignment required by the input file data.
417 InputFileNum - Number of input files. Should be at least 1.
419 FileBuffer - Output buffer to contain data
421 BufferLength - On input, this is size of the FileBuffer.
422 On output, this is the actual length of the data.
426 EFI_SUCCESS on successful return
427 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
428 EFI_ABORTED if unable to open input file.
429 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
437 EFI_COMMON_SECTION_HEADER
*SectHeader
;
438 EFI_COMMON_SECTION_HEADER2 TempSectHeader
;
439 EFI_TE_IMAGE_HEADER TeHeader
;
441 EFI_GUID_DEFINED_SECTION GuidSectHeader
;
442 EFI_GUID_DEFINED_SECTION2 GuidSectHeader2
;
445 if (InputFileNum
< 1) {
446 Error (NULL
, 0, 2000, "Invalid parameter", "must specify at least one input file");
447 return EFI_INVALID_PARAMETER
;
450 if (BufferLength
== NULL
) {
451 Error (NULL
, 0, 2000, "Invalid parameter", "BufferLength can't be NULL");
452 return EFI_INVALID_PARAMETER
;
459 // Go through our array of file names and copy their contents
460 // to the output buffer.
462 for (Index
= 0; Index
< InputFileNum
; Index
++) {
464 // make sure section ends on a DWORD boundary
466 while ((Size
& 0x03) != 0) {
467 if (FileBuffer
!= NULL
&& Size
< *BufferLength
) {
468 FileBuffer
[Size
] = 0;
474 // Open file and read contents
476 InFile
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
477 if (InFile
== NULL
) {
478 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
482 fseek (InFile
, 0, SEEK_END
);
483 FileSize
= ftell (InFile
);
484 fseek (InFile
, 0, SEEK_SET
);
485 DebugMsg (NULL
, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName
[Index
], (unsigned) FileSize
);
487 // Adjust section buffer when section alignment is required.
489 if (InputFileAlign
!= NULL
) {
491 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
495 // The section might be EFI_COMMON_SECTION_HEADER2
496 // But only Type needs to be checked
498 if (FileSize
>= MAX_SECTION_SIZE
) {
499 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER2
);
501 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER
);
503 fread (&TempSectHeader
, 1, HeaderSize
, InFile
);
504 if (TempSectHeader
.Type
== EFI_SECTION_TE
) {
505 fread (&TeHeader
, 1, sizeof (TeHeader
), InFile
);
506 if (TeHeader
.Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
507 TeOffset
= TeHeader
.StrippedSize
- sizeof (TeHeader
);
509 } else if (TempSectHeader
.Type
== EFI_SECTION_GUID_DEFINED
) {
510 fseek (InFile
, 0, SEEK_SET
);
511 if (FileSize
>= MAX_SECTION_SIZE
) {
512 fread (&GuidSectHeader2
, 1, sizeof (GuidSectHeader2
), InFile
);
513 if ((GuidSectHeader2
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
514 HeaderSize
= GuidSectHeader2
.DataOffset
;
517 fread (&GuidSectHeader
, 1, sizeof (GuidSectHeader
), InFile
);
518 if ((GuidSectHeader
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
519 HeaderSize
= GuidSectHeader
.DataOffset
;
524 fseek (InFile
, 0, SEEK_SET
);
527 // Revert TeOffset to the converse value relative to Alignment
528 // This is to assure the original PeImage Header at Alignment.
531 TeOffset
= InputFileAlign
[Index
] - (TeOffset
% InputFileAlign
[Index
]);
532 TeOffset
= TeOffset
% InputFileAlign
[Index
];
536 // make sure section data meet its alignment requirement by adding one raw pad section.
538 if ((InputFileAlign
[Index
] != 0) && (((Size
+ HeaderSize
+ TeOffset
) % InputFileAlign
[Index
]) != 0)) {
539 Offset
= (Size
+ sizeof (EFI_COMMON_SECTION_HEADER
) + HeaderSize
+ TeOffset
+ InputFileAlign
[Index
] - 1) & ~(InputFileAlign
[Index
] - 1);
540 Offset
= Offset
- Size
- HeaderSize
- TeOffset
;
542 if (FileBuffer
!= NULL
&& ((Size
+ Offset
) < *BufferLength
)) {
544 // The maximal alignment is 64K, the raw section size must be less than 0xffffff
546 memset (FileBuffer
+ Size
, 0, Offset
);
547 SectHeader
= (EFI_COMMON_SECTION_HEADER
*) (FileBuffer
+ Size
);
548 SectHeader
->Type
= EFI_SECTION_RAW
;
549 SectHeader
->Size
[0] = (UINT8
) (Offset
& 0xff);
550 SectHeader
->Size
[1] = (UINT8
) ((Offset
& 0xff00) >> 8);
551 SectHeader
->Size
[2] = (UINT8
) ((Offset
& 0xff0000) >> 16);
553 DebugMsg (NULL
, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset
);
555 Size
= Size
+ Offset
;
560 // Now read the contents of the file into the buffer
561 // Buffer must be enough to contain the file content.
563 if ((FileSize
> 0) && (FileBuffer
!= NULL
) && ((Size
+ FileSize
) <= *BufferLength
)) {
564 if (fread (FileBuffer
+ Size
, (size_t) FileSize
, 1, InFile
) != 1) {
565 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[Index
]);
576 // Set the real required buffer size.
578 if (Size
> *BufferLength
) {
579 *BufferLength
= Size
;
580 return EFI_BUFFER_TOO_SMALL
;
582 *BufferLength
= Size
;
588 GenSectionCompressionSection (
589 CHAR8
**InputFileName
,
590 UINT32
*InputFileAlign
,
592 UINT8 SectCompSubType
,
593 UINT8
**OutFileBuffer
599 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
600 Input file must be already sectioned. The function won't validate
601 the input files' contents. Caller should hand in files already
606 InputFileName - Name of the input file.
608 InputFileAlign - Alignment required by the input file data.
610 InputFileNum - Number of input files. Should be at least 1.
612 SectCompSubType - Specify the compression algorithm requested.
614 OutFileBuffer - Buffer pointer to Output file contents
618 EFI_SUCCESS on successful return
619 EFI_INVALID_PARAMETER if InputFileNum is less than 1
620 EFI_ABORTED if unable to open input file.
621 EFI_OUT_OF_RESOURCES No resource to complete the operation.
626 UINT32 CompressedLength
;
631 EFI_COMPRESSION_SECTION
*CompressionSect
;
632 EFI_COMPRESSION_SECTION2
*CompressionSect2
;
633 COMPRESS_FUNCTION CompressFunction
;
638 CompressedLength
= 0;
641 // read all input file contents into a buffer
642 // first get the size of all file contents
644 Status
= GetSectionContents (
652 if (Status
== EFI_BUFFER_TOO_SMALL
) {
653 FileBuffer
= (UINT8
*) malloc (InputLength
);
654 if (FileBuffer
== NULL
) {
655 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
656 return EFI_OUT_OF_RESOURCES
;
659 // read all input file contents into a buffer
661 Status
= GetSectionContents (
670 if (EFI_ERROR (Status
)) {
671 if (FileBuffer
!= NULL
) {
677 if (FileBuffer
== NULL
) {
678 return EFI_OUT_OF_RESOURCES
;
681 CompressFunction
= NULL
;
684 // Now data is in FileBuffer, compress the data
686 switch (SectCompSubType
) {
687 case EFI_NOT_COMPRESSED
:
688 CompressedLength
= InputLength
;
689 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION
);
690 if (CompressedLength
+ HeaderLength
>= MAX_SECTION_SIZE
) {
691 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION2
);
693 TotalLength
= CompressedLength
+ HeaderLength
;
695 // Copy file buffer to the none compressed data.
697 OutputBuffer
= malloc (TotalLength
);
698 if (OutputBuffer
== NULL
) {
700 return EFI_OUT_OF_RESOURCES
;
702 memcpy (OutputBuffer
+ HeaderLength
, FileBuffer
, CompressedLength
);
704 FileBuffer
= OutputBuffer
;
707 case EFI_STANDARD_COMPRESSION
:
708 CompressFunction
= (COMPRESS_FUNCTION
) EfiCompress
;
712 Error (NULL
, 0, 2000, "Invalid parameter", "unknown compression type");
717 if (CompressFunction
!= NULL
) {
719 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
, &CompressedLength
);
720 if (Status
== EFI_BUFFER_TOO_SMALL
) {
721 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION
);
722 if (CompressedLength
+ HeaderLength
>= MAX_SECTION_SIZE
) {
723 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION2
);
725 TotalLength
= CompressedLength
+ HeaderLength
;
726 OutputBuffer
= malloc (TotalLength
);
729 return EFI_OUT_OF_RESOURCES
;
732 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
+ HeaderLength
, &CompressedLength
);
736 FileBuffer
= OutputBuffer
;
738 if (EFI_ERROR (Status
)) {
739 if (FileBuffer
!= NULL
) {
746 if (FileBuffer
== NULL
) {
747 return EFI_OUT_OF_RESOURCES
;
751 DebugMsg (NULL
, 0, 9, "comprss file size",
752 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength
, (unsigned) CompressedLength
);
754 //if (TotalLength >= MAX_SECTION_SIZE) {
755 // Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);
756 // if (FileBuffer != NULL) {
757 // free (FileBuffer);
759 // if (OutputBuffer != NULL) {
760 // free (OutputBuffer);
762 // return STATUS_ERROR;
764 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
767 // Add the section header for the compressed data
769 if (TotalLength
>= MAX_SECTION_SIZE
) {
770 CompressionSect2
= (EFI_COMPRESSION_SECTION2
*)FileBuffer
;
772 memset(CompressionSect2
->CommonHeader
.Size
, 0xff, sizeof(UINT8
) * 3);
773 CompressionSect2
->CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
774 CompressionSect2
->CommonHeader
.ExtendedSize
= TotalLength
;
775 CompressionSect2
->CompressionType
= SectCompSubType
;
776 CompressionSect2
->UncompressedLength
= InputLength
;
778 CompressionSect
= (EFI_COMPRESSION_SECTION
*) FileBuffer
;
780 CompressionSect
->CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
781 CompressionSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
782 CompressionSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
783 CompressionSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
784 CompressionSect
->CompressionType
= SectCompSubType
;
785 CompressionSect
->UncompressedLength
= InputLength
;
791 *OutFileBuffer
= FileBuffer
;
797 GenSectionGuidDefinedSection (
798 CHAR8
**InputFileName
,
799 UINT32
*InputFileAlign
,
801 EFI_GUID
*VendorGuid
,
802 UINT16 DataAttribute
,
803 UINT32 DataHeaderSize
,
804 UINT8
**OutFileBuffer
810 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
811 Input file must be already sectioned. The function won't validate
812 the input files' contents. Caller should hand in files already
817 InputFileName - Name of the input file.
819 InputFileAlign - Alignment required by the input file data.
821 InputFileNum - Number of input files. Should be at least 1.
823 VendorGuid - Specify vendor guid value.
825 DataAttribute - Specify attribute for the vendor guid data.
827 DataHeaderSize- Guided Data Header Size
829 OutFileBuffer - Buffer pointer to Output file contents
833 EFI_SUCCESS on successful return
834 EFI_INVALID_PARAMETER if InputFileNum is less than 1
835 EFI_ABORTED if unable to open input file.
836 EFI_OUT_OF_RESOURCES No resource to complete the operation.
844 UINT32 Crc32Checksum
;
846 CRC32_SECTION_HEADER
*Crc32GuidSect
;
847 CRC32_SECTION_HEADER2
*Crc32GuidSect2
;
848 EFI_GUID_DEFINED_SECTION
*VendorGuidSect
;
849 EFI_GUID_DEFINED_SECTION2
*VendorGuidSect2
;
857 // read all input file contents into a buffer
858 // first get the size of all file contents
860 Status
= GetSectionContents (
868 if (Status
== EFI_BUFFER_TOO_SMALL
) {
869 if (CompareGuid (VendorGuid
, &mZeroGuid
) == 0) {
870 Offset
= sizeof (CRC32_SECTION_HEADER
);
871 if (InputLength
+ Offset
>= MAX_SECTION_SIZE
) {
872 Offset
= sizeof (CRC32_SECTION_HEADER2
);
875 Offset
= sizeof (EFI_GUID_DEFINED_SECTION
);
876 if (InputLength
+ Offset
>= MAX_SECTION_SIZE
) {
877 Offset
= sizeof (EFI_GUID_DEFINED_SECTION2
);
880 TotalLength
= InputLength
+ Offset
;
882 FileBuffer
= (UINT8
*) malloc (InputLength
+ Offset
);
883 if (FileBuffer
== NULL
) {
884 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
885 return EFI_OUT_OF_RESOURCES
;
888 // read all input file contents into a buffer
890 Status
= GetSectionContents (
899 if (EFI_ERROR (Status
)) {
900 if (FileBuffer
!= NULL
) {
903 Error (NULL
, 0, 0001, "Error opening file for reading", InputFileName
[0]);
907 if (InputLength
== 0) {
908 if (FileBuffer
!= NULL
) {
911 Error (NULL
, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName
);
912 return EFI_NOT_FOUND
;
916 // InputLength != 0, but FileBuffer == NULL means out of resources.
918 if (FileBuffer
== NULL
) {
919 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
920 return EFI_OUT_OF_RESOURCES
;
924 // Now data is in FileBuffer + Offset
926 if (CompareGuid (VendorGuid
, &mZeroGuid
) == 0) {
928 // Default Guid section is CRC32.
931 CalculateCrc32 (FileBuffer
+ Offset
, InputLength
, &Crc32Checksum
);
933 if (TotalLength
>= MAX_SECTION_SIZE
) {
934 Crc32GuidSect2
= (CRC32_SECTION_HEADER2
*) FileBuffer
;
935 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
936 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) 0xff;
937 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) 0xff;
938 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) 0xff;
939 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.ExtendedSize
= TotalLength
;
940 memcpy (&(Crc32GuidSect2
->GuidSectionHeader
.SectionDefinitionGuid
), &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
941 Crc32GuidSect2
->GuidSectionHeader
.Attributes
= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
942 Crc32GuidSect2
->GuidSectionHeader
.DataOffset
= sizeof (CRC32_SECTION_HEADER2
);
943 Crc32GuidSect2
->CRC32Checksum
= Crc32Checksum
;
944 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2
->GuidSectionHeader
.DataOffset
);
946 Crc32GuidSect
= (CRC32_SECTION_HEADER
*) FileBuffer
;
947 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
948 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
949 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
950 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
951 memcpy (&(Crc32GuidSect
->GuidSectionHeader
.SectionDefinitionGuid
), &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
952 Crc32GuidSect
->GuidSectionHeader
.Attributes
= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
953 Crc32GuidSect
->GuidSectionHeader
.DataOffset
= sizeof (CRC32_SECTION_HEADER
);
954 Crc32GuidSect
->CRC32Checksum
= Crc32Checksum
;
955 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect
->GuidSectionHeader
.DataOffset
);
958 if (TotalLength
>= MAX_SECTION_SIZE
) {
959 VendorGuidSect2
= (EFI_GUID_DEFINED_SECTION2
*) FileBuffer
;
960 VendorGuidSect2
->CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
961 VendorGuidSect2
->CommonHeader
.Size
[0] = (UINT8
) 0xff;
962 VendorGuidSect2
->CommonHeader
.Size
[1] = (UINT8
) 0xff;
963 VendorGuidSect2
->CommonHeader
.Size
[2] = (UINT8
) 0xff;
964 VendorGuidSect2
->CommonHeader
.ExtendedSize
= InputLength
+ sizeof (EFI_GUID_DEFINED_SECTION2
);
965 memcpy (&(VendorGuidSect2
->SectionDefinitionGuid
), VendorGuid
, sizeof (EFI_GUID
));
966 VendorGuidSect2
->Attributes
= DataAttribute
;
967 VendorGuidSect2
->DataOffset
= (UINT16
) (sizeof (EFI_GUID_DEFINED_SECTION2
) + DataHeaderSize
);
968 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2
->DataOffset
);
970 VendorGuidSect
= (EFI_GUID_DEFINED_SECTION
*) FileBuffer
;
971 VendorGuidSect
->CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
972 VendorGuidSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
973 VendorGuidSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
974 VendorGuidSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
975 memcpy (&(VendorGuidSect
->SectionDefinitionGuid
), VendorGuid
, sizeof (EFI_GUID
));
976 VendorGuidSect
->Attributes
= DataAttribute
;
977 VendorGuidSect
->DataOffset
= (UINT16
) (sizeof (EFI_GUID_DEFINED_SECTION
) + DataHeaderSize
);
978 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect
->DataOffset
);
981 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
986 *OutFileBuffer
= FileBuffer
;
992 GenSectionSubtypeGuidSection (
993 CHAR8
**InputFileName
,
994 UINT32
*InputFileAlign
,
996 EFI_GUID
*SubTypeGuid
,
997 UINT8
**OutFileBuffer
1001 Routine Description:
1003 Generate a section of type EFI_SECTION_FREEFORM_SUBTYPE_GUID
1004 The function won't validate the input file contents.
1005 The utility will add section header to the file.
1009 InputFileName - Name of the input file.
1011 InputFileAlign - Alignment required by the input file data.
1013 InputFileNum - Number of input files. Should be 1 for this section.
1015 SubTypeGuid - Specify vendor guid value.
1017 OutFileBuffer - Buffer pointer to Output file contents
1021 EFI_SUCCESS on successful return
1022 EFI_INVALID_PARAMETER if InputFileNum is less than 1
1023 EFI_ABORTED if unable to open input file.
1024 EFI_OUT_OF_RESOURCES No resource to complete the operation.
1033 EFI_FREEFORM_SUBTYPE_GUID_SECTION
*SubtypeGuidSect
;
1034 EFI_FREEFORM_SUBTYPE_GUID_SECTION2
*SubtypeGuidSect2
;
1042 if (InputFileNum
> 1) {
1043 Error (NULL
, 0, 2000, "Invalid parameter", "more than one input file specified");
1044 return STATUS_ERROR
;
1045 } else if (InputFileNum
< 1) {
1046 Error (NULL
, 0, 2000, "Invalid parameter", "no input file specified");
1047 return STATUS_ERROR
;
1051 // read all input file contents into a buffer
1052 // first get the size of all file contents
1054 Status
= GetSectionContents (
1062 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1063 Offset
= sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION
);
1064 if (InputLength
+ Offset
>= MAX_SECTION_SIZE
) {
1065 Offset
= sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION2
);
1067 TotalLength
= InputLength
+ Offset
;
1069 FileBuffer
= (UINT8
*) malloc (InputLength
+ Offset
);
1070 if (FileBuffer
== NULL
) {
1071 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1072 return EFI_OUT_OF_RESOURCES
;
1075 // read all input file contents into a buffer
1077 Status
= GetSectionContents (
1081 FileBuffer
+ Offset
,
1086 if (EFI_ERROR (Status
)) {
1087 if (FileBuffer
!= NULL
) {
1090 Error (NULL
, 0, 0001, "Error opening file for reading", InputFileName
[0]);
1094 if (InputLength
== 0) {
1095 if (FileBuffer
!= NULL
) {
1098 Error (NULL
, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName
);
1099 return EFI_NOT_FOUND
;
1103 // InputLength != 0, but FileBuffer == NULL means out of resources.
1105 if (FileBuffer
== NULL
) {
1106 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1107 return EFI_OUT_OF_RESOURCES
;
1111 // Now data is in FileBuffer + Offset
1113 if (TotalLength
>= MAX_SECTION_SIZE
) {
1114 SubtypeGuidSect2
= (EFI_FREEFORM_SUBTYPE_GUID_SECTION2
*) FileBuffer
;
1115 SubtypeGuidSect2
->CommonHeader
.Type
= EFI_SECTION_FREEFORM_SUBTYPE_GUID
;
1116 SubtypeGuidSect2
->CommonHeader
.Size
[0] = (UINT8
) 0xff;
1117 SubtypeGuidSect2
->CommonHeader
.Size
[1] = (UINT8
) 0xff;
1118 SubtypeGuidSect2
->CommonHeader
.Size
[2] = (UINT8
) 0xff;
1119 SubtypeGuidSect2
->CommonHeader
.ExtendedSize
= InputLength
+ sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION2
);
1120 memcpy (&(SubtypeGuidSect2
->SubTypeGuid
), SubTypeGuid
, sizeof (EFI_GUID
));
1122 SubtypeGuidSect
= (EFI_FREEFORM_SUBTYPE_GUID_SECTION
*) FileBuffer
;
1123 SubtypeGuidSect
->CommonHeader
.Type
= EFI_SECTION_FREEFORM_SUBTYPE_GUID
;
1124 SubtypeGuidSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
1125 SubtypeGuidSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
1126 SubtypeGuidSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
1127 memcpy (&(SubtypeGuidSect
->SubTypeGuid
), SubTypeGuid
, sizeof (EFI_GUID
));
1130 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
1133 // Set OutFileBuffer
1135 *OutFileBuffer
= FileBuffer
;
1141 FfsRebaseImageRead (
1142 IN VOID
*FileHandle
,
1143 IN UINTN FileOffset
,
1144 IN OUT UINT32
*ReadSize
,
1149 Routine Description:
1151 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1155 FileHandle - The handle to the PE/COFF file
1157 FileOffset - The offset, in bytes, into the file to read
1159 ReadSize - The number of bytes to read from the file starting at FileOffset
1161 Buffer - A pointer to the buffer to read the data into.
1165 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1169 CHAR8
*Destination8
;
1173 Destination8
= Buffer
;
1174 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1177 *(Destination8
++) = *(Source8
++);
1185 GetAlignmentFromFile(char *InFile
, UINT32
*Alignment
)
1187 InFile is input file for getting alignment
1188 return the alignment
1192 UINT8
*PeFileBuffer
;
1194 UINT32 CurSecHdrSize
;
1195 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1196 EFI_COMMON_SECTION_HEADER
*CommonHeader
;
1199 InFileHandle
= NULL
;
1200 PeFileBuffer
= NULL
;
1203 memset (&ImageContext
, 0, sizeof (ImageContext
));
1205 InFileHandle
= fopen(LongFilePath(InFile
), "rb");
1206 if (InFileHandle
== NULL
){
1207 Error (NULL
, 0, 0001, "Error opening file", InFile
);
1210 PeFileSize
= _filelength (fileno(InFileHandle
));
1211 PeFileBuffer
= (UINT8
*) malloc (PeFileSize
);
1212 if (PeFileBuffer
== NULL
) {
1213 fclose (InFileHandle
);
1214 Error(NULL
, 0, 4001, "Resource", "memory cannot be allocated for %s", InFile
);
1215 return EFI_OUT_OF_RESOURCES
;
1217 fread (PeFileBuffer
, sizeof (UINT8
), PeFileSize
, InFileHandle
);
1218 fclose (InFileHandle
);
1219 CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) PeFileBuffer
;
1220 CurSecHdrSize
= GetSectionHeaderLength(CommonHeader
);
1221 ImageContext
.Handle
= (VOID
*) ((UINTN
)PeFileBuffer
+ CurSecHdrSize
);
1222 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)FfsRebaseImageRead
;
1223 Status
= PeCoffLoaderGetImageInfo(&ImageContext
);
1224 if (EFI_ERROR (Status
)) {
1225 Error (NULL
, 0, 3000, "Invalid PeImage", "The input file is %s and return status is %x", InFile
, (int) Status
);
1228 *Alignment
= ImageContext
.SectionAlignment
;
1229 // Free the allocated memory resource
1230 if (PeFileBuffer
!= NULL
) {
1231 free (PeFileBuffer
);
1232 PeFileBuffer
= NULL
;
1244 Routine Description:
1250 command line parameters
1254 EFI_SUCCESS Section header successfully generated and section concatenated.
1255 EFI_ABORTED Could not generate the section
1256 EFI_OUT_OF_RESOURCES No resource to complete the operation.
1261 UINT32 InputFileNum
;
1263 CHAR8
**InputFileName
;
1264 CHAR8
*OutputFileName
;
1266 CHAR8
*CompressionName
;
1267 CHAR8
*StringBuffer
;
1268 EFI_GUID VendorGuid
= mZeroGuid
;
1271 UINT8 SectCompSubType
;
1272 UINT16 SectGuidAttribute
;
1273 UINT64 SectGuidHeaderLength
;
1274 EFI_VERSION_SECTION
*VersionSect
;
1275 EFI_USER_INTERFACE_SECTION
*UiSect
;
1277 UINT8
*OutFileBuffer
;
1280 UINT32
*InputFileAlign
;
1281 UINT32 InputFileAlignNum
;
1282 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
1283 CHAR8
*DummyFileName
;
1285 UINTN DummyFileSize
;
1286 UINT8
*DummyFileBuffer
;
1288 UINT8
*InFileBuffer
;
1291 InputFileAlign
= NULL
;
1292 InputFileAlignNum
= 0;
1293 InputFileName
= NULL
;
1294 OutputFileName
= NULL
;
1296 CompressionName
= NULL
;
1301 SectType
= EFI_SECTION_ALL
;
1302 SectCompSubType
= 0;
1303 SectGuidAttribute
= EFI_GUIDED_SECTION_NONE
;
1304 OutFileBuffer
= NULL
;
1306 Status
= STATUS_SUCCESS
;
1308 SectGuidHeaderLength
= 0;
1312 DummyFileName
= NULL
;
1314 DummyFileBuffer
= NULL
;
1317 InFileBuffer
= NULL
;
1319 SetUtilityName (UTILITY_NAME
);
1322 Error (NULL
, 0, 1001, "Missing options", "No options input");
1324 return STATUS_ERROR
;
1328 // Parse command line
1333 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1336 return STATUS_SUCCESS
;
1339 if (stricmp (argv
[0], "--version") == 0) {
1341 return STATUS_SUCCESS
;
1345 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--SectionType") == 0)) {
1346 SectionName
= argv
[1];
1347 if (SectionName
== NULL
) {
1348 Error (NULL
, 0, 1003, "Invalid option value", "Section Type can't be NULL");
1356 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1357 OutputFileName
= argv
[1];
1358 if (OutputFileName
== NULL
) {
1359 Error (NULL
, 0, 1003, "Invalid option value", "Output file can't be NULL");
1367 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--compress") == 0)) {
1368 CompressionName
= argv
[1];
1369 if (CompressionName
== NULL
) {
1370 Error (NULL
, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
1378 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--vendor") == 0)) {
1379 Status
= StringToGuid (argv
[1], &VendorGuid
);
1380 if (EFI_ERROR (Status
)) {
1381 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1388 if (stricmp (argv
[0], "--dummy") == 0) {
1389 DummyFileName
= argv
[1];
1390 if (DummyFileName
== NULL
) {
1391 Error (NULL
, 0, 1003, "Invalid option value", "Dummy file can't be NULL");
1399 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--attributes") == 0)) {
1400 if (argv
[1] == NULL
) {
1401 Error (NULL
, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL");
1404 if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]) == 0) {
1405 SectGuidAttribute
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1406 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]) == 0) {
1407 SectGuidAttribute
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
1408 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[0]) == 0) {
1412 SectGuidAttribute
|= EFI_GUIDED_SECTION_NONE
;
1414 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1422 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--HeaderLength") == 0)) {
1423 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &SectGuidHeaderLength
);
1424 if (EFI_ERROR (Status
)) {
1425 Error (NULL
, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv
[0], argv
[1]);
1433 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--name") == 0)) {
1434 StringBuffer
= argv
[1];
1435 if (StringBuffer
== NULL
) {
1436 Error (NULL
, 0, 1003, "Invalid option value", "Name can't be NULL");
1444 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--buildnumber") == 0)) {
1445 if (argv
[1] == NULL
) {
1446 Error (NULL
, 0, 1003, "Invalid option value", "build number can't be NULL");
1450 // Verify string is a integrator number
1452 for (Index
= 0; Index
< strlen (argv
[1]); Index
++) {
1453 if ((argv
[1][Index
] != '-') && (isdigit ((int)argv
[1][Index
]) == 0)) {
1454 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1459 sscanf (argv
[1], "%d", &VersionNumber
);
1465 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1466 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1467 VerboseMsg ("Verbose output Mode Set!");
1473 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1474 SetPrintLevel (KEY_LOG_LEVEL
);
1475 KeyMsg ("Quiet output Mode Set!");
1481 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1482 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1483 if (EFI_ERROR (Status
)) {
1484 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1488 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0~9, current input level is %d", (int) LogLevel
);
1491 SetPrintLevel (LogLevel
);
1492 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1499 // Section File alignment requirement
1501 if (stricmp (argv
[0], "--sectionalign") == 0) {
1502 if (InputFileAlignNum
== 0) {
1503 InputFileAlign
= (UINT32
*) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1504 if (InputFileAlign
== NULL
) {
1505 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1508 memset (InputFileAlign
, 1, MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1509 } else if (InputFileAlignNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1510 InputFileAlign
= (UINT32
*) realloc (
1512 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (UINT32
)
1515 if (InputFileAlign
== NULL
) {
1516 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1519 memset (&(InputFileAlign
[InputFileNum
]), 1, (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
)));
1521 if (stricmp(argv
[1], "0") == 0) {
1522 InputFileAlign
[InputFileAlignNum
] = 0;
1524 Status
= StringtoAlignment (argv
[1], &(InputFileAlign
[InputFileAlignNum
]));
1525 if (EFI_ERROR (Status
)) {
1526 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1532 InputFileAlignNum
++;
1537 // Get Input file name
1539 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1540 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1541 if (InputFileName
== NULL
) {
1542 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1545 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1546 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1548 // InputFileName buffer too small, need to realloc
1550 InputFileName
= (CHAR8
**) realloc (
1552 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1555 if (InputFileName
== NULL
) {
1556 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1559 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1562 InputFileName
[InputFileNum
++] = argv
[0];
1567 if (InputFileAlignNum
> 0 && InputFileAlignNum
!= InputFileNum
) {
1568 Error (NULL
, 0, 1003, "Invalid option", "section alignment must be set for each section");
1571 for (Index
= 0; Index
< InputFileAlignNum
; Index
++)
1573 if (InputFileAlign
[Index
] == 0) {
1574 Status
= GetAlignmentFromFile(InputFileName
[Index
], &(InputFileAlign
[Index
]));
1575 if (EFI_ERROR(Status
)) {
1576 Error (NULL
, 0, 1003, "Fail to get Alignment from %s", InputFileName
[InputFileNum
]);
1582 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1584 if (DummyFileName
!= NULL
) {
1586 // Open file and read contents
1588 DummyFile
= fopen (LongFilePath (DummyFileName
), "rb");
1589 if (DummyFile
== NULL
) {
1590 Error (NULL
, 0, 0001, "Error opening file", DummyFileName
);
1594 fseek (DummyFile
, 0, SEEK_END
);
1595 DummyFileSize
= ftell (DummyFile
);
1596 fseek (DummyFile
, 0, SEEK_SET
);
1597 DummyFileBuffer
= (UINT8
*) malloc (DummyFileSize
);
1598 if (DummyFileBuffer
== NULL
) {
1600 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1604 fread(DummyFileBuffer
, 1, DummyFileSize
, DummyFile
);
1606 DebugMsg (NULL
, 0, 9, "Dummy files", "the dummy file name is %s and the size is %u bytes", DummyFileName
, (unsigned) DummyFileSize
);
1608 if (InputFileName
== NULL
) {
1609 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1612 InFile
= fopen(LongFilePath(InputFileName
[0]), "rb");
1613 if (InFile
== NULL
) {
1614 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[0]);
1618 fseek (InFile
, 0, SEEK_END
);
1619 InFileSize
= ftell (InFile
);
1620 fseek (InFile
, 0, SEEK_SET
);
1621 InFileBuffer
= (UINT8
*) malloc (InFileSize
);
1622 if (InFileBuffer
== NULL
) {
1624 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1628 fread(InFileBuffer
, 1, InFileSize
, InFile
);
1630 DebugMsg (NULL
, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName
[0], (unsigned) InFileSize
);
1631 if (InFileSize
> DummyFileSize
){
1632 if (stricmp((CHAR8
*)DummyFileBuffer
, (CHAR8
*)(InFileBuffer
+ (InFileSize
- DummyFileSize
))) == 0){
1633 SectGuidHeaderLength
= InFileSize
- DummyFileSize
;
1636 if (SectGuidHeaderLength
== 0) {
1637 SectGuidAttribute
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1639 if (DummyFileBuffer
!= NULL
) {
1640 free (DummyFileBuffer
);
1641 DummyFileBuffer
= NULL
;
1643 if (InFileBuffer
!= NULL
) {
1644 free (InFileBuffer
);
1649 // Parse all command line parameters to get the corresponding section type.
1651 VerboseMsg ("Section type is %s", SectionName
);
1652 if (SectionName
== NULL
) {
1654 // No specified Section type, default is SECTION_ALL.
1656 SectType
= EFI_SECTION_ALL
;
1657 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPRESSION
]) == 0) {
1658 SectType
= EFI_SECTION_COMPRESSION
;
1659 if (CompressionName
== NULL
) {
1661 // Default is PI_STD compression algorithm.
1663 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1664 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_NOT_COMPRESSED
]) == 0) {
1665 SectCompSubType
= EFI_NOT_COMPRESSED
;
1666 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_STANDARD_COMPRESSION
]) == 0) {
1667 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1669 Error (NULL
, 0, 1003, "Invalid option value", "--compress = %s", CompressionName
);
1672 VerboseMsg ("Compress method is %s", mCompressionTypeName
[SectCompSubType
]);
1673 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_GUID_DEFINED
]) == 0) {
1674 SectType
= EFI_SECTION_GUID_DEFINED
;
1676 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_NONE
) != 0) {
1678 // NONE attribute, clear attribute value.
1680 SectGuidAttribute
= SectGuidAttribute
& ~EFI_GUIDED_SECTION_NONE
;
1682 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1683 (unsigned) VendorGuid
.Data1
,
1686 VendorGuid
.Data4
[0],
1687 VendorGuid
.Data4
[1],
1688 VendorGuid
.Data4
[2],
1689 VendorGuid
.Data4
[3],
1690 VendorGuid
.Data4
[4],
1691 VendorGuid
.Data4
[5],
1692 VendorGuid
.Data4
[6],
1693 VendorGuid
.Data4
[7]);
1694 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
1695 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]);
1697 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
1698 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]);
1700 if (SectGuidHeaderLength
!= 0) {
1701 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength
);
1703 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PE32
]) == 0) {
1704 SectType
= EFI_SECTION_PE32
;
1705 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PIC
]) == 0) {
1706 SectType
= EFI_SECTION_PIC
;
1707 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_TE
]) == 0) {
1708 SectType
= EFI_SECTION_TE
;
1709 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_DXE_DEPEX
]) == 0) {
1710 SectType
= EFI_SECTION_DXE_DEPEX
;
1711 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_SMM_DEPEX
]) == 0) {
1712 SectType
= EFI_SECTION_SMM_DEPEX
;
1713 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_VERSION
]) == 0) {
1714 SectType
= EFI_SECTION_VERSION
;
1715 if (VersionNumber
< 0 || VersionNumber
> 65535) {
1716 Error (NULL
, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber
);
1719 VerboseMsg ("Version section number is %d", VersionNumber
);
1720 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_USER_INTERFACE
]) == 0) {
1721 SectType
= EFI_SECTION_USER_INTERFACE
;
1722 if (StringBuffer
[0] == '\0') {
1723 Error (NULL
, 0, 1001, "Missing option", "user interface string");
1726 VerboseMsg ("UI section string name is %s", StringBuffer
);
1727 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPATIBILITY16
]) == 0) {
1728 SectType
= EFI_SECTION_COMPATIBILITY16
;
1729 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FIRMWARE_VOLUME_IMAGE
]) == 0) {
1730 SectType
= EFI_SECTION_FIRMWARE_VOLUME_IMAGE
;
1731 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FREEFORM_SUBTYPE_GUID
]) == 0) {
1732 SectType
= EFI_SECTION_FREEFORM_SUBTYPE_GUID
;
1733 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_RAW
]) == 0) {
1734 SectType
= EFI_SECTION_RAW
;
1735 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PEI_DEPEX
]) == 0) {
1736 SectType
= EFI_SECTION_PEI_DEPEX
;
1738 Error (NULL
, 0, 1003, "Invalid option value", "SectionType = %s", SectionName
);
1743 // GuidValue is only required by Guided section and SubtypeGuid section.
1745 if ((SectType
!= EFI_SECTION_GUID_DEFINED
) && (SectType
!= EFI_SECTION_FREEFORM_SUBTYPE_GUID
) &&
1746 (SectionName
!= NULL
) &&
1747 (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1748 fprintf (stdout
, "Warning: the input guid value is not required for this section type %s\n", SectionName
);
1752 // Check whether there is GUID for the SubtypeGuid section
1754 if ((SectType
== EFI_SECTION_FREEFORM_SUBTYPE_GUID
) && (CompareGuid (&VendorGuid
, &mZeroGuid
) == 0)) {
1755 Error (NULL
, 0, 1001, "Missing options", "GUID");
1760 // Check whether there is input file
1762 if ((SectType
!= EFI_SECTION_VERSION
) && (SectType
!= EFI_SECTION_USER_INTERFACE
)) {
1764 // The input file are required for other section type.
1766 if (InputFileNum
== 0) {
1767 Error (NULL
, 0, 1001, "Missing options", "Input files");
1772 // Check whether there is output file
1774 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1775 VerboseMsg ("the %uth input file name is %s", (unsigned) Index
, InputFileName
[Index
]);
1777 if (OutputFileName
== NULL
) {
1778 Error (NULL
, 0, 1001, "Missing options", "Output file");
1780 // OutFile = stdout;
1782 VerboseMsg ("Output file name is %s", OutputFileName
);
1785 // At this point, we've fully validated the command line, and opened appropriate
1786 // files, so let's go and do what we've been asked to do...
1789 // Within this switch, build and write out the section header including any
1790 // section type specific pieces. If there's an input file, it's tacked on later
1793 case EFI_SECTION_COMPRESSION
:
1794 if (InputFileAlign
!= NULL
) {
1795 free (InputFileAlign
);
1796 InputFileAlign
= NULL
;
1798 Status
= GenSectionCompressionSection (
1807 case EFI_SECTION_GUID_DEFINED
:
1808 if (InputFileAlign
!= NULL
&& (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1810 // Only process alignment for the default known CRC32 guided section.
1811 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
1813 free (InputFileAlign
);
1814 InputFileAlign
= NULL
;
1816 Status
= GenSectionGuidDefinedSection (
1822 (UINT32
) SectGuidHeaderLength
,
1827 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
1828 Status
= GenSectionSubtypeGuidSection (
1837 case EFI_SECTION_VERSION
:
1838 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1840 // 2 bytes for the build number UINT16
1844 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1846 Index
+= (strlen (StringBuffer
) * 2) + 2;
1847 OutFileBuffer
= (UINT8
*) malloc (Index
);
1848 if (OutFileBuffer
== NULL
) {
1849 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1852 VersionSect
= (EFI_VERSION_SECTION
*) OutFileBuffer
;
1853 VersionSect
->CommonHeader
.Type
= SectType
;
1854 VersionSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1855 VersionSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1856 VersionSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1857 VersionSect
->BuildNumber
= (UINT16
) VersionNumber
;
1858 Ascii2UnicodeString (StringBuffer
, VersionSect
->VersionString
);
1859 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1862 case EFI_SECTION_USER_INTERFACE
:
1863 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1865 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1867 Index
+= (strlen (StringBuffer
) * 2) + 2;
1868 OutFileBuffer
= (UINT8
*) malloc (Index
);
1869 if (OutFileBuffer
== NULL
) {
1870 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1873 UiSect
= (EFI_USER_INTERFACE_SECTION
*) OutFileBuffer
;
1874 UiSect
->CommonHeader
.Type
= SectType
;
1875 UiSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1876 UiSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1877 UiSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1878 Ascii2UnicodeString (StringBuffer
, UiSect
->FileNameString
);
1879 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1882 case EFI_SECTION_ALL
:
1884 // read all input file contents into a buffer
1885 // first get the size of all file contents
1887 Status
= GetSectionContents (
1895 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1896 OutFileBuffer
= (UINT8
*) malloc (InputLength
);
1897 if (OutFileBuffer
== NULL
) {
1898 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1902 // read all input file contents into a buffer
1904 Status
= GetSectionContents (
1912 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength
);
1916 // All other section types are caught by default (they're all the same)
1918 Status
= GenSectionCommonLeafSection (
1927 if (Status
!= EFI_SUCCESS
|| OutFileBuffer
== NULL
) {
1928 Error (NULL
, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status
);
1933 // Get output file length
1935 if (SectType
!= EFI_SECTION_ALL
) {
1936 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*)OutFileBuffer
;
1937 InputLength
= *(UINT32
*)SectionHeader
->Size
& 0x00ffffff;
1938 if (InputLength
== 0xffffff) {
1939 InputLength
= ((EFI_COMMON_SECTION_HEADER2
*)SectionHeader
)->ExtendedSize
;
1944 // Write the output file
1946 OutFile
= fopen (LongFilePath (OutputFileName
), "wb");
1947 if (OutFile
== NULL
) {
1948 Error (NULL
, 0, 0001, "Error opening file for writing", OutputFileName
);
1952 fwrite (OutFileBuffer
, InputLength
, 1, OutFile
);
1955 if (InputFileName
!= NULL
) {
1956 free (InputFileName
);
1959 if (InputFileAlign
!= NULL
) {
1960 free (InputFileAlign
);
1963 if (OutFileBuffer
!= NULL
) {
1964 free (OutFileBuffer
);
1967 if (OutFile
!= NULL
) {
1971 if (DummyFileBuffer
!= NULL
) {
1972 free (DummyFileBuffer
);
1975 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
1977 return GetUtilityStatus ();