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. if -s option is not given, \n\
164 EFI_SECTION_ALL is default section type.\n");
165 fprintf (stdout
, " -c [Type], --compress [Type]\n\
166 Compress method type can be PI_NONE or PI_STD.\n\
167 if -c option is not given, PI_STD is default type.\n");
168 fprintf (stdout
, " -g GuidValue, --vendor GuidValue\n\
169 GuidValue is one specific vendor guid value.\n\
170 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
171 fprintf (stdout
, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
172 GuidHeaderLength is the size of header of guided data\n");
173 fprintf (stdout
, " -r GuidAttr, --attributes GuidAttr\n\
174 GuidAttr is guid section atttributes, which may be\n\
175 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
176 if -r option is not given, default PROCESSING_REQUIRED\n");
177 fprintf (stdout
, " -n String, --name String\n\
178 String is a NULL terminated string used in Ui section.\n");
179 fprintf (stdout
, " -j Number, --buildnumber Number\n\
180 Number is an integer value between 0000 and 9999\n\
181 used in Ver section.\n");
182 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
183 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
184 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
185 fprintf (stdout
, " --version Show program's version number and exit.\n");
186 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
190 Ascii2UnicodeString (
198 Write ascii string as unicode string format to FILE
202 String - Pointer to string that is written to FILE.
203 UniString - Pointer to unicode string
211 while (*String
!= '\0') {
212 *(UniString
++) = (CHAR16
) *(String
++);
215 // End the UniString with a NULL.
221 GenSectionCommonLeafSection (
222 CHAR8
**InputFileName
,
225 UINT8
**OutFileBuffer
231 Generate a leaf section of type other than EFI_SECTION_VERSION
232 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
233 The function won't validate the input file's contents. For
234 common leaf sections, the input file may be a binary file.
235 The utility will add section header to the file.
239 InputFileName - Name of the input file.
241 InputFileNum - Number of input files. Should be 1 for leaf section.
243 SectionType - A valid section type string
245 OutFileBuffer - Buffer pointer to Output file contents
249 STATUS_ERROR - can't continue
250 STATUS_SUCCESS - successful return
254 UINT32 InputFileLength
;
258 EFI_COMMON_SECTION_HEADER
*CommonSect
;
261 if (InputFileNum
> 1) {
262 Error (NULL
, 0, 2000, "Invalid paramter", "more than one input file specified");
264 } else if (InputFileNum
< 1) {
265 Error (NULL
, 0, 2000, "Invalid paramter", "no input file specified");
269 // Open the input file
271 InFile
= fopen (InputFileName
[0], "rb");
272 if (InFile
== NULL
) {
273 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[0]);
277 Status
= STATUS_ERROR
;
280 // Seek to the end of the input file so we can determine its size
282 fseek (InFile
, 0, SEEK_END
);
283 InputFileLength
= ftell (InFile
);
284 fseek (InFile
, 0, SEEK_SET
);
285 DebugMsg (NULL
, 0, 9, "Input file", "File name is %s and File size is %d bytes", InputFileName
[0], InputFileLength
);
286 TotalLength
= sizeof (EFI_COMMON_SECTION_HEADER
) + InputFileLength
;
288 // Size must fit in 3 bytes
290 if (TotalLength
>= MAX_SECTION_SIZE
) {
291 Error (NULL
, 0, 2000, "Invalid paramter", "%s file size (0x%X) exceeds section size limit(%dM).", InputFileName
[0], TotalLength
, MAX_SECTION_SIZE
>>20);
294 VerboseMsg ("the size of the created section file is %d bytes", TotalLength
);
296 // Fill in the fields in the local section header structure
298 Buffer
= (UINT8
*) malloc ((size_t) TotalLength
);
299 if (Buffer
== NULL
) {
300 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
303 CommonSect
= (EFI_COMMON_SECTION_HEADER
*) Buffer
;
304 CommonSect
->Type
= SectionType
;
305 CommonSect
->Size
[0] = (UINT8
) (TotalLength
& 0xff);
306 CommonSect
->Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
307 CommonSect
->Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
310 // read data from the input file.
312 if (InputFileLength
!= 0) {
313 if (fread (Buffer
+ sizeof (EFI_COMMON_SECTION_HEADER
), (size_t) InputFileLength
, 1, InFile
) != 1) {
314 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[0]);
322 *OutFileBuffer
= Buffer
;
323 Status
= STATUS_SUCCESS
;
333 CHAR8
**InputFileName
,
342 Get the contents of all section files specified in InputFileName
347 InputFileName - Name of the input file.
349 InputFileNum - Number of input files. Should be at least 1.
351 FileBuffer - Output buffer to contain data
353 BufferLength - On input, this is size of the FileBuffer.
354 On output, this is the actual length of the data.
358 EFI_SUCCESS on successful return
359 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
360 EFI_ABORTED if unable to open input file.
361 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
369 if (InputFileNum
< 1) {
370 Error (NULL
, 0, 2000, "Invalid paramter", "must specify at least one input file");
371 return EFI_INVALID_PARAMETER
;
374 if (BufferLength
== NULL
) {
375 Error (NULL
, 0, 2000, "Invalid paramter", "BufferLength can't be NULL");
376 return EFI_INVALID_PARAMETER
;
381 // Go through our array of file names and copy their contents
382 // to the output buffer.
384 for (Index
= 0; Index
< InputFileNum
; Index
++) {
386 // make sure section ends on a DWORD boundary
388 while ((Size
& 0x03) != 0) {
389 if (FileBuffer
!= NULL
&& Size
< *BufferLength
) {
390 FileBuffer
[Size
] = 0;
396 // Open file and read contents
398 InFile
= fopen (InputFileName
[Index
], "rb");
399 if (InFile
== NULL
) {
400 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
404 fseek (InFile
, 0, SEEK_END
);
405 FileSize
= ftell (InFile
);
406 fseek (InFile
, 0, SEEK_SET
);
407 DebugMsg (NULL
, 0, 9, "Input files", "the input file name is %s and the size is %d bytes", InputFileName
[Index
], FileSize
);
409 // Now read the contents of the file into the buffer
410 // Buffer must be enough to contain the file content.
412 if (FileSize
> 0 && FileBuffer
!= NULL
&& (Size
+ FileSize
) <= *BufferLength
) {
413 if (fread (FileBuffer
+ Size
, (size_t) FileSize
, 1, InFile
) != 1) {
414 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[Index
]);
425 // Set the real required buffer size.
427 if (Size
> *BufferLength
) {
428 *BufferLength
= Size
;
429 return EFI_BUFFER_TOO_SMALL
;
431 *BufferLength
= Size
;
437 GenSectionCompressionSection (
438 CHAR8
**InputFileName
,
440 UINT8 SectCompSubType
,
441 UINT8
**OutFileBuffer
447 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
448 Input file must be already sectioned. The function won't validate
449 the input files' contents. Caller should hand in files already
454 InputFileName - Name of the input file.
456 InputFileNum - Number of input files. Should be at least 1.
458 SectCompSubType - Specify the compression algorithm requested.
460 OutFileBuffer - Buffer pointer to Output file contents
464 EFI_SUCCESS on successful return
465 EFI_INVALID_PARAMETER if InputFileNum is less than 1
466 EFI_ABORTED if unable to open input file.
467 EFI_OUT_OF_RESOURCES No resource to complete the operation.
472 UINT32 CompressedLength
;
476 EFI_COMPRESSION_SECTION
*CompressionSect
;
477 COMPRESS_FUNCTION CompressFunction
;
482 CompressedLength
= 0;
484 // read all input file contents into a buffer
485 // first get the size of all file contents
487 Status
= GetSectionContents (
494 if (Status
== EFI_BUFFER_TOO_SMALL
) {
495 FileBuffer
= (UINT8
*) malloc (InputLength
);
496 if (FileBuffer
== NULL
) {
497 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
498 return EFI_OUT_OF_RESOURCES
;
501 // read all input file contents into a buffer
503 Status
= GetSectionContents (
511 if (EFI_ERROR (Status
)) {
512 if (FileBuffer
!= NULL
) {
518 CompressFunction
= NULL
;
521 // Now data is in FileBuffer, compress the data
523 switch (SectCompSubType
) {
524 case EFI_NOT_COMPRESSED
:
525 CompressedLength
= InputLength
;
528 case EFI_STANDARD_COMPRESSION
:
529 CompressFunction
= (COMPRESS_FUNCTION
) EfiCompress
;
533 Error (NULL
, 0, 2000, "Invalid paramter", "unknown compression type");
538 if (CompressFunction
!= NULL
) {
540 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
, &CompressedLength
);
541 if (Status
== EFI_BUFFER_TOO_SMALL
) {
542 OutputBuffer
= malloc (CompressedLength
+ sizeof (EFI_COMPRESSION_SECTION
));
545 return EFI_OUT_OF_RESOURCES
;
548 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
+ sizeof (EFI_COMPRESSION_SECTION
), &CompressedLength
);
552 FileBuffer
= OutputBuffer
;
554 if (EFI_ERROR (Status
)) {
555 if (FileBuffer
!= NULL
) {
563 DebugMsg (NULL
, 0, 9, "comprss file size",
564 "the original section size is %d bytes and the compressed section size is %d bytes", InputLength
, CompressedLength
);
565 TotalLength
= CompressedLength
+ sizeof (EFI_COMPRESSION_SECTION
);
566 if (TotalLength
>= MAX_SECTION_SIZE
) {
567 Error (NULL
, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE
>>20);
568 if (FileBuffer
!= NULL
) {
571 if (OutputBuffer
!= NULL
) {
576 VerboseMsg ("the size of the created section file is %d bytes", TotalLength
);
579 // Add the section header for the compressed data
581 CompressionSect
= (EFI_COMPRESSION_SECTION
*) FileBuffer
;
583 CompressionSect
->CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
584 CompressionSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
585 CompressionSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
586 CompressionSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
587 CompressionSect
->CompressionType
= SectCompSubType
;
588 CompressionSect
->UncompressedLength
= InputLength
;
593 *OutFileBuffer
= FileBuffer
;
599 GenSectionGuidDefinedSection (
600 CHAR8
**InputFileName
,
602 EFI_GUID
*VendorGuid
,
603 UINT16 DataAttribute
,
604 UINT32 DataHeaderSize
,
605 UINT8
**OutFileBuffer
611 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
612 Input file must be already sectioned. The function won't validate
613 the input files' contents. Caller should hand in files already
618 InputFileName - Name of the input file.
620 InputFileNum - Number of input files. Should be at least 1.
622 VendorGuid - Specify vendor guid value.
624 DataAttribute - Specify attribute for the vendor guid data.
626 DataHeaderSize- Guided Data Header Size
628 OutFileBuffer - Buffer pointer to Output file contents
632 EFI_SUCCESS on successful return
633 EFI_INVALID_PARAMETER if InputFileNum is less than 1
634 EFI_ABORTED if unable to open input file.
635 EFI_OUT_OF_RESOURCES No resource to complete the operation.
643 UINT32 Crc32Checksum
;
645 CRC32_SECTION_HEADER
*Crc32GuidSect
;
646 EFI_GUID_DEFINED_SECTION
*VendorGuidSect
;
652 if (CompareGuid (VendorGuid
, &mEfiCrc32SectionGuid
) == 0) {
653 Offset
= sizeof (CRC32_SECTION_HEADER
);
655 Offset
= sizeof (EFI_GUID_DEFINED_SECTION
);
659 // read all input file contents into a buffer
660 // first get the size of all file contents
662 Status
= GetSectionContents (
669 if (Status
== EFI_BUFFER_TOO_SMALL
) {
670 FileBuffer
= (UINT8
*) malloc (InputLength
+ Offset
);
671 if (FileBuffer
== NULL
) {
672 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
673 return EFI_OUT_OF_RESOURCES
;
676 // read all input file contents into a buffer
678 Status
= GetSectionContents (
686 if (EFI_ERROR (Status
)) {
687 if (FileBuffer
!= NULL
) {
690 Error (NULL
, 0, 0001, "Error opening file for reading", InputFileName
[0]);
694 if (InputLength
== 0) {
695 Error (NULL
, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName
);
696 return EFI_NOT_FOUND
;
700 // Now data is in FileBuffer + Offset
702 if (CompareGuid (VendorGuid
, &mEfiCrc32SectionGuid
) == 0) {
704 // Default Guid section is CRC32.
707 CalculateCrc32 (FileBuffer
+ Offset
, InputLength
, &Crc32Checksum
);
709 TotalLength
= InputLength
+ sizeof (CRC32_SECTION_HEADER
);
710 if (TotalLength
>= MAX_SECTION_SIZE
) {
711 Error (NULL
, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE
>>20);
716 Crc32GuidSect
= (CRC32_SECTION_HEADER
*) FileBuffer
;
717 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
718 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
719 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
720 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
721 memcpy (&(Crc32GuidSect
->GuidSectionHeader
.SectionDefinitionGuid
), &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
722 Crc32GuidSect
->GuidSectionHeader
.Attributes
= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
723 Crc32GuidSect
->GuidSectionHeader
.DataOffset
= sizeof (CRC32_SECTION_HEADER
);
724 Crc32GuidSect
->CRC32Checksum
= Crc32Checksum
;
725 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %d", Crc32GuidSect
->GuidSectionHeader
.DataOffset
);
728 TotalLength
= InputLength
+ sizeof (EFI_GUID_DEFINED_SECTION
);
729 if (TotalLength
>= MAX_SECTION_SIZE
) {
730 Error (NULL
, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE
>>20);
735 VendorGuidSect
= (EFI_GUID_DEFINED_SECTION
*) FileBuffer
;
736 VendorGuidSect
->CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
737 VendorGuidSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
738 VendorGuidSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
739 VendorGuidSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
740 memcpy (&(VendorGuidSect
->SectionDefinitionGuid
), VendorGuid
, sizeof (EFI_GUID
));
741 VendorGuidSect
->Attributes
= DataAttribute
;
742 VendorGuidSect
->DataOffset
= sizeof (EFI_GUID_DEFINED_SECTION
) + DataHeaderSize
;
743 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %d", VendorGuidSect
->DataOffset
);
745 VerboseMsg ("the size of the created section file is %d bytes", TotalLength
);
750 *OutFileBuffer
= FileBuffer
;
768 command line parameters
772 EFI_SUCCESS Section header successfully generated and section concatenated.
773 EFI_ABORTED Could not generate the section
774 EFI_OUT_OF_RESOURCES No resource to complete the operation.
782 CHAR8
**InputFileName
;
783 CHAR8
*OutputFileName
;
785 CHAR8
*CompressionName
;
787 EFI_GUID VendorGuid
= mZeroGuid
;
790 UINT8 SectCompSubType
;
791 UINT16 SectGuidAttribute
;
792 UINT64 SectGuidHeaderLength
;
793 EFI_VERSION_SECTION
*VersionSect
;
794 EFI_USER_INTERFACE_SECTION
*UiSect
;
796 UINT8
*OutFileBuffer
;
800 InputFileName
= NULL
;
801 OutputFileName
= NULL
;
803 CompressionName
= NULL
;
809 SectType
= EFI_SECTION_ALL
;
811 SectGuidAttribute
= 0;
812 OutFileBuffer
= NULL
;
814 Status
= STATUS_SUCCESS
;
816 SectGuidHeaderLength
= 0;
820 SetUtilityName (UTILITY_NAME
);
823 Error (NULL
, 0, 1001, "Missing options", "No options input");
829 // Parse command line
834 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
837 return STATUS_SUCCESS
;
840 if (stricmp (argv
[0], "--version") == 0) {
842 return STATUS_SUCCESS
;
846 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--SectionType") == 0)) {
847 SectionName
= argv
[1];
848 if (SectionName
== NULL
) {
849 Error (NULL
, 0, 1003, "Invalid option value", "Section Type can't be NULL");
857 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
858 OutputFileName
= argv
[1];
859 if (OutputFileName
== NULL
) {
860 Error (NULL
, 0, 1003, "Invalid option value", "Output file can't be NULL");
868 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--compress") == 0)) {
869 CompressionName
= argv
[1];
870 if (CompressionName
== NULL
) {
871 Error (NULL
, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
879 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--vendor") == 0)) {
880 Status
= StringToGuid (argv
[1], &VendorGuid
);
881 if (EFI_ERROR (Status
)) {
882 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
890 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--attributes") == 0)) {
891 if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]) == 0) {
892 SectGuidAttribute
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
893 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]) == 0) {
894 SectGuidAttribute
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
895 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[0]) == 0) {
899 SectGuidAttribute
|= EFI_GUIDED_SECTION_NONE
;
901 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
909 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--HeaderLength") == 0)) {
910 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &SectGuidHeaderLength
);
911 if (EFI_ERROR (Status
)) {
912 Error (NULL
, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv
[0], argv
[1]);
920 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--name") == 0)) {
921 StringBuffer
= argv
[1];
922 if (StringBuffer
== NULL
) {
923 Error (NULL
, 0, 1003, "Invalid option value", "Name can't be NULL");
931 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--buildnumber") == 0)) {
932 if (argv
[1] == NULL
) {
933 Error (NULL
, 0, 1003, "Invalid option value", "build number can't be NULL");
937 // Verify string is a integrator number
939 for (Index
= 0; Index
< strlen (argv
[1]); Index
++) {
940 if ((argv
[1][Index
] != '-') && (isdigit (argv
[1][Index
]) == 0)) {
941 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
946 sscanf (argv
[1], "%d", &VersionNumber
);
952 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
953 SetPrintLevel (VERBOSE_LOG_LEVEL
);
954 VerboseMsg ("Verbose output Mode Set!");
960 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
961 SetPrintLevel (KEY_LOG_LEVEL
);
962 KeyMsg ("Quiet output Mode Set!");
968 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
969 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
970 if (EFI_ERROR (Status
)) {
971 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
975 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", LogLevel
);
978 SetPrintLevel (LogLevel
);
979 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
986 // Get Input file name
988 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
989 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
990 if (InputFileName
== NULL
) {
991 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
995 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
996 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
998 // InputFileName buffer too small, need to realloc
1000 InputFileName
= (CHAR8
**) realloc (
1002 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1005 if (InputFileName
== NULL
) {
1006 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1010 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1013 InputFileName
[InputFileNum
++] = argv
[0];
1018 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1021 // Parse all command line parameters to get the corresponding section type.
1023 VerboseMsg ("Section type is %s", SectionName
);
1024 if (SectionName
== NULL
) {
1026 // No specified Section type, default is SECTION_ALL.
1028 SectType
= EFI_SECTION_ALL
;
1029 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPRESSION
]) == 0) {
1030 SectType
= EFI_SECTION_COMPRESSION
;
1031 if (CompressionName
== NULL
) {
1033 // Default is PI_STD compression algorithm.
1035 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1036 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_NOT_COMPRESSED
]) == 0) {
1037 SectCompSubType
= EFI_NOT_COMPRESSED
;
1038 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_STANDARD_COMPRESSION
]) == 0) {
1039 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1041 Error (NULL
, 0, 1003, "Invalid option value", "--compress = %s", CompressionName
);
1044 VerboseMsg ("Compress method is %s", mCompressionTypeName
[SectCompSubType
]);
1045 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_GUID_DEFINED
]) == 0) {
1046 SectType
= EFI_SECTION_GUID_DEFINED
;
1048 if (CompareGuid (&VendorGuid
, &mZeroGuid
) == 0) {
1049 memcpy (&VendorGuid
, &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
1052 if (SectGuidAttribute
== 0) {
1053 SectGuidAttribute
= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1055 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_NONE
) != 0) {
1057 // NONE attribute, clear attribute value.
1059 SectGuidAttribute
= 0;
1061 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1065 VendorGuid
.Data4
[0],
1066 VendorGuid
.Data4
[1],
1067 VendorGuid
.Data4
[2],
1068 VendorGuid
.Data4
[3],
1069 VendorGuid
.Data4
[4],
1070 VendorGuid
.Data4
[5],
1071 VendorGuid
.Data4
[6],
1072 VendorGuid
.Data4
[7]);
1073 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
1074 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]);
1076 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
1077 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]);
1079 if (SectGuidHeaderLength
!= 0) {
1080 VerboseMsg ("Guid Data Header size is 0x%x", SectGuidHeaderLength
);
1082 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PE32
]) == 0) {
1083 SectType
= EFI_SECTION_PE32
;
1084 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PIC
]) == 0) {
1085 SectType
= EFI_SECTION_PIC
;
1086 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_TE
]) == 0) {
1087 SectType
= EFI_SECTION_TE
;
1088 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_DXE_DEPEX
]) == 0) {
1089 SectType
= EFI_SECTION_DXE_DEPEX
;
1090 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_VERSION
]) == 0) {
1091 SectType
= EFI_SECTION_VERSION
;
1092 if (VersionNumber
< 0 || VersionNumber
> 9999) {
1093 Error (NULL
, 0, 1003, "Invalid option value", "%d is not in 0~9999", VersionNumber
);
1096 VerboseMsg ("Version section number is %d", VersionNumber
);
1097 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_USER_INTERFACE
]) == 0) {
1098 SectType
= EFI_SECTION_USER_INTERFACE
;
1099 if (StringBuffer
[0] == '\0') {
1100 Error (NULL
, 0, 1001, "Missing option", "user interface string");
1103 VerboseMsg ("UI section string name is %s", StringBuffer
);
1104 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPATIBILITY16
]) == 0) {
1105 SectType
= EFI_SECTION_COMPATIBILITY16
;
1106 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FIRMWARE_VOLUME_IMAGE
]) == 0) {
1107 SectType
= EFI_SECTION_FIRMWARE_VOLUME_IMAGE
;
1108 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FREEFORM_SUBTYPE_GUID
]) == 0) {
1109 SectType
= EFI_SECTION_FREEFORM_SUBTYPE_GUID
;
1110 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_RAW
]) == 0) {
1111 SectType
= EFI_SECTION_RAW
;
1112 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PEI_DEPEX
]) == 0) {
1113 SectType
= EFI_SECTION_PEI_DEPEX
;
1115 Error (NULL
, 0, 1003, "Invalid option value", "SectionType = %s", SectionName
);
1120 // GuidValue is only required by Guided section.
1122 if ((SectType
!= EFI_SECTION_GUID_DEFINED
) && (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1123 fprintf (stdout
, "Warning: the input guid value is not required for this section type %s\n", SectionName
);
1127 // Check whether there is input file
1129 if ((SectType
!= EFI_SECTION_VERSION
) && (SectType
!= EFI_SECTION_USER_INTERFACE
)) {
1131 // The input file are required for other section type.
1133 if (InputFileNum
== 0) {
1134 Error (NULL
, 0, 1001, "Missing options", "Input files");
1139 // Check whether there is output file
1141 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1142 VerboseMsg ("the %dth input file name is %s", Index
, InputFileName
[Index
]);
1144 if (OutputFileName
== NULL
) {
1145 Error (NULL
, 0, 1001, "Missing options", "Output file");
1147 // OutFile = stdout;
1149 VerboseMsg ("Output file name is %s", OutputFileName
);
1152 // At this point, we've fully validated the command line, and opened appropriate
1153 // files, so let's go and do what we've been asked to do...
1156 // Within this switch, build and write out the section header including any
1157 // section type specific pieces. If there's an input file, it's tacked on later
1160 case EFI_SECTION_COMPRESSION
:
1161 Status
= GenSectionCompressionSection (
1169 case EFI_SECTION_GUID_DEFINED
:
1170 Status
= GenSectionGuidDefinedSection (
1175 (UINT32
) SectGuidHeaderLength
,
1180 case EFI_SECTION_VERSION
:
1181 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1183 // 2 bytes for the build number UINT16
1187 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1189 Index
+= (strlen (StringBuffer
) * 2) + 2;
1190 OutFileBuffer
= (UINT8
*) malloc (Index
);
1191 if (OutFileBuffer
== NULL
) {
1192 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1195 VersionSect
= (EFI_VERSION_SECTION
*) OutFileBuffer
;
1196 VersionSect
->CommonHeader
.Type
= SectType
;
1197 VersionSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1198 VersionSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1199 VersionSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1200 VersionSect
->BuildNumber
= (UINT16
) VersionNumber
;
1201 Ascii2UnicodeString (StringBuffer
, VersionSect
->VersionString
);
1202 VerboseMsg ("the size of the created section file is %d bytes", Index
);
1205 case EFI_SECTION_USER_INTERFACE
:
1206 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1208 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1210 Index
+= (strlen (StringBuffer
) * 2) + 2;
1211 OutFileBuffer
= (UINT8
*) malloc (Index
);
1212 if (OutFileBuffer
== NULL
) {
1213 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1216 UiSect
= (EFI_USER_INTERFACE_SECTION
*) OutFileBuffer
;
1217 UiSect
->CommonHeader
.Type
= SectType
;
1218 UiSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1219 UiSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1220 UiSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1221 Ascii2UnicodeString (StringBuffer
, UiSect
->FileNameString
);
1222 VerboseMsg ("the size of the created section file is %d bytes", Index
);
1225 case EFI_SECTION_ALL
:
1227 // read all input file contents into a buffer
1228 // first get the size of all file contents
1230 Status
= GetSectionContents (
1237 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1238 OutFileBuffer
= (UINT8
*) malloc (InputLength
);
1239 if (OutFileBuffer
== NULL
) {
1240 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1244 // read all input file contents into a buffer
1246 Status
= GetSectionContents (
1253 VerboseMsg ("the size of the created section file is %d bytes", InputLength
);
1257 // All other section types are caught by default (they're all the same)
1259 Status
= GenSectionCommonLeafSection (
1268 if (Status
!= EFI_SUCCESS
|| OutFileBuffer
== NULL
) {
1269 Error (NULL
, 0, 2000, "Status is not successful", "Status value is 0x%X", (UINTN
) Status
);
1274 // Get output file length
1276 if (SectType
!= EFI_SECTION_ALL
) {
1277 InputLength
= SECTION_SIZE (OutFileBuffer
);
1281 // Write the output file
1283 OutFile
= fopen (OutputFileName
, "wb");
1284 if (OutFile
== NULL
) {
1285 Error (NULL
, 0, 0001, "Error opening file for writing", OutputFileName
);
1289 fwrite (OutFileBuffer
, InputLength
, 1, OutFile
);
1292 if (InputFileName
!= NULL
) {
1293 free (InputFileName
);
1296 if (OutFileBuffer
!= NULL
) {
1297 free (OutFileBuffer
);
1300 if (OutFile
!= NULL
) {
1304 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
1306 return GetUtilityStatus ();