3 Copyright (c) 2004 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Creates output file that is a properly formed section per the PI spec.
27 #include <Common/UefiBaseTypes.h>
28 #include <Common/PiFirmwareFile.h>
29 #include <Protocol/GuidedSectionExtraction.h>
31 #include "CommonLib.h"
34 #include "EfiUtilityMsgs.h"
38 // GenSec Tool Information
40 #define UTILITY_NAME "GenSec"
41 #define UTILITY_MAJOR_VERSION 0
42 #define UTILITY_MINOR_VERSION 1
44 #define MAX_SECTION_SIZE 0x1000000
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"};
84 // Crc32 GUID section related definitions.
87 EFI_GUID_DEFINED_SECTION GuidSectionHeader
;
89 } CRC32_SECTION_HEADER
;
91 STATIC EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
92 STATIC EFI_GUID mEfiCrc32SectionGuid
= EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID
;
103 Print out version information for this utility.
115 fprintf (stdout
, "%s Version %d.%d\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
142 fprintf (stdout
, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME
);
145 // Copyright declaration
147 fprintf (stdout
, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
152 fprintf (stdout
, "Options:\n");
153 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
154 File is the SectionFile to be created.\n");
155 fprintf (stdout
, " -s [SectionType], --sectiontype [SectionType]\n\
156 SectionType defined in PI spec is one type of\n\
157 EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\
158 EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\
159 EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\
160 EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\
161 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\
162 EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\
163 EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\
164 if -s option is not given, \n\
165 EFI_SECTION_ALL is default section type.\n");
166 fprintf (stdout
, " -c [Type], --compress [Type]\n\
167 Compress method type can be PI_NONE or PI_STD.\n\
168 if -c option is not given, PI_STD is default type.\n");
169 fprintf (stdout
, " -g GuidValue, --vendor GuidValue\n\
170 GuidValue is one specific vendor guid value.\n\
171 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
172 fprintf (stdout
, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
173 GuidHeaderLength is the size of header of guided data\n");
174 fprintf (stdout
, " -r GuidAttr, --attributes GuidAttr\n\
175 GuidAttr is guid section atttributes, which may be\n\
176 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
177 if -r option is not given, default PROCESSING_REQUIRED\n");
178 fprintf (stdout
, " -n String, --name String\n\
179 String is a NULL terminated string used in Ui section.\n");
180 fprintf (stdout
, " -j Number, --buildnumber Number\n\
181 Number is an integer value between 0000 and 9999\n\
182 used in Ver section.\n");
183 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
184 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
185 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
186 fprintf (stdout
, " --version Show program's version number and exit.\n");
187 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
191 Ascii2UnicodeString (
199 Write ascii string as unicode string format to FILE
203 String - Pointer to string that is written to FILE.
204 UniString - Pointer to unicode string
212 while (*String
!= '\0') {
213 *(UniString
++) = (CHAR16
) *(String
++);
216 // End the UniString with a NULL.
222 GenSectionCommonLeafSection (
223 CHAR8
**InputFileName
,
226 UINT8
**OutFileBuffer
232 Generate a leaf section of type other than EFI_SECTION_VERSION
233 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
234 The function won't validate the input file's contents. For
235 common leaf sections, the input file may be a binary file.
236 The utility will add section header to the file.
240 InputFileName - Name of the input file.
242 InputFileNum - Number of input files. Should be 1 for leaf section.
244 SectionType - A valid section type string
246 OutFileBuffer - Buffer pointer to Output file contents
250 STATUS_ERROR - can't continue
251 STATUS_SUCCESS - successful return
255 UINT32 InputFileLength
;
259 EFI_COMMON_SECTION_HEADER
*CommonSect
;
262 if (InputFileNum
> 1) {
263 Error (NULL
, 0, 2000, "Invalid paramter", "more than one input file specified");
265 } else if (InputFileNum
< 1) {
266 Error (NULL
, 0, 2000, "Invalid paramter", "no input file specified");
270 // Open the input file
272 InFile
= fopen (InputFileName
[0], "rb");
273 if (InFile
== NULL
) {
274 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[0]);
278 Status
= STATUS_ERROR
;
281 // Seek to the end of the input file so we can determine its size
283 fseek (InFile
, 0, SEEK_END
);
284 InputFileLength
= ftell (InFile
);
285 fseek (InFile
, 0, SEEK_SET
);
286 DebugMsg (NULL
, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName
[0], (unsigned) InputFileLength
);
287 TotalLength
= sizeof (EFI_COMMON_SECTION_HEADER
) + InputFileLength
;
289 // Size must fit in 3 bytes
291 if (TotalLength
>= MAX_SECTION_SIZE
) {
292 Error (NULL
, 0, 2000, "Invalid paramter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName
[0], (unsigned) TotalLength
, MAX_SECTION_SIZE
>>20);
295 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
297 // Fill in the fields in the local section header structure
299 Buffer
= (UINT8
*) malloc ((size_t) TotalLength
);
300 if (Buffer
== NULL
) {
301 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
304 CommonSect
= (EFI_COMMON_SECTION_HEADER
*) Buffer
;
305 CommonSect
->Type
= SectionType
;
306 CommonSect
->Size
[0] = (UINT8
) (TotalLength
& 0xff);
307 CommonSect
->Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
308 CommonSect
->Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
311 // read data from the input file.
313 if (InputFileLength
!= 0) {
314 if (fread (Buffer
+ sizeof (EFI_COMMON_SECTION_HEADER
), (size_t) InputFileLength
, 1, InFile
) != 1) {
315 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[0]);
323 *OutFileBuffer
= Buffer
;
324 Status
= STATUS_SUCCESS
;
334 CHAR8
**InputFileName
,
343 Get the contents of all section files specified in InputFileName
348 InputFileName - Name of the input file.
350 InputFileNum - Number of input files. Should be at least 1.
352 FileBuffer - Output buffer to contain data
354 BufferLength - On input, this is size of the FileBuffer.
355 On output, this is the actual length of the data.
359 EFI_SUCCESS on successful return
360 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
361 EFI_ABORTED if unable to open input file.
362 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
370 if (InputFileNum
< 1) {
371 Error (NULL
, 0, 2000, "Invalid paramter", "must specify at least one input file");
372 return EFI_INVALID_PARAMETER
;
375 if (BufferLength
== NULL
) {
376 Error (NULL
, 0, 2000, "Invalid paramter", "BufferLength can't be NULL");
377 return EFI_INVALID_PARAMETER
;
382 // Go through our array of file names and copy their contents
383 // to the output buffer.
385 for (Index
= 0; Index
< InputFileNum
; Index
++) {
387 // make sure section ends on a DWORD boundary
389 while ((Size
& 0x03) != 0) {
390 if (FileBuffer
!= NULL
&& Size
< *BufferLength
) {
391 FileBuffer
[Size
] = 0;
397 // Open file and read contents
399 InFile
= fopen (InputFileName
[Index
], "rb");
400 if (InFile
== NULL
) {
401 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
405 fseek (InFile
, 0, SEEK_END
);
406 FileSize
= ftell (InFile
);
407 fseek (InFile
, 0, SEEK_SET
);
408 DebugMsg (NULL
, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName
[Index
], (unsigned) FileSize
);
410 // Now read the contents of the file into the buffer
411 // Buffer must be enough to contain the file content.
413 if (FileSize
> 0 && FileBuffer
!= NULL
&& (Size
+ FileSize
) <= *BufferLength
) {
414 if (fread (FileBuffer
+ Size
, (size_t) FileSize
, 1, InFile
) != 1) {
415 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[Index
]);
426 // Set the real required buffer size.
428 if (Size
> *BufferLength
) {
429 *BufferLength
= Size
;
430 return EFI_BUFFER_TOO_SMALL
;
432 *BufferLength
= Size
;
438 GenSectionCompressionSection (
439 CHAR8
**InputFileName
,
441 UINT8 SectCompSubType
,
442 UINT8
**OutFileBuffer
448 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
449 Input file must be already sectioned. The function won't validate
450 the input files' contents. Caller should hand in files already
455 InputFileName - Name of the input file.
457 InputFileNum - Number of input files. Should be at least 1.
459 SectCompSubType - Specify the compression algorithm requested.
461 OutFileBuffer - Buffer pointer to Output file contents
465 EFI_SUCCESS on successful return
466 EFI_INVALID_PARAMETER if InputFileNum is less than 1
467 EFI_ABORTED if unable to open input file.
468 EFI_OUT_OF_RESOURCES No resource to complete the operation.
473 UINT32 CompressedLength
;
477 EFI_COMPRESSION_SECTION
*CompressionSect
;
478 COMPRESS_FUNCTION CompressFunction
;
483 CompressedLength
= 0;
485 // read all input file contents into a buffer
486 // first get the size of all file contents
488 Status
= GetSectionContents (
495 if (Status
== EFI_BUFFER_TOO_SMALL
) {
496 FileBuffer
= (UINT8
*) malloc (InputLength
);
497 if (FileBuffer
== NULL
) {
498 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
499 return EFI_OUT_OF_RESOURCES
;
502 // read all input file contents into a buffer
504 Status
= GetSectionContents (
512 if (EFI_ERROR (Status
)) {
513 if (FileBuffer
!= NULL
) {
519 CompressFunction
= NULL
;
522 // Now data is in FileBuffer, compress the data
524 switch (SectCompSubType
) {
525 case EFI_NOT_COMPRESSED
:
526 CompressedLength
= InputLength
;
529 case EFI_STANDARD_COMPRESSION
:
530 CompressFunction
= (COMPRESS_FUNCTION
) EfiCompress
;
534 Error (NULL
, 0, 2000, "Invalid paramter", "unknown compression type");
539 if (CompressFunction
!= NULL
) {
541 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
, &CompressedLength
);
542 if (Status
== EFI_BUFFER_TOO_SMALL
) {
543 OutputBuffer
= malloc (CompressedLength
+ sizeof (EFI_COMPRESSION_SECTION
));
546 return EFI_OUT_OF_RESOURCES
;
549 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
+ sizeof (EFI_COMPRESSION_SECTION
), &CompressedLength
);
553 FileBuffer
= OutputBuffer
;
555 if (EFI_ERROR (Status
)) {
556 if (FileBuffer
!= NULL
) {
564 DebugMsg (NULL
, 0, 9, "comprss file size",
565 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength
, (unsigned) CompressedLength
);
566 TotalLength
= CompressedLength
+ sizeof (EFI_COMPRESSION_SECTION
);
567 if (TotalLength
>= MAX_SECTION_SIZE
) {
568 Error (NULL
, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE
>>20);
569 if (FileBuffer
!= NULL
) {
572 if (OutputBuffer
!= NULL
) {
577 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
580 // Add the section header for the compressed data
582 CompressionSect
= (EFI_COMPRESSION_SECTION
*) FileBuffer
;
584 CompressionSect
->CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
585 CompressionSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
586 CompressionSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
587 CompressionSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
588 CompressionSect
->CompressionType
= SectCompSubType
;
589 CompressionSect
->UncompressedLength
= InputLength
;
594 *OutFileBuffer
= FileBuffer
;
600 GenSectionGuidDefinedSection (
601 CHAR8
**InputFileName
,
603 EFI_GUID
*VendorGuid
,
604 UINT16 DataAttribute
,
605 UINT32 DataHeaderSize
,
606 UINT8
**OutFileBuffer
612 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
613 Input file must be already sectioned. The function won't validate
614 the input files' contents. Caller should hand in files already
619 InputFileName - Name of the input file.
621 InputFileNum - Number of input files. Should be at least 1.
623 VendorGuid - Specify vendor guid value.
625 DataAttribute - Specify attribute for the vendor guid data.
627 DataHeaderSize- Guided Data Header Size
629 OutFileBuffer - Buffer pointer to Output file contents
633 EFI_SUCCESS on successful return
634 EFI_INVALID_PARAMETER if InputFileNum is less than 1
635 EFI_ABORTED if unable to open input file.
636 EFI_OUT_OF_RESOURCES No resource to complete the operation.
644 UINT32 Crc32Checksum
;
646 CRC32_SECTION_HEADER
*Crc32GuidSect
;
647 EFI_GUID_DEFINED_SECTION
*VendorGuidSect
;
653 if (CompareGuid (VendorGuid
, &mEfiCrc32SectionGuid
) == 0) {
654 Offset
= sizeof (CRC32_SECTION_HEADER
);
656 Offset
= sizeof (EFI_GUID_DEFINED_SECTION
);
660 // read all input file contents into a buffer
661 // first get the size of all file contents
663 Status
= GetSectionContents (
670 if (Status
== EFI_BUFFER_TOO_SMALL
) {
671 FileBuffer
= (UINT8
*) malloc (InputLength
+ Offset
);
672 if (FileBuffer
== NULL
) {
673 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
674 return EFI_OUT_OF_RESOURCES
;
677 // read all input file contents into a buffer
679 Status
= GetSectionContents (
687 if (EFI_ERROR (Status
)) {
688 if (FileBuffer
!= NULL
) {
691 Error (NULL
, 0, 0001, "Error opening file for reading", InputFileName
[0]);
695 if (InputLength
== 0) {
696 Error (NULL
, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName
);
697 return EFI_NOT_FOUND
;
701 // Now data is in FileBuffer + Offset
703 if (CompareGuid (VendorGuid
, &mEfiCrc32SectionGuid
) == 0) {
705 // Default Guid section is CRC32.
708 CalculateCrc32 (FileBuffer
+ Offset
, InputLength
, &Crc32Checksum
);
710 TotalLength
= InputLength
+ sizeof (CRC32_SECTION_HEADER
);
711 if (TotalLength
>= MAX_SECTION_SIZE
) {
712 Error (NULL
, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE
>>20);
717 Crc32GuidSect
= (CRC32_SECTION_HEADER
*) FileBuffer
;
718 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
719 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
720 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
721 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
722 memcpy (&(Crc32GuidSect
->GuidSectionHeader
.SectionDefinitionGuid
), &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
723 Crc32GuidSect
->GuidSectionHeader
.Attributes
= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
724 Crc32GuidSect
->GuidSectionHeader
.DataOffset
= sizeof (CRC32_SECTION_HEADER
);
725 Crc32GuidSect
->CRC32Checksum
= Crc32Checksum
;
726 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect
->GuidSectionHeader
.DataOffset
);
729 TotalLength
= InputLength
+ sizeof (EFI_GUID_DEFINED_SECTION
);
730 if (TotalLength
>= MAX_SECTION_SIZE
) {
731 Error (NULL
, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE
>>20);
736 VendorGuidSect
= (EFI_GUID_DEFINED_SECTION
*) FileBuffer
;
737 VendorGuidSect
->CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
738 VendorGuidSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
739 VendorGuidSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
740 VendorGuidSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
741 memcpy (&(VendorGuidSect
->SectionDefinitionGuid
), VendorGuid
, sizeof (EFI_GUID
));
742 VendorGuidSect
->Attributes
= DataAttribute
;
743 VendorGuidSect
->DataOffset
= (UINT16
) (sizeof (EFI_GUID_DEFINED_SECTION
) + DataHeaderSize
);
744 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect
->DataOffset
);
746 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
751 *OutFileBuffer
= FileBuffer
;
769 command line parameters
773 EFI_SUCCESS Section header successfully generated and section concatenated.
774 EFI_ABORTED Could not generate the section
775 EFI_OUT_OF_RESOURCES No resource to complete the operation.
783 CHAR8
**InputFileName
;
784 CHAR8
*OutputFileName
;
786 CHAR8
*CompressionName
;
788 EFI_GUID VendorGuid
= mZeroGuid
;
791 UINT8 SectCompSubType
;
792 UINT16 SectGuidAttribute
;
793 UINT64 SectGuidHeaderLength
;
794 EFI_VERSION_SECTION
*VersionSect
;
795 EFI_USER_INTERFACE_SECTION
*UiSect
;
797 UINT8
*OutFileBuffer
;
801 InputFileName
= NULL
;
802 OutputFileName
= NULL
;
804 CompressionName
= NULL
;
810 SectType
= EFI_SECTION_ALL
;
812 SectGuidAttribute
= 0;
813 OutFileBuffer
= NULL
;
815 Status
= STATUS_SUCCESS
;
817 SectGuidHeaderLength
= 0;
821 SetUtilityName (UTILITY_NAME
);
824 Error (NULL
, 0, 1001, "Missing options", "No options input");
830 // Parse command line
835 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
838 return STATUS_SUCCESS
;
841 if (stricmp (argv
[0], "--version") == 0) {
843 return STATUS_SUCCESS
;
847 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--SectionType") == 0)) {
848 SectionName
= argv
[1];
849 if (SectionName
== NULL
) {
850 Error (NULL
, 0, 1003, "Invalid option value", "Section Type can't be NULL");
858 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
859 OutputFileName
= argv
[1];
860 if (OutputFileName
== NULL
) {
861 Error (NULL
, 0, 1003, "Invalid option value", "Output file can't be NULL");
869 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--compress") == 0)) {
870 CompressionName
= argv
[1];
871 if (CompressionName
== NULL
) {
872 Error (NULL
, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
880 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--vendor") == 0)) {
881 Status
= StringToGuid (argv
[1], &VendorGuid
);
882 if (EFI_ERROR (Status
)) {
883 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
891 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--attributes") == 0)) {
892 if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]) == 0) {
893 SectGuidAttribute
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
894 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]) == 0) {
895 SectGuidAttribute
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
896 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[0]) == 0) {
900 SectGuidAttribute
|= EFI_GUIDED_SECTION_NONE
;
902 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
910 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--HeaderLength") == 0)) {
911 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &SectGuidHeaderLength
);
912 if (EFI_ERROR (Status
)) {
913 Error (NULL
, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv
[0], argv
[1]);
921 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--name") == 0)) {
922 StringBuffer
= argv
[1];
923 if (StringBuffer
== NULL
) {
924 Error (NULL
, 0, 1003, "Invalid option value", "Name can't be NULL");
932 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--buildnumber") == 0)) {
933 if (argv
[1] == NULL
) {
934 Error (NULL
, 0, 1003, "Invalid option value", "build number can't be NULL");
938 // Verify string is a integrator number
940 for (Index
= 0; Index
< strlen (argv
[1]); Index
++) {
941 if ((argv
[1][Index
] != '-') && (isdigit (argv
[1][Index
]) == 0)) {
942 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
947 sscanf (argv
[1], "%d", &VersionNumber
);
953 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
954 SetPrintLevel (VERBOSE_LOG_LEVEL
);
955 VerboseMsg ("Verbose output Mode Set!");
961 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
962 SetPrintLevel (KEY_LOG_LEVEL
);
963 KeyMsg ("Quiet output Mode Set!");
969 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
970 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
971 if (EFI_ERROR (Status
)) {
972 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
976 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel
);
979 SetPrintLevel (LogLevel
);
980 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
987 // Get Input file name
989 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
990 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
991 if (InputFileName
== NULL
) {
992 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
996 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
997 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
999 // InputFileName buffer too small, need to realloc
1001 InputFileName
= (CHAR8
**) realloc (
1003 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1006 if (InputFileName
== NULL
) {
1007 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1011 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1014 InputFileName
[InputFileNum
++] = argv
[0];
1019 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1022 // Parse all command line parameters to get the corresponding section type.
1024 VerboseMsg ("Section type is %s", SectionName
);
1025 if (SectionName
== NULL
) {
1027 // No specified Section type, default is SECTION_ALL.
1029 SectType
= EFI_SECTION_ALL
;
1030 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPRESSION
]) == 0) {
1031 SectType
= EFI_SECTION_COMPRESSION
;
1032 if (CompressionName
== NULL
) {
1034 // Default is PI_STD compression algorithm.
1036 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1037 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_NOT_COMPRESSED
]) == 0) {
1038 SectCompSubType
= EFI_NOT_COMPRESSED
;
1039 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_STANDARD_COMPRESSION
]) == 0) {
1040 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1042 Error (NULL
, 0, 1003, "Invalid option value", "--compress = %s", CompressionName
);
1045 VerboseMsg ("Compress method is %s", mCompressionTypeName
[SectCompSubType
]);
1046 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_GUID_DEFINED
]) == 0) {
1047 SectType
= EFI_SECTION_GUID_DEFINED
;
1049 if (CompareGuid (&VendorGuid
, &mZeroGuid
) == 0) {
1050 memcpy (&VendorGuid
, &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
1053 if (SectGuidAttribute
== 0) {
1054 SectGuidAttribute
= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1056 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_NONE
) != 0) {
1058 // NONE attribute, clear attribute value.
1060 SectGuidAttribute
= 0;
1062 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1063 (unsigned) VendorGuid
.Data1
,
1066 VendorGuid
.Data4
[0],
1067 VendorGuid
.Data4
[1],
1068 VendorGuid
.Data4
[2],
1069 VendorGuid
.Data4
[3],
1070 VendorGuid
.Data4
[4],
1071 VendorGuid
.Data4
[5],
1072 VendorGuid
.Data4
[6],
1073 VendorGuid
.Data4
[7]);
1074 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
1075 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]);
1077 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
1078 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]);
1080 if (SectGuidHeaderLength
!= 0) {
1081 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength
);
1083 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PE32
]) == 0) {
1084 SectType
= EFI_SECTION_PE32
;
1085 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PIC
]) == 0) {
1086 SectType
= EFI_SECTION_PIC
;
1087 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_TE
]) == 0) {
1088 SectType
= EFI_SECTION_TE
;
1089 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_DXE_DEPEX
]) == 0) {
1090 SectType
= EFI_SECTION_DXE_DEPEX
;
1091 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_SMM_DEPEX
]) == 0) {
1092 SectType
= EFI_SECTION_SMM_DEPEX
;
1093 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_VERSION
]) == 0) {
1094 SectType
= EFI_SECTION_VERSION
;
1095 if (VersionNumber
< 0 || VersionNumber
> 9999) {
1096 Error (NULL
, 0, 1003, "Invalid option value", "%d is not in 0~9999", VersionNumber
);
1099 VerboseMsg ("Version section number is %d", VersionNumber
);
1100 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_USER_INTERFACE
]) == 0) {
1101 SectType
= EFI_SECTION_USER_INTERFACE
;
1102 if (StringBuffer
[0] == '\0') {
1103 Error (NULL
, 0, 1001, "Missing option", "user interface string");
1106 VerboseMsg ("UI section string name is %s", StringBuffer
);
1107 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPATIBILITY16
]) == 0) {
1108 SectType
= EFI_SECTION_COMPATIBILITY16
;
1109 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FIRMWARE_VOLUME_IMAGE
]) == 0) {
1110 SectType
= EFI_SECTION_FIRMWARE_VOLUME_IMAGE
;
1111 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FREEFORM_SUBTYPE_GUID
]) == 0) {
1112 SectType
= EFI_SECTION_FREEFORM_SUBTYPE_GUID
;
1113 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_RAW
]) == 0) {
1114 SectType
= EFI_SECTION_RAW
;
1115 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PEI_DEPEX
]) == 0) {
1116 SectType
= EFI_SECTION_PEI_DEPEX
;
1118 Error (NULL
, 0, 1003, "Invalid option value", "SectionType = %s", SectionName
);
1123 // GuidValue is only required by Guided section.
1125 if ((SectType
!= EFI_SECTION_GUID_DEFINED
) && (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1126 fprintf (stdout
, "Warning: the input guid value is not required for this section type %s\n", SectionName
);
1130 // Check whether there is input file
1132 if ((SectType
!= EFI_SECTION_VERSION
) && (SectType
!= EFI_SECTION_USER_INTERFACE
)) {
1134 // The input file are required for other section type.
1136 if (InputFileNum
== 0) {
1137 Error (NULL
, 0, 1001, "Missing options", "Input files");
1142 // Check whether there is output file
1144 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1145 VerboseMsg ("the %uth input file name is %s", (unsigned) Index
, InputFileName
[Index
]);
1147 if (OutputFileName
== NULL
) {
1148 Error (NULL
, 0, 1001, "Missing options", "Output file");
1150 // OutFile = stdout;
1152 VerboseMsg ("Output file name is %s", OutputFileName
);
1155 // At this point, we've fully validated the command line, and opened appropriate
1156 // files, so let's go and do what we've been asked to do...
1159 // Within this switch, build and write out the section header including any
1160 // section type specific pieces. If there's an input file, it's tacked on later
1163 case EFI_SECTION_COMPRESSION
:
1164 Status
= GenSectionCompressionSection (
1172 case EFI_SECTION_GUID_DEFINED
:
1173 Status
= GenSectionGuidDefinedSection (
1178 (UINT32
) SectGuidHeaderLength
,
1183 case EFI_SECTION_VERSION
:
1184 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1186 // 2 bytes for the build number UINT16
1190 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1192 Index
+= (strlen (StringBuffer
) * 2) + 2;
1193 OutFileBuffer
= (UINT8
*) malloc (Index
);
1194 if (OutFileBuffer
== NULL
) {
1195 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1198 VersionSect
= (EFI_VERSION_SECTION
*) OutFileBuffer
;
1199 VersionSect
->CommonHeader
.Type
= SectType
;
1200 VersionSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1201 VersionSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1202 VersionSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1203 VersionSect
->BuildNumber
= (UINT16
) VersionNumber
;
1204 Ascii2UnicodeString (StringBuffer
, VersionSect
->VersionString
);
1205 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1208 case EFI_SECTION_USER_INTERFACE
:
1209 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1211 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1213 Index
+= (strlen (StringBuffer
) * 2) + 2;
1214 OutFileBuffer
= (UINT8
*) malloc (Index
);
1215 if (OutFileBuffer
== NULL
) {
1216 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1219 UiSect
= (EFI_USER_INTERFACE_SECTION
*) OutFileBuffer
;
1220 UiSect
->CommonHeader
.Type
= SectType
;
1221 UiSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1222 UiSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1223 UiSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1224 Ascii2UnicodeString (StringBuffer
, UiSect
->FileNameString
);
1225 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1228 case EFI_SECTION_ALL
:
1230 // read all input file contents into a buffer
1231 // first get the size of all file contents
1233 Status
= GetSectionContents (
1240 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1241 OutFileBuffer
= (UINT8
*) malloc (InputLength
);
1242 if (OutFileBuffer
== NULL
) {
1243 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1247 // read all input file contents into a buffer
1249 Status
= GetSectionContents (
1256 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength
);
1260 // All other section types are caught by default (they're all the same)
1262 Status
= GenSectionCommonLeafSection (
1271 if (Status
!= EFI_SUCCESS
|| OutFileBuffer
== NULL
) {
1272 Error (NULL
, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status
);
1277 // Get output file length
1279 if (SectType
!= EFI_SECTION_ALL
) {
1280 InputLength
= SECTION_SIZE (OutFileBuffer
);
1284 // Write the output file
1286 OutFile
= fopen (OutputFileName
, "wb");
1287 if (OutFile
== NULL
) {
1288 Error (NULL
, 0, 0001, "Error opening file for writing", OutputFileName
);
1292 fwrite (OutFileBuffer
, InputLength
, 1, OutFile
);
1295 if (InputFileName
!= NULL
) {
1296 free (InputFileName
);
1299 if (OutFileBuffer
!= NULL
) {
1300 free (OutFileBuffer
);
1303 if (OutFile
!= NULL
) {
1307 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
1309 return GetUtilityStatus ();