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 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <sys/types.h>
26 #include <Common/UefiBaseTypes.h>
27 #include <Common/PiFirmwareFile.h>
28 #include <Protocol/GuidedSectionExtraction.h>
29 #include <IndustryStandard/PeImage.h>
31 #include "CommonLib.h"
34 #include "EfiUtilityMsgs.h"
37 #include "PeCoffLib.h"
40 // GenSec Tool Information
42 #define UTILITY_NAME "GenSec"
43 #define UTILITY_MAJOR_VERSION 0
44 #define UTILITY_MINOR_VERSION 1
46 STATIC CHAR8
*mSectionTypeName
[] = {
47 NULL
, // 0x00 - reserved
48 "EFI_SECTION_COMPRESSION", // 0x01
49 "EFI_SECTION_GUID_DEFINED", // 0x02
50 NULL
, // 0x03 - reserved
51 NULL
, // 0x04 - reserved
52 NULL
, // 0x05 - reserved
53 NULL
, // 0x06 - reserved
54 NULL
, // 0x07 - reserved
55 NULL
, // 0x08 - reserved
56 NULL
, // 0x09 - reserved
57 NULL
, // 0x0A - reserved
58 NULL
, // 0x0B - reserved
59 NULL
, // 0x0C - reserved
60 NULL
, // 0x0D - reserved
61 NULL
, // 0x0E - reserved
62 NULL
, // 0x0F - reserved
63 "EFI_SECTION_PE32", // 0x10
64 "EFI_SECTION_PIC", // 0x11
65 "EFI_SECTION_TE", // 0x12
66 "EFI_SECTION_DXE_DEPEX", // 0x13
67 "EFI_SECTION_VERSION", // 0x14
68 "EFI_SECTION_USER_INTERFACE", // 0x15
69 "EFI_SECTION_COMPATIBILITY16", // 0x16
70 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17
71 "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18
72 "EFI_SECTION_RAW", // 0x19
74 "EFI_SECTION_PEI_DEPEX", // 0x1B
75 "EFI_SECTION_SMM_DEPEX" // 0x1C
78 STATIC CHAR8
*mCompressionTypeName
[] = { "PI_NONE", "PI_STD" };
80 #define EFI_GUIDED_SECTION_NONE 0x80
81 STATIC CHAR8
*mGUIDedSectionAttribue
[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};
83 STATIC CHAR8
*mAlignName
[] = {
84 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
85 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K",
86 "512K", "1M", "2M", "4M", "8M", "16M"
90 // Crc32 GUID section related definitions.
93 EFI_GUID_DEFINED_SECTION GuidSectionHeader
;
95 } CRC32_SECTION_HEADER
;
98 EFI_GUID_DEFINED_SECTION2 GuidSectionHeader
;
100 } CRC32_SECTION_HEADER2
;
102 STATIC EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
103 STATIC EFI_GUID mEfiCrc32SectionGuid
= EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID
;
114 Print out version information for this utility.
126 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
153 fprintf (stdout
, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME
);
156 // Copyright declaration
158 fprintf (stdout
, "Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.\n\n");
163 fprintf (stdout
, "Options:\n");
164 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
165 File is the SectionFile to be created.\n");
166 fprintf (stdout
, " -s [SectionType], --sectiontype [SectionType]\n\
167 SectionType defined in PI spec is one type of\n\
168 EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\
169 EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\
170 EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\
171 EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\
172 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\
173 EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\
174 EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\
175 if -s option is not given, \n\
176 EFI_SECTION_ALL is default section type.\n");
177 fprintf (stdout
, " -c [Type], --compress [Type]\n\
178 Compress method type can be PI_NONE or PI_STD.\n\
179 if -c option is not given, PI_STD is default type.\n");
180 fprintf (stdout
, " -g GuidValue, --vendor GuidValue\n\
181 GuidValue is one specific vendor guid value.\n\
182 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
183 fprintf (stdout
, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
184 GuidHeaderLength is the size of header of guided data\n");
185 fprintf (stdout
, " -r GuidAttr, --attributes GuidAttr\n\
186 GuidAttr is guid section atttributes, which may be\n\
187 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
188 if -r option is not given, default PROCESSING_REQUIRED\n");
189 fprintf (stdout
, " -n String, --name String\n\
190 String is a NULL terminated string used in Ui section.\n");
191 fprintf (stdout
, " -j Number, --buildnumber Number\n\
192 Number is an integer value between 0 and 65535\n\
193 used in Ver section.\n");
194 fprintf (stdout
, " --sectionalign SectionAlign\n\
195 SectionAlign points to section alignment, which support\n\
196 the alignment scope 0~16M. If SectionAlign is specified\n\
197 as 0, tool get alignment value from SectionFile. It is\n\
198 specified in same order that the section file is input.\n");
199 fprintf (stdout
, " --dummy dummyfile\n\
200 compare dummpyfile with input_file to decide whether\n\
201 need to set PROCESSING_REQUIRED attribute.\n");
202 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
203 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
204 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
205 fprintf (stdout
, " --version Show program's version number and exit.\n");
206 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
210 Ascii2UnicodeString (
218 Write ascii string as unicode string format to FILE
222 String - Pointer to string that is written to FILE.
223 UniString - Pointer to unicode string
231 while (*String
!= '\0') {
232 *(UniString
++) = (CHAR16
) *(String
++);
235 // End the UniString with a NULL.
241 GenSectionCommonLeafSection (
242 CHAR8
**InputFileName
,
245 UINT8
**OutFileBuffer
251 Generate a leaf section of type other than EFI_SECTION_VERSION
252 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
253 The function won't validate the input file's contents. For
254 common leaf sections, the input file may be a binary file.
255 The utility will add section header to the file.
259 InputFileName - Name of the input file.
261 InputFileNum - Number of input files. Should be 1 for leaf section.
263 SectionType - A valid section type string
265 OutFileBuffer - Buffer pointer to Output file contents
269 STATUS_ERROR - can't continue
270 STATUS_SUCCESS - successful return
274 UINT32 InputFileLength
;
279 EFI_COMMON_SECTION_HEADER
*CommonSect
;
282 if (InputFileNum
> 1) {
283 Error (NULL
, 0, 2000, "Invalid parameter", "more than one input file specified");
285 } else if (InputFileNum
< 1) {
286 Error (NULL
, 0, 2000, "Invalid parameter", "no input file specified");
290 // Open the input file
292 InFile
= fopen (LongFilePath (InputFileName
[0]), "rb");
293 if (InFile
== NULL
) {
294 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[0]);
298 Status
= STATUS_ERROR
;
301 // Seek to the end of the input file so we can determine its size
303 fseek (InFile
, 0, SEEK_END
);
304 InputFileLength
= ftell (InFile
);
305 fseek (InFile
, 0, SEEK_SET
);
306 DebugMsg (NULL
, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName
[0], (unsigned) InputFileLength
);
307 TotalLength
= sizeof (EFI_COMMON_SECTION_HEADER
) + InputFileLength
;
309 // Size must fit in 3 bytes
311 //if (TotalLength >= MAX_SECTION_SIZE) {
312 // Error (NULL, 0, 2000, "Invalid parameter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20);
315 HeaderLength
= sizeof (EFI_COMMON_SECTION_HEADER
);
316 if (TotalLength
>= MAX_SECTION_SIZE
) {
317 TotalLength
= sizeof (EFI_COMMON_SECTION_HEADER2
) + InputFileLength
;
318 HeaderLength
= sizeof (EFI_COMMON_SECTION_HEADER2
);
320 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
322 // Fill in the fields in the local section header structure
324 Buffer
= (UINT8
*) malloc ((size_t) TotalLength
);
325 if (Buffer
== NULL
) {
326 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
329 CommonSect
= (EFI_COMMON_SECTION_HEADER
*) Buffer
;
330 CommonSect
->Type
= SectionType
;
331 if (TotalLength
< MAX_SECTION_SIZE
) {
332 CommonSect
->Size
[0] = (UINT8
) (TotalLength
& 0xff);
333 CommonSect
->Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
334 CommonSect
->Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
336 memset(CommonSect
->Size
, 0xff, sizeof(UINT8
) * 3);
337 ((EFI_COMMON_SECTION_HEADER2
*)CommonSect
)->ExtendedSize
= TotalLength
;
341 // read data from the input file.
343 if (InputFileLength
!= 0) {
344 if (fread (Buffer
+ HeaderLength
, (size_t) InputFileLength
, 1, InFile
) != 1) {
345 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[0]);
353 *OutFileBuffer
= Buffer
;
354 Status
= STATUS_SUCCESS
;
365 IN CHAR8
*AlignBuffer
,
366 OUT UINT32
*AlignNumber
372 Converts Align String to align value (1~16M).
376 AlignBuffer - Pointer to Align string.
377 AlignNumber - Pointer to Align value.
381 EFI_SUCCESS Successfully convert align string to align value.
382 EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.
390 if (AlignBuffer
== NULL
) {
391 return EFI_INVALID_PARAMETER
;
393 for (Index
= 0; Index
< sizeof (mAlignName
) / sizeof (CHAR8
*); Index
++) {
394 if (stricmp (AlignBuffer
, mAlignName
[Index
]) == 0) {
395 *AlignNumber
= 1 << Index
;
399 return EFI_INVALID_PARAMETER
;
404 CHAR8
**InputFileName
,
405 UINT32
*InputFileAlign
,
414 Get the contents of all section files specified in InputFileName
419 InputFileName - Name of the input file.
421 InputFileAlign - Alignment required by the input file data.
423 InputFileNum - Number of input files. Should be at least 1.
425 FileBuffer - Output buffer to contain data
427 BufferLength - On input, this is size of the FileBuffer.
428 On output, this is the actual length of the data.
432 EFI_SUCCESS on successful return
433 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
434 EFI_ABORTED if unable to open input file.
435 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
443 EFI_COMMON_SECTION_HEADER
*SectHeader
;
444 EFI_COMMON_SECTION_HEADER2 TempSectHeader
;
445 EFI_TE_IMAGE_HEADER TeHeader
;
447 EFI_GUID_DEFINED_SECTION GuidSectHeader
;
448 EFI_GUID_DEFINED_SECTION2 GuidSectHeader2
;
451 if (InputFileNum
< 1) {
452 Error (NULL
, 0, 2000, "Invalid parameter", "must specify at least one input file");
453 return EFI_INVALID_PARAMETER
;
456 if (BufferLength
== NULL
) {
457 Error (NULL
, 0, 2000, "Invalid parameter", "BufferLength can't be NULL");
458 return EFI_INVALID_PARAMETER
;
465 // Go through our array of file names and copy their contents
466 // to the output buffer.
468 for (Index
= 0; Index
< InputFileNum
; Index
++) {
470 // make sure section ends on a DWORD boundary
472 while ((Size
& 0x03) != 0) {
473 if (FileBuffer
!= NULL
&& Size
< *BufferLength
) {
474 FileBuffer
[Size
] = 0;
480 // Open file and read contents
482 InFile
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
483 if (InFile
== NULL
) {
484 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
488 fseek (InFile
, 0, SEEK_END
);
489 FileSize
= ftell (InFile
);
490 fseek (InFile
, 0, SEEK_SET
);
491 DebugMsg (NULL
, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName
[Index
], (unsigned) FileSize
);
493 // Adjust section buffer when section alignment is required.
495 if (InputFileAlign
!= NULL
) {
497 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
501 // The section might be EFI_COMMON_SECTION_HEADER2
502 // But only Type needs to be checked
504 if (FileSize
>= MAX_SECTION_SIZE
) {
505 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER2
);
507 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER
);
509 fread (&TempSectHeader
, 1, HeaderSize
, InFile
);
510 if (TempSectHeader
.Type
== EFI_SECTION_TE
) {
511 fread (&TeHeader
, 1, sizeof (TeHeader
), InFile
);
512 if (TeHeader
.Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
513 TeOffset
= TeHeader
.StrippedSize
- sizeof (TeHeader
);
515 } else if (TempSectHeader
.Type
== EFI_SECTION_GUID_DEFINED
) {
516 fseek (InFile
, 0, SEEK_SET
);
517 if (FileSize
>= MAX_SECTION_SIZE
) {
518 fread (&GuidSectHeader2
, 1, sizeof (GuidSectHeader2
), InFile
);
519 if ((GuidSectHeader2
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
520 HeaderSize
= GuidSectHeader2
.DataOffset
;
523 fread (&GuidSectHeader
, 1, sizeof (GuidSectHeader
), InFile
);
524 if ((GuidSectHeader
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
525 HeaderSize
= GuidSectHeader
.DataOffset
;
530 fseek (InFile
, 0, SEEK_SET
);
533 // Revert TeOffset to the converse value relative to Alignment
534 // This is to assure the original PeImage Header at Alignment.
537 TeOffset
= InputFileAlign
[Index
] - (TeOffset
% InputFileAlign
[Index
]);
538 TeOffset
= TeOffset
% InputFileAlign
[Index
];
542 // make sure section data meet its alignment requirement by adding one raw pad section.
544 if ((InputFileAlign
[Index
] != 0) && (((Size
+ HeaderSize
+ TeOffset
) % InputFileAlign
[Index
]) != 0)) {
545 Offset
= (Size
+ sizeof (EFI_COMMON_SECTION_HEADER
) + HeaderSize
+ TeOffset
+ InputFileAlign
[Index
] - 1) & ~(InputFileAlign
[Index
] - 1);
546 Offset
= Offset
- Size
- HeaderSize
- TeOffset
;
548 if (FileBuffer
!= NULL
&& ((Size
+ Offset
) < *BufferLength
)) {
550 // The maximal alignment is 64K, the raw section size must be less than 0xffffff
552 memset (FileBuffer
+ Size
, 0, Offset
);
553 SectHeader
= (EFI_COMMON_SECTION_HEADER
*) (FileBuffer
+ Size
);
554 SectHeader
->Type
= EFI_SECTION_RAW
;
555 SectHeader
->Size
[0] = (UINT8
) (Offset
& 0xff);
556 SectHeader
->Size
[1] = (UINT8
) ((Offset
& 0xff00) >> 8);
557 SectHeader
->Size
[2] = (UINT8
) ((Offset
& 0xff0000) >> 16);
559 DebugMsg (NULL
, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset
);
561 Size
= Size
+ Offset
;
566 // Now read the contents of the file into the buffer
567 // Buffer must be enough to contain the file content.
569 if ((FileSize
> 0) && (FileBuffer
!= NULL
) && ((Size
+ FileSize
) <= *BufferLength
)) {
570 if (fread (FileBuffer
+ Size
, (size_t) FileSize
, 1, InFile
) != 1) {
571 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[Index
]);
582 // Set the real required buffer size.
584 if (Size
> *BufferLength
) {
585 *BufferLength
= Size
;
586 return EFI_BUFFER_TOO_SMALL
;
588 *BufferLength
= Size
;
594 GenSectionCompressionSection (
595 CHAR8
**InputFileName
,
596 UINT32
*InputFileAlign
,
598 UINT8 SectCompSubType
,
599 UINT8
**OutFileBuffer
605 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
606 Input file must be already sectioned. The function won't validate
607 the input files' contents. Caller should hand in files already
612 InputFileName - Name of the input file.
614 InputFileAlign - Alignment required by the input file data.
616 InputFileNum - Number of input files. Should be at least 1.
618 SectCompSubType - Specify the compression algorithm requested.
620 OutFileBuffer - Buffer pointer to Output file contents
624 EFI_SUCCESS on successful return
625 EFI_INVALID_PARAMETER if InputFileNum is less than 1
626 EFI_ABORTED if unable to open input file.
627 EFI_OUT_OF_RESOURCES No resource to complete the operation.
632 UINT32 CompressedLength
;
637 EFI_COMPRESSION_SECTION
*CompressionSect
;
638 EFI_COMPRESSION_SECTION2
*CompressionSect2
;
639 COMPRESS_FUNCTION CompressFunction
;
644 CompressedLength
= 0;
647 // read all input file contents into a buffer
648 // first get the size of all file contents
650 Status
= GetSectionContents (
658 if (Status
== EFI_BUFFER_TOO_SMALL
) {
659 FileBuffer
= (UINT8
*) malloc (InputLength
);
660 if (FileBuffer
== NULL
) {
661 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
662 return EFI_OUT_OF_RESOURCES
;
665 // read all input file contents into a buffer
667 Status
= GetSectionContents (
676 if (EFI_ERROR (Status
)) {
677 if (FileBuffer
!= NULL
) {
683 if (FileBuffer
== NULL
) {
684 return EFI_OUT_OF_RESOURCES
;
687 CompressFunction
= NULL
;
690 // Now data is in FileBuffer, compress the data
692 switch (SectCompSubType
) {
693 case EFI_NOT_COMPRESSED
:
694 CompressedLength
= InputLength
;
695 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION
);
696 if (CompressedLength
+ HeaderLength
>= MAX_SECTION_SIZE
) {
697 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION2
);
699 TotalLength
= CompressedLength
+ HeaderLength
;
701 // Copy file buffer to the none compressed data.
703 OutputBuffer
= malloc (TotalLength
);
704 if (OutputBuffer
== NULL
) {
706 return EFI_OUT_OF_RESOURCES
;
708 memcpy (OutputBuffer
+ HeaderLength
, FileBuffer
, CompressedLength
);
710 FileBuffer
= OutputBuffer
;
713 case EFI_STANDARD_COMPRESSION
:
714 CompressFunction
= (COMPRESS_FUNCTION
) EfiCompress
;
718 Error (NULL
, 0, 2000, "Invalid parameter", "unknown compression type");
723 if (CompressFunction
!= NULL
) {
725 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
, &CompressedLength
);
726 if (Status
== EFI_BUFFER_TOO_SMALL
) {
727 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION
);
728 if (CompressedLength
+ HeaderLength
>= MAX_SECTION_SIZE
) {
729 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION2
);
731 TotalLength
= CompressedLength
+ HeaderLength
;
732 OutputBuffer
= malloc (TotalLength
);
735 return EFI_OUT_OF_RESOURCES
;
738 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
+ HeaderLength
, &CompressedLength
);
742 FileBuffer
= OutputBuffer
;
744 if (EFI_ERROR (Status
)) {
745 if (FileBuffer
!= NULL
) {
752 if (FileBuffer
== NULL
) {
753 return EFI_OUT_OF_RESOURCES
;
757 DebugMsg (NULL
, 0, 9, "comprss file size",
758 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength
, (unsigned) CompressedLength
);
760 //if (TotalLength >= MAX_SECTION_SIZE) {
761 // Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);
762 // if (FileBuffer != NULL) {
763 // free (FileBuffer);
765 // if (OutputBuffer != NULL) {
766 // free (OutputBuffer);
768 // return STATUS_ERROR;
770 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
773 // Add the section header for the compressed data
775 if (TotalLength
>= MAX_SECTION_SIZE
) {
776 CompressionSect2
= (EFI_COMPRESSION_SECTION2
*)FileBuffer
;
778 memset(CompressionSect2
->CommonHeader
.Size
, 0xff, sizeof(UINT8
) * 3);
779 CompressionSect2
->CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
780 CompressionSect2
->CommonHeader
.ExtendedSize
= TotalLength
;
781 CompressionSect2
->CompressionType
= SectCompSubType
;
782 CompressionSect2
->UncompressedLength
= InputLength
;
784 CompressionSect
= (EFI_COMPRESSION_SECTION
*) FileBuffer
;
786 CompressionSect
->CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
787 CompressionSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
788 CompressionSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
789 CompressionSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
790 CompressionSect
->CompressionType
= SectCompSubType
;
791 CompressionSect
->UncompressedLength
= InputLength
;
797 *OutFileBuffer
= FileBuffer
;
803 GenSectionGuidDefinedSection (
804 CHAR8
**InputFileName
,
805 UINT32
*InputFileAlign
,
807 EFI_GUID
*VendorGuid
,
808 UINT16 DataAttribute
,
809 UINT32 DataHeaderSize
,
810 UINT8
**OutFileBuffer
816 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
817 Input file must be already sectioned. The function won't validate
818 the input files' contents. Caller should hand in files already
823 InputFileName - Name of the input file.
825 InputFileAlign - Alignment required by the input file data.
827 InputFileNum - Number of input files. Should be at least 1.
829 VendorGuid - Specify vendor guid value.
831 DataAttribute - Specify attribute for the vendor guid data.
833 DataHeaderSize- Guided Data Header Size
835 OutFileBuffer - Buffer pointer to Output file contents
839 EFI_SUCCESS on successful return
840 EFI_INVALID_PARAMETER if InputFileNum is less than 1
841 EFI_ABORTED if unable to open input file.
842 EFI_OUT_OF_RESOURCES No resource to complete the operation.
850 UINT32 Crc32Checksum
;
852 CRC32_SECTION_HEADER
*Crc32GuidSect
;
853 CRC32_SECTION_HEADER2
*Crc32GuidSect2
;
854 EFI_GUID_DEFINED_SECTION
*VendorGuidSect
;
855 EFI_GUID_DEFINED_SECTION2
*VendorGuidSect2
;
863 // read all input file contents into a buffer
864 // first get the size of all file contents
866 Status
= GetSectionContents (
874 if (Status
== EFI_BUFFER_TOO_SMALL
) {
875 if (CompareGuid (VendorGuid
, &mZeroGuid
) == 0) {
876 Offset
= sizeof (CRC32_SECTION_HEADER
);
877 if (InputLength
+ Offset
>= MAX_SECTION_SIZE
) {
878 Offset
= sizeof (CRC32_SECTION_HEADER2
);
881 Offset
= sizeof (EFI_GUID_DEFINED_SECTION
);
882 if (InputLength
+ Offset
>= MAX_SECTION_SIZE
) {
883 Offset
= sizeof (EFI_GUID_DEFINED_SECTION2
);
886 TotalLength
= InputLength
+ Offset
;
888 FileBuffer
= (UINT8
*) malloc (InputLength
+ Offset
);
889 if (FileBuffer
== NULL
) {
890 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
891 return EFI_OUT_OF_RESOURCES
;
894 // read all input file contents into a buffer
896 Status
= GetSectionContents (
905 if (EFI_ERROR (Status
)) {
906 if (FileBuffer
!= NULL
) {
909 Error (NULL
, 0, 0001, "Error opening file for reading", InputFileName
[0]);
913 if (InputLength
== 0) {
914 if (FileBuffer
!= NULL
) {
917 Error (NULL
, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName
);
918 return EFI_NOT_FOUND
;
922 // InputLength != 0, but FileBuffer == NULL means out of resources.
924 if (FileBuffer
== NULL
) {
925 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
926 return EFI_OUT_OF_RESOURCES
;
930 // Now data is in FileBuffer + Offset
932 if (CompareGuid (VendorGuid
, &mZeroGuid
) == 0) {
934 // Default Guid section is CRC32.
937 CalculateCrc32 (FileBuffer
+ Offset
, InputLength
, &Crc32Checksum
);
939 if (TotalLength
>= MAX_SECTION_SIZE
) {
940 Crc32GuidSect2
= (CRC32_SECTION_HEADER2
*) FileBuffer
;
941 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
942 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) 0xff;
943 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) 0xff;
944 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) 0xff;
945 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.ExtendedSize
= TotalLength
;
946 memcpy (&(Crc32GuidSect2
->GuidSectionHeader
.SectionDefinitionGuid
), &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
947 Crc32GuidSect2
->GuidSectionHeader
.Attributes
= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
948 Crc32GuidSect2
->GuidSectionHeader
.DataOffset
= sizeof (CRC32_SECTION_HEADER2
);
949 Crc32GuidSect2
->CRC32Checksum
= Crc32Checksum
;
950 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2
->GuidSectionHeader
.DataOffset
);
952 Crc32GuidSect
= (CRC32_SECTION_HEADER
*) FileBuffer
;
953 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
954 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
955 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
956 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
957 memcpy (&(Crc32GuidSect
->GuidSectionHeader
.SectionDefinitionGuid
), &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
958 Crc32GuidSect
->GuidSectionHeader
.Attributes
= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
959 Crc32GuidSect
->GuidSectionHeader
.DataOffset
= sizeof (CRC32_SECTION_HEADER
);
960 Crc32GuidSect
->CRC32Checksum
= Crc32Checksum
;
961 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect
->GuidSectionHeader
.DataOffset
);
964 if (TotalLength
>= MAX_SECTION_SIZE
) {
965 VendorGuidSect2
= (EFI_GUID_DEFINED_SECTION2
*) FileBuffer
;
966 VendorGuidSect2
->CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
967 VendorGuidSect2
->CommonHeader
.Size
[0] = (UINT8
) 0xff;
968 VendorGuidSect2
->CommonHeader
.Size
[1] = (UINT8
) 0xff;
969 VendorGuidSect2
->CommonHeader
.Size
[2] = (UINT8
) 0xff;
970 VendorGuidSect2
->CommonHeader
.ExtendedSize
= InputLength
+ sizeof (EFI_GUID_DEFINED_SECTION2
);
971 memcpy (&(VendorGuidSect2
->SectionDefinitionGuid
), VendorGuid
, sizeof (EFI_GUID
));
972 VendorGuidSect2
->Attributes
= DataAttribute
;
973 VendorGuidSect2
->DataOffset
= (UINT16
) (sizeof (EFI_GUID_DEFINED_SECTION2
) + DataHeaderSize
);
974 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2
->DataOffset
);
976 VendorGuidSect
= (EFI_GUID_DEFINED_SECTION
*) FileBuffer
;
977 VendorGuidSect
->CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
978 VendorGuidSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
979 VendorGuidSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
980 VendorGuidSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
981 memcpy (&(VendorGuidSect
->SectionDefinitionGuid
), VendorGuid
, sizeof (EFI_GUID
));
982 VendorGuidSect
->Attributes
= DataAttribute
;
983 VendorGuidSect
->DataOffset
= (UINT16
) (sizeof (EFI_GUID_DEFINED_SECTION
) + DataHeaderSize
);
984 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect
->DataOffset
);
987 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
992 *OutFileBuffer
= FileBuffer
;
1000 IN UINTN FileOffset
,
1001 IN OUT UINT32
*ReadSize
,
1006 Routine Description:
1008 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1012 FileHandle - The handle to the PE/COFF file
1014 FileOffset - The offset, in bytes, into the file to read
1016 ReadSize - The number of bytes to read from the file starting at FileOffset
1018 Buffer - A pointer to the buffer to read the data into.
1022 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1026 CHAR8
*Destination8
;
1030 Destination8
= Buffer
;
1031 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1034 *(Destination8
++) = *(Source8
++);
1042 GetAlignmentFromFile(char *InFile
, UINT32
*Alignment
)
1044 InFile is input file for getting alignment
1045 return the alignment
1049 UINT8
*PeFileBuffer
;
1051 UINT32 CurSecHdrSize
;
1052 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1053 EFI_COMMON_SECTION_HEADER
*CommonHeader
;
1056 InFileHandle
= NULL
;
1057 PeFileBuffer
= NULL
;
1060 memset (&ImageContext
, 0, sizeof (ImageContext
));
1062 InFileHandle
= fopen(LongFilePath(InFile
), "rb");
1063 if (InFileHandle
== NULL
){
1064 Error (NULL
, 0, 0001, "Error opening file", InFile
);
1067 PeFileSize
= _filelength (fileno(InFileHandle
));
1068 PeFileBuffer
= (UINT8
*) malloc (PeFileSize
);
1069 if (PeFileBuffer
== NULL
) {
1070 fclose (InFileHandle
);
1071 Error(NULL
, 0, 4001, "Resource", "memory cannot be allocated of %s", InFileHandle
);
1072 return EFI_OUT_OF_RESOURCES
;
1074 fread (PeFileBuffer
, sizeof (UINT8
), PeFileSize
, InFileHandle
);
1075 fclose (InFileHandle
);
1076 CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) PeFileBuffer
;
1077 CurSecHdrSize
= GetSectionHeaderLength(CommonHeader
);
1078 ImageContext
.Handle
= (VOID
*) ((UINTN
)PeFileBuffer
+ CurSecHdrSize
);
1079 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
)FfsRebaseImageRead
;
1080 Status
= PeCoffLoaderGetImageInfo(&ImageContext
);
1081 if (EFI_ERROR (Status
)) {
1082 Error (NULL
, 0, 3000, "Invalid PeImage", "The input file is %s and return status is %x", InFile
, (int) Status
);
1085 *Alignment
= ImageContext
.SectionAlignment
;
1086 // Free the allocated memory resource
1087 if (PeFileBuffer
!= NULL
) {
1088 free (PeFileBuffer
);
1089 PeFileBuffer
= NULL
;
1101 Routine Description:
1107 command line parameters
1111 EFI_SUCCESS Section header successfully generated and section concatenated.
1112 EFI_ABORTED Could not generate the section
1113 EFI_OUT_OF_RESOURCES No resource to complete the operation.
1118 UINT32 InputFileNum
;
1120 CHAR8
**InputFileName
;
1121 CHAR8
*OutputFileName
;
1123 CHAR8
*CompressionName
;
1124 CHAR8
*StringBuffer
;
1125 EFI_GUID VendorGuid
= mZeroGuid
;
1128 UINT8 SectCompSubType
;
1129 UINT16 SectGuidAttribute
;
1130 UINT64 SectGuidHeaderLength
;
1131 EFI_VERSION_SECTION
*VersionSect
;
1132 EFI_USER_INTERFACE_SECTION
*UiSect
;
1134 UINT8
*OutFileBuffer
;
1137 UINT32
*InputFileAlign
;
1138 UINT32 InputFileAlignNum
;
1139 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
1140 CHAR8
*DummyFileName
;
1142 UINTN DummyFileSize
;
1143 UINT8
*DummyFileBuffer
;
1145 UINT8
*InFileBuffer
;
1148 InputFileAlign
= NULL
;
1149 InputFileAlignNum
= 0;
1150 InputFileName
= NULL
;
1151 OutputFileName
= NULL
;
1153 CompressionName
= NULL
;
1158 SectType
= EFI_SECTION_ALL
;
1159 SectCompSubType
= 0;
1160 SectGuidAttribute
= EFI_GUIDED_SECTION_NONE
;
1161 OutFileBuffer
= NULL
;
1163 Status
= STATUS_SUCCESS
;
1165 SectGuidHeaderLength
= 0;
1169 DummyFileName
= NULL
;
1171 DummyFileBuffer
= NULL
;
1174 InFileBuffer
= NULL
;
1176 SetUtilityName (UTILITY_NAME
);
1179 Error (NULL
, 0, 1001, "Missing options", "No options input");
1181 return STATUS_ERROR
;
1185 // Parse command line
1190 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1193 return STATUS_SUCCESS
;
1196 if (stricmp (argv
[0], "--version") == 0) {
1198 return STATUS_SUCCESS
;
1202 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--SectionType") == 0)) {
1203 SectionName
= argv
[1];
1204 if (SectionName
== NULL
) {
1205 Error (NULL
, 0, 1003, "Invalid option value", "Section Type can't be NULL");
1213 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1214 OutputFileName
= argv
[1];
1215 if (OutputFileName
== NULL
) {
1216 Error (NULL
, 0, 1003, "Invalid option value", "Output file can't be NULL");
1224 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--compress") == 0)) {
1225 CompressionName
= argv
[1];
1226 if (CompressionName
== NULL
) {
1227 Error (NULL
, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
1235 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--vendor") == 0)) {
1236 Status
= StringToGuid (argv
[1], &VendorGuid
);
1237 if (EFI_ERROR (Status
)) {
1238 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1245 if (stricmp (argv
[0], "--dummy") == 0) {
1246 DummyFileName
= argv
[1];
1247 if (DummyFileName
== NULL
) {
1248 Error (NULL
, 0, 1003, "Invalid option value", "Dummy file can't be NULL");
1256 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--attributes") == 0)) {
1257 if (argv
[1] == NULL
) {
1258 Error (NULL
, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL");
1261 if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]) == 0) {
1262 SectGuidAttribute
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1263 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]) == 0) {
1264 SectGuidAttribute
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
1265 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[0]) == 0) {
1269 SectGuidAttribute
|= EFI_GUIDED_SECTION_NONE
;
1271 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1279 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--HeaderLength") == 0)) {
1280 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &SectGuidHeaderLength
);
1281 if (EFI_ERROR (Status
)) {
1282 Error (NULL
, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv
[0], argv
[1]);
1290 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--name") == 0)) {
1291 StringBuffer
= argv
[1];
1292 if (StringBuffer
== NULL
) {
1293 Error (NULL
, 0, 1003, "Invalid option value", "Name can't be NULL");
1301 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--buildnumber") == 0)) {
1302 if (argv
[1] == NULL
) {
1303 Error (NULL
, 0, 1003, "Invalid option value", "build number can't be NULL");
1307 // Verify string is a integrator number
1309 for (Index
= 0; Index
< strlen (argv
[1]); Index
++) {
1310 if ((argv
[1][Index
] != '-') && (isdigit ((int)argv
[1][Index
]) == 0)) {
1311 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1316 sscanf (argv
[1], "%d", &VersionNumber
);
1322 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1323 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1324 VerboseMsg ("Verbose output Mode Set!");
1330 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1331 SetPrintLevel (KEY_LOG_LEVEL
);
1332 KeyMsg ("Quiet output Mode Set!");
1338 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1339 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1340 if (EFI_ERROR (Status
)) {
1341 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1345 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel
);
1348 SetPrintLevel (LogLevel
);
1349 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1356 // Section File alignment requirement
1358 if (stricmp (argv
[0], "--sectionalign") == 0) {
1359 if (InputFileAlignNum
== 0) {
1360 InputFileAlign
= (UINT32
*) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1361 if (InputFileAlign
== NULL
) {
1362 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1365 memset (InputFileAlign
, 1, MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1366 } else if (InputFileAlignNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1367 InputFileAlign
= (UINT32
*) realloc (
1369 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (UINT32
)
1372 if (InputFileAlign
== NULL
) {
1373 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1376 memset (&(InputFileAlign
[InputFileNum
]), 1, (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
)));
1378 if (stricmp(argv
[1], "0") == 0) {
1379 InputFileAlign
[InputFileAlignNum
] = 0;
1381 Status
= StringtoAlignment (argv
[1], &(InputFileAlign
[InputFileAlignNum
]));
1382 if (EFI_ERROR (Status
)) {
1383 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1389 InputFileAlignNum
++;
1394 // Get Input file name
1396 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1397 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1398 if (InputFileName
== NULL
) {
1399 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1402 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1403 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1405 // InputFileName buffer too small, need to realloc
1407 InputFileName
= (CHAR8
**) realloc (
1409 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1412 if (InputFileName
== NULL
) {
1413 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1416 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1419 InputFileName
[InputFileNum
++] = argv
[0];
1424 if (InputFileAlignNum
> 0 && InputFileAlignNum
!= InputFileNum
) {
1425 Error (NULL
, 0, 1003, "Invalid option", "section alignment must be set for each section");
1428 for (Index
= 0; Index
< InputFileAlignNum
; Index
++)
1430 if (InputFileAlign
[Index
] == 0) {
1431 Status
= GetAlignmentFromFile(InputFileName
[Index
], &(InputFileAlign
[Index
]));
1432 if (EFI_ERROR(Status
)) {
1433 Error (NULL
, 0, 1003, "Fail to get Alignment from %s", InputFileName
[InputFileNum
]);
1439 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1441 if (DummyFileName
!= NULL
) {
1443 // Open file and read contents
1445 DummyFile
= fopen (LongFilePath (DummyFileName
), "rb");
1446 if (DummyFile
== NULL
) {
1447 Error (NULL
, 0, 0001, "Error opening file", DummyFileName
);
1451 fseek (DummyFile
, 0, SEEK_END
);
1452 DummyFileSize
= ftell (DummyFile
);
1453 fseek (DummyFile
, 0, SEEK_SET
);
1454 DummyFileBuffer
= (UINT8
*) malloc (DummyFileSize
);
1455 if (DummyFileBuffer
== NULL
) {
1457 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1461 fread(DummyFileBuffer
, 1, DummyFileSize
, DummyFile
);
1463 DebugMsg (NULL
, 0, 9, "Dummy files", "the dummy file name is %s and the size is %u bytes", DummyFileName
, (unsigned) DummyFileSize
);
1465 if (InputFileName
== NULL
) {
1466 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1469 InFile
= fopen(LongFilePath(InputFileName
[0]), "rb");
1470 if (InFile
== NULL
) {
1471 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[0]);
1475 fseek (InFile
, 0, SEEK_END
);
1476 InFileSize
= ftell (InFile
);
1477 fseek (InFile
, 0, SEEK_SET
);
1478 InFileBuffer
= (UINT8
*) malloc (InFileSize
);
1479 if (InFileBuffer
== NULL
) {
1481 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1485 fread(InFileBuffer
, 1, InFileSize
, InFile
);
1487 DebugMsg (NULL
, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName
[0], (unsigned) InFileSize
);
1488 if (InFileSize
> DummyFileSize
){
1489 if (stricmp((CHAR8
*)DummyFileBuffer
, (CHAR8
*)(InFileBuffer
+ (InFileSize
- DummyFileSize
))) == 0){
1490 SectGuidHeaderLength
= InFileSize
- DummyFileSize
;
1493 if (SectGuidHeaderLength
== 0) {
1494 SectGuidAttribute
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1496 if (DummyFileBuffer
!= NULL
) {
1497 free (DummyFileBuffer
);
1498 DummyFileBuffer
= NULL
;
1500 if (InFileBuffer
!= NULL
) {
1501 free (InFileBuffer
);
1506 // Parse all command line parameters to get the corresponding section type.
1508 VerboseMsg ("Section type is %s", SectionName
);
1509 if (SectionName
== NULL
) {
1511 // No specified Section type, default is SECTION_ALL.
1513 SectType
= EFI_SECTION_ALL
;
1514 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPRESSION
]) == 0) {
1515 SectType
= EFI_SECTION_COMPRESSION
;
1516 if (CompressionName
== NULL
) {
1518 // Default is PI_STD compression algorithm.
1520 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1521 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_NOT_COMPRESSED
]) == 0) {
1522 SectCompSubType
= EFI_NOT_COMPRESSED
;
1523 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_STANDARD_COMPRESSION
]) == 0) {
1524 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1526 Error (NULL
, 0, 1003, "Invalid option value", "--compress = %s", CompressionName
);
1529 VerboseMsg ("Compress method is %s", mCompressionTypeName
[SectCompSubType
]);
1530 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_GUID_DEFINED
]) == 0) {
1531 SectType
= EFI_SECTION_GUID_DEFINED
;
1533 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_NONE
) != 0) {
1535 // NONE attribute, clear attribute value.
1537 SectGuidAttribute
= SectGuidAttribute
& ~EFI_GUIDED_SECTION_NONE
;
1539 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1540 (unsigned) VendorGuid
.Data1
,
1543 VendorGuid
.Data4
[0],
1544 VendorGuid
.Data4
[1],
1545 VendorGuid
.Data4
[2],
1546 VendorGuid
.Data4
[3],
1547 VendorGuid
.Data4
[4],
1548 VendorGuid
.Data4
[5],
1549 VendorGuid
.Data4
[6],
1550 VendorGuid
.Data4
[7]);
1551 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
1552 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]);
1554 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
1555 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]);
1557 if (SectGuidHeaderLength
!= 0) {
1558 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength
);
1560 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PE32
]) == 0) {
1561 SectType
= EFI_SECTION_PE32
;
1562 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PIC
]) == 0) {
1563 SectType
= EFI_SECTION_PIC
;
1564 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_TE
]) == 0) {
1565 SectType
= EFI_SECTION_TE
;
1566 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_DXE_DEPEX
]) == 0) {
1567 SectType
= EFI_SECTION_DXE_DEPEX
;
1568 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_SMM_DEPEX
]) == 0) {
1569 SectType
= EFI_SECTION_SMM_DEPEX
;
1570 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_VERSION
]) == 0) {
1571 SectType
= EFI_SECTION_VERSION
;
1572 if (VersionNumber
< 0 || VersionNumber
> 65535) {
1573 Error (NULL
, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber
);
1576 VerboseMsg ("Version section number is %d", VersionNumber
);
1577 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_USER_INTERFACE
]) == 0) {
1578 SectType
= EFI_SECTION_USER_INTERFACE
;
1579 if (StringBuffer
[0] == '\0') {
1580 Error (NULL
, 0, 1001, "Missing option", "user interface string");
1583 VerboseMsg ("UI section string name is %s", StringBuffer
);
1584 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPATIBILITY16
]) == 0) {
1585 SectType
= EFI_SECTION_COMPATIBILITY16
;
1586 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FIRMWARE_VOLUME_IMAGE
]) == 0) {
1587 SectType
= EFI_SECTION_FIRMWARE_VOLUME_IMAGE
;
1588 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FREEFORM_SUBTYPE_GUID
]) == 0) {
1589 SectType
= EFI_SECTION_FREEFORM_SUBTYPE_GUID
;
1590 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_RAW
]) == 0) {
1591 SectType
= EFI_SECTION_RAW
;
1592 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PEI_DEPEX
]) == 0) {
1593 SectType
= EFI_SECTION_PEI_DEPEX
;
1595 Error (NULL
, 0, 1003, "Invalid option value", "SectionType = %s", SectionName
);
1600 // GuidValue is only required by Guided section.
1602 if ((SectType
!= EFI_SECTION_GUID_DEFINED
) &&
1603 (SectionName
!= NULL
) &&
1604 (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1605 fprintf (stdout
, "Warning: the input guid value is not required for this section type %s\n", SectionName
);
1609 // Check whether there is input file
1611 if ((SectType
!= EFI_SECTION_VERSION
) && (SectType
!= EFI_SECTION_USER_INTERFACE
)) {
1613 // The input file are required for other section type.
1615 if (InputFileNum
== 0) {
1616 Error (NULL
, 0, 1001, "Missing options", "Input files");
1621 // Check whether there is output file
1623 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1624 VerboseMsg ("the %uth input file name is %s", (unsigned) Index
, InputFileName
[Index
]);
1626 if (OutputFileName
== NULL
) {
1627 Error (NULL
, 0, 1001, "Missing options", "Output file");
1629 // OutFile = stdout;
1631 VerboseMsg ("Output file name is %s", OutputFileName
);
1634 // At this point, we've fully validated the command line, and opened appropriate
1635 // files, so let's go and do what we've been asked to do...
1638 // Within this switch, build and write out the section header including any
1639 // section type specific pieces. If there's an input file, it's tacked on later
1642 case EFI_SECTION_COMPRESSION
:
1643 if (InputFileAlign
!= NULL
) {
1644 free (InputFileAlign
);
1645 InputFileAlign
= NULL
;
1647 Status
= GenSectionCompressionSection (
1656 case EFI_SECTION_GUID_DEFINED
:
1657 if (InputFileAlign
!= NULL
&& (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1659 // Only process alignment for the default known CRC32 guided section.
1660 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
1662 free (InputFileAlign
);
1663 InputFileAlign
= NULL
;
1665 Status
= GenSectionGuidDefinedSection (
1671 (UINT32
) SectGuidHeaderLength
,
1676 case EFI_SECTION_VERSION
:
1677 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1679 // 2 bytes for the build number UINT16
1683 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1685 Index
+= (strlen (StringBuffer
) * 2) + 2;
1686 OutFileBuffer
= (UINT8
*) malloc (Index
);
1687 if (OutFileBuffer
== NULL
) {
1688 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1691 VersionSect
= (EFI_VERSION_SECTION
*) OutFileBuffer
;
1692 VersionSect
->CommonHeader
.Type
= SectType
;
1693 VersionSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1694 VersionSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1695 VersionSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1696 VersionSect
->BuildNumber
= (UINT16
) VersionNumber
;
1697 Ascii2UnicodeString (StringBuffer
, VersionSect
->VersionString
);
1698 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1701 case EFI_SECTION_USER_INTERFACE
:
1702 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1704 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1706 Index
+= (strlen (StringBuffer
) * 2) + 2;
1707 OutFileBuffer
= (UINT8
*) malloc (Index
);
1708 if (OutFileBuffer
== NULL
) {
1709 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1712 UiSect
= (EFI_USER_INTERFACE_SECTION
*) OutFileBuffer
;
1713 UiSect
->CommonHeader
.Type
= SectType
;
1714 UiSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1715 UiSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1716 UiSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1717 Ascii2UnicodeString (StringBuffer
, UiSect
->FileNameString
);
1718 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1721 case EFI_SECTION_ALL
:
1723 // read all input file contents into a buffer
1724 // first get the size of all file contents
1726 Status
= GetSectionContents (
1734 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1735 OutFileBuffer
= (UINT8
*) malloc (InputLength
);
1736 if (OutFileBuffer
== NULL
) {
1737 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1741 // read all input file contents into a buffer
1743 Status
= GetSectionContents (
1751 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength
);
1755 // All other section types are caught by default (they're all the same)
1757 Status
= GenSectionCommonLeafSection (
1766 if (Status
!= EFI_SUCCESS
|| OutFileBuffer
== NULL
) {
1767 Error (NULL
, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status
);
1772 // Get output file length
1774 if (SectType
!= EFI_SECTION_ALL
) {
1775 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*)OutFileBuffer
;
1776 InputLength
= *(UINT32
*)SectionHeader
->Size
& 0x00ffffff;
1777 if (InputLength
== 0xffffff) {
1778 InputLength
= ((EFI_COMMON_SECTION_HEADER2
*)SectionHeader
)->ExtendedSize
;
1783 // Write the output file
1785 OutFile
= fopen (LongFilePath (OutputFileName
), "wb");
1786 if (OutFile
== NULL
) {
1787 Error (NULL
, 0, 0001, "Error opening file for writing", OutputFileName
);
1791 fwrite (OutFileBuffer
, InputLength
, 1, OutFile
);
1794 if (InputFileName
!= NULL
) {
1795 free (InputFileName
);
1798 if (InputFileAlign
!= NULL
) {
1799 free (InputFileAlign
);
1802 if (OutFileBuffer
!= NULL
) {
1803 free (OutFileBuffer
);
1806 if (OutFile
!= NULL
) {
1810 if (DummyFileBuffer
!= NULL
) {
1811 free (DummyFileBuffer
);
1814 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
1816 return GetUtilityStatus ();