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 atttributes, 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 dummpyfile 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
;
995 IN OUT UINT32
*ReadSize
,
1000 Routine Description:
1002 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1006 FileHandle - The handle to the PE/COFF file
1008 FileOffset - The offset, in bytes, into the file to read
1010 ReadSize - The number of bytes to read from the file starting at FileOffset
1012 Buffer - A pointer to the buffer to read the data into.
1016 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1020 CHAR8
*Destination8
;
1024 Destination8
= Buffer
;
1025 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1028 *(Destination8
++) = *(Source8
++);
1036 GetAlignmentFromFile(char *InFile
, UINT32
*Alignment
)
1038 InFile is input file for getting alignment
1039 return the alignment
1043 UINT8
*PeFileBuffer
;
1045 UINT32 CurSecHdrSize
;
1046 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1047 EFI_COMMON_SECTION_HEADER
*CommonHeader
;
1050 InFileHandle
= NULL
;
1051 PeFileBuffer
= NULL
;
1054 memset (&ImageContext
, 0, sizeof (ImageContext
));
1056 InFileHandle
= fopen(LongFilePath(InFile
), "rb");
1057 if (InFileHandle
== NULL
){
1058 Error (NULL
, 0, 0001, "Error opening file", InFile
);
1061 PeFileSize
= _filelength (fileno(InFileHandle
));
1062 PeFileBuffer
= (UINT8
*) malloc (PeFileSize
);
1063 if (PeFileBuffer
== NULL
) {
1064 fclose (InFileHandle
);
1065 Error(NULL
, 0, 4001, "Resource", "memory cannot be allocated of %s", InFileHandle
);
1066 return EFI_OUT_OF_RESOURCES
;
1068 fread (PeFileBuffer
, sizeof (UINT8
), PeFileSize
, InFileHandle
);
1069 fclose (InFileHandle
);
1070 CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) PeFileBuffer
;
1071 CurSecHdrSize
= GetSectionHeaderLength(CommonHeader
);
1072 ImageContext
.Handle
= (VOID
*) ((UINTN
)PeFileBuffer
+ CurSecHdrSize
);
1073 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)FfsRebaseImageRead
;
1074 Status
= PeCoffLoaderGetImageInfo(&ImageContext
);
1075 if (EFI_ERROR (Status
)) {
1076 Error (NULL
, 0, 3000, "Invalid PeImage", "The input file is %s and return status is %x", InFile
, (int) Status
);
1079 *Alignment
= ImageContext
.SectionAlignment
;
1080 // Free the allocated memory resource
1081 if (PeFileBuffer
!= NULL
) {
1082 free (PeFileBuffer
);
1083 PeFileBuffer
= NULL
;
1095 Routine Description:
1101 command line parameters
1105 EFI_SUCCESS Section header successfully generated and section concatenated.
1106 EFI_ABORTED Could not generate the section
1107 EFI_OUT_OF_RESOURCES No resource to complete the operation.
1112 UINT32 InputFileNum
;
1114 CHAR8
**InputFileName
;
1115 CHAR8
*OutputFileName
;
1117 CHAR8
*CompressionName
;
1118 CHAR8
*StringBuffer
;
1119 EFI_GUID VendorGuid
= mZeroGuid
;
1122 UINT8 SectCompSubType
;
1123 UINT16 SectGuidAttribute
;
1124 UINT64 SectGuidHeaderLength
;
1125 EFI_VERSION_SECTION
*VersionSect
;
1126 EFI_USER_INTERFACE_SECTION
*UiSect
;
1128 UINT8
*OutFileBuffer
;
1131 UINT32
*InputFileAlign
;
1132 UINT32 InputFileAlignNum
;
1133 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
1134 CHAR8
*DummyFileName
;
1136 UINTN DummyFileSize
;
1137 UINT8
*DummyFileBuffer
;
1139 UINT8
*InFileBuffer
;
1142 InputFileAlign
= NULL
;
1143 InputFileAlignNum
= 0;
1144 InputFileName
= NULL
;
1145 OutputFileName
= NULL
;
1147 CompressionName
= NULL
;
1152 SectType
= EFI_SECTION_ALL
;
1153 SectCompSubType
= 0;
1154 SectGuidAttribute
= EFI_GUIDED_SECTION_NONE
;
1155 OutFileBuffer
= NULL
;
1157 Status
= STATUS_SUCCESS
;
1159 SectGuidHeaderLength
= 0;
1163 DummyFileName
= NULL
;
1165 DummyFileBuffer
= NULL
;
1168 InFileBuffer
= NULL
;
1170 SetUtilityName (UTILITY_NAME
);
1173 Error (NULL
, 0, 1001, "Missing options", "No options input");
1175 return STATUS_ERROR
;
1179 // Parse command line
1184 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1187 return STATUS_SUCCESS
;
1190 if (stricmp (argv
[0], "--version") == 0) {
1192 return STATUS_SUCCESS
;
1196 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--SectionType") == 0)) {
1197 SectionName
= argv
[1];
1198 if (SectionName
== NULL
) {
1199 Error (NULL
, 0, 1003, "Invalid option value", "Section Type can't be NULL");
1207 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1208 OutputFileName
= argv
[1];
1209 if (OutputFileName
== NULL
) {
1210 Error (NULL
, 0, 1003, "Invalid option value", "Output file can't be NULL");
1218 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--compress") == 0)) {
1219 CompressionName
= argv
[1];
1220 if (CompressionName
== NULL
) {
1221 Error (NULL
, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
1229 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--vendor") == 0)) {
1230 Status
= StringToGuid (argv
[1], &VendorGuid
);
1231 if (EFI_ERROR (Status
)) {
1232 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1239 if (stricmp (argv
[0], "--dummy") == 0) {
1240 DummyFileName
= argv
[1];
1241 if (DummyFileName
== NULL
) {
1242 Error (NULL
, 0, 1003, "Invalid option value", "Dummy file can't be NULL");
1250 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--attributes") == 0)) {
1251 if (argv
[1] == NULL
) {
1252 Error (NULL
, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL");
1255 if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]) == 0) {
1256 SectGuidAttribute
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1257 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]) == 0) {
1258 SectGuidAttribute
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
1259 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[0]) == 0) {
1263 SectGuidAttribute
|= EFI_GUIDED_SECTION_NONE
;
1265 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1273 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--HeaderLength") == 0)) {
1274 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &SectGuidHeaderLength
);
1275 if (EFI_ERROR (Status
)) {
1276 Error (NULL
, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv
[0], argv
[1]);
1284 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--name") == 0)) {
1285 StringBuffer
= argv
[1];
1286 if (StringBuffer
== NULL
) {
1287 Error (NULL
, 0, 1003, "Invalid option value", "Name can't be NULL");
1295 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--buildnumber") == 0)) {
1296 if (argv
[1] == NULL
) {
1297 Error (NULL
, 0, 1003, "Invalid option value", "build number can't be NULL");
1301 // Verify string is a integrator number
1303 for (Index
= 0; Index
< strlen (argv
[1]); Index
++) {
1304 if ((argv
[1][Index
] != '-') && (isdigit ((int)argv
[1][Index
]) == 0)) {
1305 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1310 sscanf (argv
[1], "%d", &VersionNumber
);
1316 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1317 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1318 VerboseMsg ("Verbose output Mode Set!");
1324 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1325 SetPrintLevel (KEY_LOG_LEVEL
);
1326 KeyMsg ("Quiet output Mode Set!");
1332 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1333 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1334 if (EFI_ERROR (Status
)) {
1335 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1339 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0~9, current input level is %d", (int) LogLevel
);
1342 SetPrintLevel (LogLevel
);
1343 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1350 // Section File alignment requirement
1352 if (stricmp (argv
[0], "--sectionalign") == 0) {
1353 if (InputFileAlignNum
== 0) {
1354 InputFileAlign
= (UINT32
*) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1355 if (InputFileAlign
== NULL
) {
1356 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1359 memset (InputFileAlign
, 1, MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1360 } else if (InputFileAlignNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1361 InputFileAlign
= (UINT32
*) realloc (
1363 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (UINT32
)
1366 if (InputFileAlign
== NULL
) {
1367 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1370 memset (&(InputFileAlign
[InputFileNum
]), 1, (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
)));
1372 if (stricmp(argv
[1], "0") == 0) {
1373 InputFileAlign
[InputFileAlignNum
] = 0;
1375 Status
= StringtoAlignment (argv
[1], &(InputFileAlign
[InputFileAlignNum
]));
1376 if (EFI_ERROR (Status
)) {
1377 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1383 InputFileAlignNum
++;
1388 // Get Input file name
1390 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1391 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1392 if (InputFileName
== NULL
) {
1393 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1396 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1397 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1399 // InputFileName buffer too small, need to realloc
1401 InputFileName
= (CHAR8
**) realloc (
1403 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1406 if (InputFileName
== NULL
) {
1407 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1410 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1413 InputFileName
[InputFileNum
++] = argv
[0];
1418 if (InputFileAlignNum
> 0 && InputFileAlignNum
!= InputFileNum
) {
1419 Error (NULL
, 0, 1003, "Invalid option", "section alignment must be set for each section");
1422 for (Index
= 0; Index
< InputFileAlignNum
; Index
++)
1424 if (InputFileAlign
[Index
] == 0) {
1425 Status
= GetAlignmentFromFile(InputFileName
[Index
], &(InputFileAlign
[Index
]));
1426 if (EFI_ERROR(Status
)) {
1427 Error (NULL
, 0, 1003, "Fail to get Alignment from %s", InputFileName
[InputFileNum
]);
1433 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1435 if (DummyFileName
!= NULL
) {
1437 // Open file and read contents
1439 DummyFile
= fopen (LongFilePath (DummyFileName
), "rb");
1440 if (DummyFile
== NULL
) {
1441 Error (NULL
, 0, 0001, "Error opening file", DummyFileName
);
1445 fseek (DummyFile
, 0, SEEK_END
);
1446 DummyFileSize
= ftell (DummyFile
);
1447 fseek (DummyFile
, 0, SEEK_SET
);
1448 DummyFileBuffer
= (UINT8
*) malloc (DummyFileSize
);
1449 if (DummyFileBuffer
== NULL
) {
1451 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1455 fread(DummyFileBuffer
, 1, DummyFileSize
, DummyFile
);
1457 DebugMsg (NULL
, 0, 9, "Dummy files", "the dummy file name is %s and the size is %u bytes", DummyFileName
, (unsigned) DummyFileSize
);
1459 if (InputFileName
== NULL
) {
1460 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1463 InFile
= fopen(LongFilePath(InputFileName
[0]), "rb");
1464 if (InFile
== NULL
) {
1465 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[0]);
1469 fseek (InFile
, 0, SEEK_END
);
1470 InFileSize
= ftell (InFile
);
1471 fseek (InFile
, 0, SEEK_SET
);
1472 InFileBuffer
= (UINT8
*) malloc (InFileSize
);
1473 if (InFileBuffer
== NULL
) {
1475 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1479 fread(InFileBuffer
, 1, InFileSize
, InFile
);
1481 DebugMsg (NULL
, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName
[0], (unsigned) InFileSize
);
1482 if (InFileSize
> DummyFileSize
){
1483 if (stricmp((CHAR8
*)DummyFileBuffer
, (CHAR8
*)(InFileBuffer
+ (InFileSize
- DummyFileSize
))) == 0){
1484 SectGuidHeaderLength
= InFileSize
- DummyFileSize
;
1487 if (SectGuidHeaderLength
== 0) {
1488 SectGuidAttribute
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1490 if (DummyFileBuffer
!= NULL
) {
1491 free (DummyFileBuffer
);
1492 DummyFileBuffer
= NULL
;
1494 if (InFileBuffer
!= NULL
) {
1495 free (InFileBuffer
);
1500 // Parse all command line parameters to get the corresponding section type.
1502 VerboseMsg ("Section type is %s", SectionName
);
1503 if (SectionName
== NULL
) {
1505 // No specified Section type, default is SECTION_ALL.
1507 SectType
= EFI_SECTION_ALL
;
1508 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPRESSION
]) == 0) {
1509 SectType
= EFI_SECTION_COMPRESSION
;
1510 if (CompressionName
== NULL
) {
1512 // Default is PI_STD compression algorithm.
1514 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1515 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_NOT_COMPRESSED
]) == 0) {
1516 SectCompSubType
= EFI_NOT_COMPRESSED
;
1517 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_STANDARD_COMPRESSION
]) == 0) {
1518 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1520 Error (NULL
, 0, 1003, "Invalid option value", "--compress = %s", CompressionName
);
1523 VerboseMsg ("Compress method is %s", mCompressionTypeName
[SectCompSubType
]);
1524 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_GUID_DEFINED
]) == 0) {
1525 SectType
= EFI_SECTION_GUID_DEFINED
;
1527 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_NONE
) != 0) {
1529 // NONE attribute, clear attribute value.
1531 SectGuidAttribute
= SectGuidAttribute
& ~EFI_GUIDED_SECTION_NONE
;
1533 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1534 (unsigned) VendorGuid
.Data1
,
1537 VendorGuid
.Data4
[0],
1538 VendorGuid
.Data4
[1],
1539 VendorGuid
.Data4
[2],
1540 VendorGuid
.Data4
[3],
1541 VendorGuid
.Data4
[4],
1542 VendorGuid
.Data4
[5],
1543 VendorGuid
.Data4
[6],
1544 VendorGuid
.Data4
[7]);
1545 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
1546 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]);
1548 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
1549 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]);
1551 if (SectGuidHeaderLength
!= 0) {
1552 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength
);
1554 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PE32
]) == 0) {
1555 SectType
= EFI_SECTION_PE32
;
1556 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PIC
]) == 0) {
1557 SectType
= EFI_SECTION_PIC
;
1558 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_TE
]) == 0) {
1559 SectType
= EFI_SECTION_TE
;
1560 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_DXE_DEPEX
]) == 0) {
1561 SectType
= EFI_SECTION_DXE_DEPEX
;
1562 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_SMM_DEPEX
]) == 0) {
1563 SectType
= EFI_SECTION_SMM_DEPEX
;
1564 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_VERSION
]) == 0) {
1565 SectType
= EFI_SECTION_VERSION
;
1566 if (VersionNumber
< 0 || VersionNumber
> 65535) {
1567 Error (NULL
, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber
);
1570 VerboseMsg ("Version section number is %d", VersionNumber
);
1571 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_USER_INTERFACE
]) == 0) {
1572 SectType
= EFI_SECTION_USER_INTERFACE
;
1573 if (StringBuffer
[0] == '\0') {
1574 Error (NULL
, 0, 1001, "Missing option", "user interface string");
1577 VerboseMsg ("UI section string name is %s", StringBuffer
);
1578 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPATIBILITY16
]) == 0) {
1579 SectType
= EFI_SECTION_COMPATIBILITY16
;
1580 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FIRMWARE_VOLUME_IMAGE
]) == 0) {
1581 SectType
= EFI_SECTION_FIRMWARE_VOLUME_IMAGE
;
1582 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FREEFORM_SUBTYPE_GUID
]) == 0) {
1583 SectType
= EFI_SECTION_FREEFORM_SUBTYPE_GUID
;
1584 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_RAW
]) == 0) {
1585 SectType
= EFI_SECTION_RAW
;
1586 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PEI_DEPEX
]) == 0) {
1587 SectType
= EFI_SECTION_PEI_DEPEX
;
1589 Error (NULL
, 0, 1003, "Invalid option value", "SectionType = %s", SectionName
);
1594 // GuidValue is only required by Guided section.
1596 if ((SectType
!= EFI_SECTION_GUID_DEFINED
) &&
1597 (SectionName
!= NULL
) &&
1598 (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1599 fprintf (stdout
, "Warning: the input guid value is not required for this section type %s\n", SectionName
);
1603 // Check whether there is input file
1605 if ((SectType
!= EFI_SECTION_VERSION
) && (SectType
!= EFI_SECTION_USER_INTERFACE
)) {
1607 // The input file are required for other section type.
1609 if (InputFileNum
== 0) {
1610 Error (NULL
, 0, 1001, "Missing options", "Input files");
1615 // Check whether there is output file
1617 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1618 VerboseMsg ("the %uth input file name is %s", (unsigned) Index
, InputFileName
[Index
]);
1620 if (OutputFileName
== NULL
) {
1621 Error (NULL
, 0, 1001, "Missing options", "Output file");
1623 // OutFile = stdout;
1625 VerboseMsg ("Output file name is %s", OutputFileName
);
1628 // At this point, we've fully validated the command line, and opened appropriate
1629 // files, so let's go and do what we've been asked to do...
1632 // Within this switch, build and write out the section header including any
1633 // section type specific pieces. If there's an input file, it's tacked on later
1636 case EFI_SECTION_COMPRESSION
:
1637 if (InputFileAlign
!= NULL
) {
1638 free (InputFileAlign
);
1639 InputFileAlign
= NULL
;
1641 Status
= GenSectionCompressionSection (
1650 case EFI_SECTION_GUID_DEFINED
:
1651 if (InputFileAlign
!= NULL
&& (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1653 // Only process alignment for the default known CRC32 guided section.
1654 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
1656 free (InputFileAlign
);
1657 InputFileAlign
= NULL
;
1659 Status
= GenSectionGuidDefinedSection (
1665 (UINT32
) SectGuidHeaderLength
,
1670 case EFI_SECTION_VERSION
:
1671 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1673 // 2 bytes for the build number UINT16
1677 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1679 Index
+= (strlen (StringBuffer
) * 2) + 2;
1680 OutFileBuffer
= (UINT8
*) malloc (Index
);
1681 if (OutFileBuffer
== NULL
) {
1682 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1685 VersionSect
= (EFI_VERSION_SECTION
*) OutFileBuffer
;
1686 VersionSect
->CommonHeader
.Type
= SectType
;
1687 VersionSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1688 VersionSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1689 VersionSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1690 VersionSect
->BuildNumber
= (UINT16
) VersionNumber
;
1691 Ascii2UnicodeString (StringBuffer
, VersionSect
->VersionString
);
1692 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1695 case EFI_SECTION_USER_INTERFACE
:
1696 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1698 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1700 Index
+= (strlen (StringBuffer
) * 2) + 2;
1701 OutFileBuffer
= (UINT8
*) malloc (Index
);
1702 if (OutFileBuffer
== NULL
) {
1703 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1706 UiSect
= (EFI_USER_INTERFACE_SECTION
*) OutFileBuffer
;
1707 UiSect
->CommonHeader
.Type
= SectType
;
1708 UiSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1709 UiSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1710 UiSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1711 Ascii2UnicodeString (StringBuffer
, UiSect
->FileNameString
);
1712 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1715 case EFI_SECTION_ALL
:
1717 // read all input file contents into a buffer
1718 // first get the size of all file contents
1720 Status
= GetSectionContents (
1728 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1729 OutFileBuffer
= (UINT8
*) malloc (InputLength
);
1730 if (OutFileBuffer
== NULL
) {
1731 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated");
1735 // read all input file contents into a buffer
1737 Status
= GetSectionContents (
1745 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength
);
1749 // All other section types are caught by default (they're all the same)
1751 Status
= GenSectionCommonLeafSection (
1760 if (Status
!= EFI_SUCCESS
|| OutFileBuffer
== NULL
) {
1761 Error (NULL
, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status
);
1766 // Get output file length
1768 if (SectType
!= EFI_SECTION_ALL
) {
1769 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*)OutFileBuffer
;
1770 InputLength
= *(UINT32
*)SectionHeader
->Size
& 0x00ffffff;
1771 if (InputLength
== 0xffffff) {
1772 InputLength
= ((EFI_COMMON_SECTION_HEADER2
*)SectionHeader
)->ExtendedSize
;
1777 // Write the output file
1779 OutFile
= fopen (LongFilePath (OutputFileName
), "wb");
1780 if (OutFile
== NULL
) {
1781 Error (NULL
, 0, 0001, "Error opening file for writing", OutputFileName
);
1785 fwrite (OutFileBuffer
, InputLength
, 1, OutFile
);
1788 if (InputFileName
!= NULL
) {
1789 free (InputFileName
);
1792 if (InputFileAlign
!= NULL
) {
1793 free (InputFileAlign
);
1796 if (OutFileBuffer
!= NULL
) {
1797 free (OutFileBuffer
);
1800 if (OutFile
!= NULL
) {
1804 if (DummyFileBuffer
!= NULL
) {
1805 free (DummyFileBuffer
);
1808 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
1810 return GetUtilityStatus ();