3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
4 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>
30 #include <IndustryStandard/PeImage.h>
32 #include "CommonLib.h"
35 #include "EfiUtilityMsgs.h"
39 // GenSec Tool Information
41 #define UTILITY_NAME "GenSec"
42 #define UTILITY_MAJOR_VERSION 0
43 #define UTILITY_MINOR_VERSION 1
45 STATIC CHAR8
*mSectionTypeName
[] = {
46 NULL
, // 0x00 - reserved
47 "EFI_SECTION_COMPRESSION", // 0x01
48 "EFI_SECTION_GUID_DEFINED", // 0x02
49 NULL
, // 0x03 - reserved
50 NULL
, // 0x04 - reserved
51 NULL
, // 0x05 - reserved
52 NULL
, // 0x06 - reserved
53 NULL
, // 0x07 - reserved
54 NULL
, // 0x08 - reserved
55 NULL
, // 0x09 - reserved
56 NULL
, // 0x0A - reserved
57 NULL
, // 0x0B - reserved
58 NULL
, // 0x0C - reserved
59 NULL
, // 0x0D - reserved
60 NULL
, // 0x0E - reserved
61 NULL
, // 0x0F - reserved
62 "EFI_SECTION_PE32", // 0x10
63 "EFI_SECTION_PIC", // 0x11
64 "EFI_SECTION_TE", // 0x12
65 "EFI_SECTION_DXE_DEPEX", // 0x13
66 "EFI_SECTION_VERSION", // 0x14
67 "EFI_SECTION_USER_INTERFACE", // 0x15
68 "EFI_SECTION_COMPATIBILITY16", // 0x16
69 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17
70 "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18
71 "EFI_SECTION_RAW", // 0x19
73 "EFI_SECTION_PEI_DEPEX", // 0x1B
74 "EFI_SECTION_SMM_DEPEX" // 0x1C
77 STATIC CHAR8
*mCompressionTypeName
[] = { "PI_NONE", "PI_STD" };
79 #define EFI_GUIDED_SECTION_NONE 0x80
80 STATIC CHAR8
*mGUIDedSectionAttribue
[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};
82 STATIC CHAR8
*mAlignName
[] = {
83 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
84 "1K", "2K", "4K", "8K", "16K", "32K", "64K"
88 // Crc32 GUID section related definitions.
91 EFI_GUID_DEFINED_SECTION GuidSectionHeader
;
93 } CRC32_SECTION_HEADER
;
96 EFI_GUID_DEFINED_SECTION2 GuidSectionHeader
;
98 } CRC32_SECTION_HEADER2
;
100 STATIC EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
101 STATIC EFI_GUID mEfiCrc32SectionGuid
= EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID
;
112 Print out version information for this utility.
124 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
151 fprintf (stdout
, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME
);
154 // Copyright declaration
156 fprintf (stdout
, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");
161 fprintf (stdout
, "Options:\n");
162 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
163 File is the SectionFile to be created.\n");
164 fprintf (stdout
, " -s [SectionType], --sectiontype [SectionType]\n\
165 SectionType defined in PI spec is one type of\n\
166 EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\
167 EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\
168 EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\
169 EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\
170 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\
171 EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\
172 EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\
173 if -s option is not given, \n\
174 EFI_SECTION_ALL is default section type.\n");
175 fprintf (stdout
, " -c [Type], --compress [Type]\n\
176 Compress method type can be PI_NONE or PI_STD.\n\
177 if -c option is not given, PI_STD is default type.\n");
178 fprintf (stdout
, " -g GuidValue, --vendor GuidValue\n\
179 GuidValue is one specific vendor guid value.\n\
180 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
181 fprintf (stdout
, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
182 GuidHeaderLength is the size of header of guided data\n");
183 fprintf (stdout
, " -r GuidAttr, --attributes GuidAttr\n\
184 GuidAttr is guid section atttributes, which may be\n\
185 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
186 if -r option is not given, default PROCESSING_REQUIRED\n");
187 fprintf (stdout
, " -n String, --name String\n\
188 String is a NULL terminated string used in Ui section.\n");
189 fprintf (stdout
, " -j Number, --buildnumber Number\n\
190 Number is an integer value between 0 and 65535\n\
191 used in Ver section.\n");
192 fprintf (stdout
, " --sectionalign SectionAlign\n\
193 SectionAlign points to section alignment, which support\n\
194 the alignment scope 1~64K. It is specified in same\n\
195 order that the section file is input.\n");
196 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
197 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
198 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
199 fprintf (stdout
, " --version Show program's version number and exit.\n");
200 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
204 Ascii2UnicodeString (
212 Write ascii string as unicode string format to FILE
216 String - Pointer to string that is written to FILE.
217 UniString - Pointer to unicode string
225 while (*String
!= '\0') {
226 *(UniString
++) = (CHAR16
) *(String
++);
229 // End the UniString with a NULL.
235 GenSectionCommonLeafSection (
236 CHAR8
**InputFileName
,
239 UINT8
**OutFileBuffer
245 Generate a leaf section of type other than EFI_SECTION_VERSION
246 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
247 The function won't validate the input file's contents. For
248 common leaf sections, the input file may be a binary file.
249 The utility will add section header to the file.
253 InputFileName - Name of the input file.
255 InputFileNum - Number of input files. Should be 1 for leaf section.
257 SectionType - A valid section type string
259 OutFileBuffer - Buffer pointer to Output file contents
263 STATUS_ERROR - can't continue
264 STATUS_SUCCESS - successful return
268 UINT32 InputFileLength
;
273 EFI_COMMON_SECTION_HEADER
*CommonSect
;
276 if (InputFileNum
> 1) {
277 Error (NULL
, 0, 2000, "Invalid paramter", "more than one input file specified");
279 } else if (InputFileNum
< 1) {
280 Error (NULL
, 0, 2000, "Invalid paramter", "no input file specified");
284 // Open the input file
286 InFile
= fopen (LongFilePath (InputFileName
[0]), "rb");
287 if (InFile
== NULL
) {
288 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[0]);
292 Status
= STATUS_ERROR
;
295 // Seek to the end of the input file so we can determine its size
297 fseek (InFile
, 0, SEEK_END
);
298 InputFileLength
= ftell (InFile
);
299 fseek (InFile
, 0, SEEK_SET
);
300 DebugMsg (NULL
, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName
[0], (unsigned) InputFileLength
);
301 TotalLength
= sizeof (EFI_COMMON_SECTION_HEADER
) + InputFileLength
;
303 // Size must fit in 3 bytes
305 //if (TotalLength >= MAX_SECTION_SIZE) {
306 // Error (NULL, 0, 2000, "Invalid paramter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20);
309 HeaderLength
= sizeof (EFI_COMMON_SECTION_HEADER
);
310 if (TotalLength
>= MAX_SECTION_SIZE
) {
311 TotalLength
= sizeof (EFI_COMMON_SECTION_HEADER2
) + InputFileLength
;
312 HeaderLength
= sizeof (EFI_COMMON_SECTION_HEADER2
);
314 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
316 // Fill in the fields in the local section header structure
318 Buffer
= (UINT8
*) malloc ((size_t) TotalLength
);
319 if (Buffer
== NULL
) {
320 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
323 CommonSect
= (EFI_COMMON_SECTION_HEADER
*) Buffer
;
324 CommonSect
->Type
= SectionType
;
325 if (TotalLength
< MAX_SECTION_SIZE
) {
326 CommonSect
->Size
[0] = (UINT8
) (TotalLength
& 0xff);
327 CommonSect
->Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
328 CommonSect
->Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
330 memset(CommonSect
->Size
, 0xff, sizeof(UINT8
) * 3);
331 ((EFI_COMMON_SECTION_HEADER2
*)CommonSect
)->ExtendedSize
= TotalLength
;
335 // read data from the input file.
337 if (InputFileLength
!= 0) {
338 if (fread (Buffer
+ HeaderLength
, (size_t) InputFileLength
, 1, InFile
) != 1) {
339 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[0]);
347 *OutFileBuffer
= Buffer
;
348 Status
= STATUS_SUCCESS
;
359 IN CHAR8
*AlignBuffer
,
360 OUT UINT32
*AlignNumber
366 Converts Align String to align value (1~64K).
370 AlignBuffer - Pointer to Align string.
371 AlignNumber - Pointer to Align value.
375 EFI_SUCCESS Successfully convert align string to align value.
376 EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.
384 if (AlignBuffer
== NULL
) {
385 return EFI_INVALID_PARAMETER
;
387 for (Index
= 0; Index
< sizeof (mAlignName
) / sizeof (CHAR8
*); Index
++) {
388 if (stricmp (AlignBuffer
, mAlignName
[Index
]) == 0) {
389 *AlignNumber
= 1 << Index
;
393 return EFI_INVALID_PARAMETER
;
398 CHAR8
**InputFileName
,
399 UINT32
*InputFileAlign
,
408 Get the contents of all section files specified in InputFileName
413 InputFileName - Name of the input file.
415 InputFileAlign - Alignment required by the input file data.
417 InputFileNum - Number of input files. Should be at least 1.
419 FileBuffer - Output buffer to contain data
421 BufferLength - On input, this is size of the FileBuffer.
422 On output, this is the actual length of the data.
426 EFI_SUCCESS on successful return
427 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
428 EFI_ABORTED if unable to open input file.
429 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
437 EFI_COMMON_SECTION_HEADER
*SectHeader
;
438 EFI_COMMON_SECTION_HEADER2 TempSectHeader
;
439 EFI_TE_IMAGE_HEADER TeHeader
;
441 EFI_GUID_DEFINED_SECTION GuidSectHeader
;
442 EFI_GUID_DEFINED_SECTION2 GuidSectHeader2
;
445 if (InputFileNum
< 1) {
446 Error (NULL
, 0, 2000, "Invalid paramter", "must specify at least one input file");
447 return EFI_INVALID_PARAMETER
;
450 if (BufferLength
== NULL
) {
451 Error (NULL
, 0, 2000, "Invalid paramter", "BufferLength can't be NULL");
452 return EFI_INVALID_PARAMETER
;
459 // Go through our array of file names and copy their contents
460 // to the output buffer.
462 for (Index
= 0; Index
< InputFileNum
; Index
++) {
464 // make sure section ends on a DWORD boundary
466 while ((Size
& 0x03) != 0) {
467 if (FileBuffer
!= NULL
&& Size
< *BufferLength
) {
468 FileBuffer
[Size
] = 0;
474 // Open file and read contents
476 InFile
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
477 if (InFile
== NULL
) {
478 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
482 fseek (InFile
, 0, SEEK_END
);
483 FileSize
= ftell (InFile
);
484 fseek (InFile
, 0, SEEK_SET
);
485 DebugMsg (NULL
, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName
[Index
], (unsigned) FileSize
);
487 // Adjust section buffer when section alignment is required.
489 if (InputFileAlign
!= NULL
) {
491 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
495 // The section might be EFI_COMMON_SECTION_HEADER2
496 // But only Type needs to be checked
498 if (FileSize
>= MAX_SECTION_SIZE
) {
499 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER2
);
501 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER
);
503 fread (&TempSectHeader
, 1, HeaderSize
, InFile
);
504 if (TempSectHeader
.Type
== EFI_SECTION_TE
) {
505 fread (&TeHeader
, 1, sizeof (TeHeader
), InFile
);
506 if (TeHeader
.Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
507 TeOffset
= TeHeader
.StrippedSize
- sizeof (TeHeader
);
509 } else if (TempSectHeader
.Type
== EFI_SECTION_GUID_DEFINED
) {
510 fseek (InFile
, 0, SEEK_SET
);
511 if (FileSize
>= MAX_SECTION_SIZE
) {
512 fread (&GuidSectHeader2
, 1, sizeof (GuidSectHeader2
), InFile
);
513 if ((GuidSectHeader2
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
514 HeaderSize
= GuidSectHeader2
.DataOffset
;
517 fread (&GuidSectHeader
, 1, sizeof (GuidSectHeader
), InFile
);
518 if ((GuidSectHeader
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
519 HeaderSize
= GuidSectHeader
.DataOffset
;
524 fseek (InFile
, 0, SEEK_SET
);
527 // Revert TeOffset to the converse value relative to Alignment
528 // This is to assure the original PeImage Header at Alignment.
531 TeOffset
= InputFileAlign
[Index
] - (TeOffset
% InputFileAlign
[Index
]);
532 TeOffset
= TeOffset
% InputFileAlign
[Index
];
536 // make sure section data meet its alignment requirement by adding one raw pad section.
538 if ((InputFileAlign
[Index
] != 0) && (((Size
+ HeaderSize
+ TeOffset
) % InputFileAlign
[Index
]) != 0)) {
539 Offset
= (Size
+ sizeof (EFI_COMMON_SECTION_HEADER
) + HeaderSize
+ TeOffset
+ InputFileAlign
[Index
] - 1) & ~(InputFileAlign
[Index
] - 1);
540 Offset
= Offset
- Size
- HeaderSize
- TeOffset
;
542 if (FileBuffer
!= NULL
&& ((Size
+ Offset
) < *BufferLength
)) {
544 // The maximal alignment is 64K, the raw section size must be less than 0xffffff
546 memset (FileBuffer
+ Size
, 0, Offset
);
547 SectHeader
= (EFI_COMMON_SECTION_HEADER
*) (FileBuffer
+ Size
);
548 SectHeader
->Type
= EFI_SECTION_RAW
;
549 SectHeader
->Size
[0] = (UINT8
) (Offset
& 0xff);
550 SectHeader
->Size
[1] = (UINT8
) ((Offset
& 0xff00) >> 8);
551 SectHeader
->Size
[2] = (UINT8
) ((Offset
& 0xff0000) >> 16);
553 DebugMsg (NULL
, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset
);
555 Size
= Size
+ Offset
;
560 // Now read the contents of the file into the buffer
561 // Buffer must be enough to contain the file content.
563 if ((FileSize
> 0) && (FileBuffer
!= NULL
) && ((Size
+ FileSize
) <= *BufferLength
)) {
564 if (fread (FileBuffer
+ Size
, (size_t) FileSize
, 1, InFile
) != 1) {
565 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[Index
]);
576 // Set the real required buffer size.
578 if (Size
> *BufferLength
) {
579 *BufferLength
= Size
;
580 return EFI_BUFFER_TOO_SMALL
;
582 *BufferLength
= Size
;
588 GenSectionCompressionSection (
589 CHAR8
**InputFileName
,
590 UINT32
*InputFileAlign
,
592 UINT8 SectCompSubType
,
593 UINT8
**OutFileBuffer
599 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
600 Input file must be already sectioned. The function won't validate
601 the input files' contents. Caller should hand in files already
606 InputFileName - Name of the input file.
608 InputFileAlign - Alignment required by the input file data.
610 InputFileNum - Number of input files. Should be at least 1.
612 SectCompSubType - Specify the compression algorithm requested.
614 OutFileBuffer - Buffer pointer to Output file contents
618 EFI_SUCCESS on successful return
619 EFI_INVALID_PARAMETER if InputFileNum is less than 1
620 EFI_ABORTED if unable to open input file.
621 EFI_OUT_OF_RESOURCES No resource to complete the operation.
626 UINT32 CompressedLength
;
631 EFI_COMPRESSION_SECTION
*CompressionSect
;
632 EFI_COMPRESSION_SECTION2
*CompressionSect2
;
633 COMPRESS_FUNCTION CompressFunction
;
638 CompressedLength
= 0;
641 // read all input file contents into a buffer
642 // first get the size of all file contents
644 Status
= GetSectionContents (
652 if (Status
== EFI_BUFFER_TOO_SMALL
) {
653 FileBuffer
= (UINT8
*) malloc (InputLength
);
654 if (FileBuffer
== NULL
) {
655 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
656 return EFI_OUT_OF_RESOURCES
;
659 // read all input file contents into a buffer
661 Status
= GetSectionContents (
670 if (EFI_ERROR (Status
)) {
671 if (FileBuffer
!= NULL
) {
677 CompressFunction
= NULL
;
680 // Now data is in FileBuffer, compress the data
682 switch (SectCompSubType
) {
683 case EFI_NOT_COMPRESSED
:
684 CompressedLength
= InputLength
;
685 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION
);
686 if (CompressedLength
+ HeaderLength
>= MAX_SECTION_SIZE
) {
687 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION2
);
689 TotalLength
= CompressedLength
+ HeaderLength
;
691 // Copy file buffer to the none compressed data.
693 OutputBuffer
= malloc (TotalLength
);
694 if (OutputBuffer
== NULL
) {
696 return EFI_OUT_OF_RESOURCES
;
698 memcpy (OutputBuffer
+ HeaderLength
, FileBuffer
, CompressedLength
);
700 FileBuffer
= OutputBuffer
;
703 case EFI_STANDARD_COMPRESSION
:
704 CompressFunction
= (COMPRESS_FUNCTION
) EfiCompress
;
708 Error (NULL
, 0, 2000, "Invalid paramter", "unknown compression type");
713 if (CompressFunction
!= NULL
) {
715 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
, &CompressedLength
);
716 if (Status
== EFI_BUFFER_TOO_SMALL
) {
717 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION
);
718 if (CompressedLength
+ HeaderLength
>= MAX_SECTION_SIZE
) {
719 HeaderLength
= sizeof (EFI_COMPRESSION_SECTION2
);
721 TotalLength
= CompressedLength
+ HeaderLength
;
722 OutputBuffer
= malloc (TotalLength
);
725 return EFI_OUT_OF_RESOURCES
;
728 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
+ HeaderLength
, &CompressedLength
);
732 FileBuffer
= OutputBuffer
;
734 if (EFI_ERROR (Status
)) {
735 if (FileBuffer
!= NULL
) {
743 DebugMsg (NULL
, 0, 9, "comprss file size",
744 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength
, (unsigned) CompressedLength
);
746 //if (TotalLength >= MAX_SECTION_SIZE) {
747 // Error (NULL, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);
748 // if (FileBuffer != NULL) {
749 // free (FileBuffer);
751 // if (OutputBuffer != NULL) {
752 // free (OutputBuffer);
754 // return STATUS_ERROR;
756 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
759 // Add the section header for the compressed data
761 if (TotalLength
>= MAX_SECTION_SIZE
) {
762 CompressionSect2
= (EFI_COMPRESSION_SECTION2
*)FileBuffer
;
764 memset(CompressionSect2
->CommonHeader
.Size
, 0xff, sizeof(UINT8
) * 3);
765 CompressionSect2
->CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
766 CompressionSect2
->CommonHeader
.ExtendedSize
= TotalLength
;
767 CompressionSect2
->CompressionType
= SectCompSubType
;
768 CompressionSect2
->UncompressedLength
= InputLength
;
770 CompressionSect
= (EFI_COMPRESSION_SECTION
*) FileBuffer
;
772 CompressionSect
->CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
773 CompressionSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
774 CompressionSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
775 CompressionSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
776 CompressionSect
->CompressionType
= SectCompSubType
;
777 CompressionSect
->UncompressedLength
= InputLength
;
783 *OutFileBuffer
= FileBuffer
;
789 GenSectionGuidDefinedSection (
790 CHAR8
**InputFileName
,
791 UINT32
*InputFileAlign
,
793 EFI_GUID
*VendorGuid
,
794 UINT16 DataAttribute
,
795 UINT32 DataHeaderSize
,
796 UINT8
**OutFileBuffer
802 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
803 Input file must be already sectioned. The function won't validate
804 the input files' contents. Caller should hand in files already
809 InputFileName - Name of the input file.
811 InputFileAlign - Alignment required by the input file data.
813 InputFileNum - Number of input files. Should be at least 1.
815 VendorGuid - Specify vendor guid value.
817 DataAttribute - Specify attribute for the vendor guid data.
819 DataHeaderSize- Guided Data Header Size
821 OutFileBuffer - Buffer pointer to Output file contents
825 EFI_SUCCESS on successful return
826 EFI_INVALID_PARAMETER if InputFileNum is less than 1
827 EFI_ABORTED if unable to open input file.
828 EFI_OUT_OF_RESOURCES No resource to complete the operation.
836 UINT32 Crc32Checksum
;
838 CRC32_SECTION_HEADER
*Crc32GuidSect
;
839 CRC32_SECTION_HEADER2
*Crc32GuidSect2
;
840 EFI_GUID_DEFINED_SECTION
*VendorGuidSect
;
841 EFI_GUID_DEFINED_SECTION2
*VendorGuidSect2
;
849 // read all input file contents into a buffer
850 // first get the size of all file contents
852 Status
= GetSectionContents (
860 if (Status
== EFI_BUFFER_TOO_SMALL
) {
861 if (CompareGuid (VendorGuid
, &mZeroGuid
) == 0) {
862 Offset
= sizeof (CRC32_SECTION_HEADER
);
863 if (InputLength
+ Offset
>= MAX_SECTION_SIZE
) {
864 Offset
= sizeof (CRC32_SECTION_HEADER2
);
867 Offset
= sizeof (EFI_GUID_DEFINED_SECTION
);
868 if (InputLength
+ Offset
>= MAX_SECTION_SIZE
) {
869 Offset
= sizeof (EFI_GUID_DEFINED_SECTION2
);
872 TotalLength
= InputLength
+ Offset
;
874 FileBuffer
= (UINT8
*) malloc (InputLength
+ Offset
);
875 if (FileBuffer
== NULL
) {
876 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
877 return EFI_OUT_OF_RESOURCES
;
880 // read all input file contents into a buffer
882 Status
= GetSectionContents (
891 if (EFI_ERROR (Status
)) {
892 if (FileBuffer
!= NULL
) {
895 Error (NULL
, 0, 0001, "Error opening file for reading", InputFileName
[0]);
899 if (InputLength
== 0) {
900 Error (NULL
, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName
);
901 return EFI_NOT_FOUND
;
905 // Now data is in FileBuffer + Offset
907 if (CompareGuid (VendorGuid
, &mZeroGuid
) == 0) {
909 // Default Guid section is CRC32.
912 CalculateCrc32 (FileBuffer
+ Offset
, InputLength
, &Crc32Checksum
);
914 if (TotalLength
>= MAX_SECTION_SIZE
) {
915 Crc32GuidSect2
= (CRC32_SECTION_HEADER2
*) FileBuffer
;
916 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
917 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) 0xff;
918 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) 0xff;
919 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) 0xff;
920 Crc32GuidSect2
->GuidSectionHeader
.CommonHeader
.ExtendedSize
= TotalLength
;
921 memcpy (&(Crc32GuidSect2
->GuidSectionHeader
.SectionDefinitionGuid
), &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
922 Crc32GuidSect2
->GuidSectionHeader
.Attributes
= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
923 Crc32GuidSect2
->GuidSectionHeader
.DataOffset
= sizeof (CRC32_SECTION_HEADER2
);
924 Crc32GuidSect2
->CRC32Checksum
= Crc32Checksum
;
925 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2
->GuidSectionHeader
.DataOffset
);
927 Crc32GuidSect
= (CRC32_SECTION_HEADER
*) FileBuffer
;
928 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
929 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
930 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
931 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
932 memcpy (&(Crc32GuidSect
->GuidSectionHeader
.SectionDefinitionGuid
), &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
933 Crc32GuidSect
->GuidSectionHeader
.Attributes
= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
934 Crc32GuidSect
->GuidSectionHeader
.DataOffset
= sizeof (CRC32_SECTION_HEADER
);
935 Crc32GuidSect
->CRC32Checksum
= Crc32Checksum
;
936 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect
->GuidSectionHeader
.DataOffset
);
939 if (TotalLength
>= MAX_SECTION_SIZE
) {
940 VendorGuidSect2
= (EFI_GUID_DEFINED_SECTION2
*) FileBuffer
;
941 VendorGuidSect2
->CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
942 VendorGuidSect2
->CommonHeader
.Size
[0] = (UINT8
) 0xff;
943 VendorGuidSect2
->CommonHeader
.Size
[1] = (UINT8
) 0xff;
944 VendorGuidSect2
->CommonHeader
.Size
[2] = (UINT8
) 0xff;
945 VendorGuidSect2
->CommonHeader
.ExtendedSize
= InputLength
+ sizeof (EFI_GUID_DEFINED_SECTION2
);
946 memcpy (&(VendorGuidSect2
->SectionDefinitionGuid
), VendorGuid
, sizeof (EFI_GUID
));
947 VendorGuidSect2
->Attributes
= DataAttribute
;
948 VendorGuidSect2
->DataOffset
= (UINT16
) (sizeof (EFI_GUID_DEFINED_SECTION2
) + DataHeaderSize
);
949 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2
->DataOffset
);
951 VendorGuidSect
= (EFI_GUID_DEFINED_SECTION
*) FileBuffer
;
952 VendorGuidSect
->CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
953 VendorGuidSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
954 VendorGuidSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
955 VendorGuidSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
956 memcpy (&(VendorGuidSect
->SectionDefinitionGuid
), VendorGuid
, sizeof (EFI_GUID
));
957 VendorGuidSect
->Attributes
= DataAttribute
;
958 VendorGuidSect
->DataOffset
= (UINT16
) (sizeof (EFI_GUID_DEFINED_SECTION
) + DataHeaderSize
);
959 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect
->DataOffset
);
962 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
967 *OutFileBuffer
= FileBuffer
;
985 command line parameters
989 EFI_SUCCESS Section header successfully generated and section concatenated.
990 EFI_ABORTED Could not generate the section
991 EFI_OUT_OF_RESOURCES No resource to complete the operation.
998 CHAR8
**InputFileName
;
999 CHAR8
*OutputFileName
;
1001 CHAR8
*CompressionName
;
1002 CHAR8
*StringBuffer
;
1003 EFI_GUID VendorGuid
= mZeroGuid
;
1006 UINT8 SectCompSubType
;
1007 UINT16 SectGuidAttribute
;
1008 UINT64 SectGuidHeaderLength
;
1009 EFI_VERSION_SECTION
*VersionSect
;
1010 EFI_USER_INTERFACE_SECTION
*UiSect
;
1012 UINT8
*OutFileBuffer
;
1015 UINT32
*InputFileAlign
;
1016 UINT32 InputFileAlignNum
;
1017 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
1019 InputFileAlign
= NULL
;
1020 InputFileAlignNum
= 0;
1021 InputFileName
= NULL
;
1022 OutputFileName
= NULL
;
1024 CompressionName
= NULL
;
1029 SectType
= EFI_SECTION_ALL
;
1030 SectCompSubType
= 0;
1031 SectGuidAttribute
= EFI_GUIDED_SECTION_NONE
;
1032 OutFileBuffer
= NULL
;
1034 Status
= STATUS_SUCCESS
;
1036 SectGuidHeaderLength
= 0;
1040 SetUtilityName (UTILITY_NAME
);
1043 Error (NULL
, 0, 1001, "Missing options", "No options input");
1045 return STATUS_ERROR
;
1049 // Parse command line
1054 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
1057 return STATUS_SUCCESS
;
1060 if (stricmp (argv
[0], "--version") == 0) {
1062 return STATUS_SUCCESS
;
1066 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--SectionType") == 0)) {
1067 SectionName
= argv
[1];
1068 if (SectionName
== NULL
) {
1069 Error (NULL
, 0, 1003, "Invalid option value", "Section Type can't be NULL");
1077 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1078 OutputFileName
= argv
[1];
1079 if (OutputFileName
== NULL
) {
1080 Error (NULL
, 0, 1003, "Invalid option value", "Output file can't be NULL");
1088 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--compress") == 0)) {
1089 CompressionName
= argv
[1];
1090 if (CompressionName
== NULL
) {
1091 Error (NULL
, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
1099 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--vendor") == 0)) {
1100 Status
= StringToGuid (argv
[1], &VendorGuid
);
1101 if (EFI_ERROR (Status
)) {
1102 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1110 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--attributes") == 0)) {
1111 if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]) == 0) {
1112 SectGuidAttribute
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1113 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]) == 0) {
1114 SectGuidAttribute
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
1115 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[0]) == 0) {
1119 SectGuidAttribute
|= EFI_GUIDED_SECTION_NONE
;
1121 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1129 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--HeaderLength") == 0)) {
1130 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &SectGuidHeaderLength
);
1131 if (EFI_ERROR (Status
)) {
1132 Error (NULL
, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv
[0], argv
[1]);
1140 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--name") == 0)) {
1141 StringBuffer
= argv
[1];
1142 if (StringBuffer
== NULL
) {
1143 Error (NULL
, 0, 1003, "Invalid option value", "Name can't be NULL");
1151 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--buildnumber") == 0)) {
1152 if (argv
[1] == NULL
) {
1153 Error (NULL
, 0, 1003, "Invalid option value", "build number can't be NULL");
1157 // Verify string is a integrator number
1159 for (Index
= 0; Index
< strlen (argv
[1]); Index
++) {
1160 if ((argv
[1][Index
] != '-') && (isdigit ((int)argv
[1][Index
]) == 0)) {
1161 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1166 sscanf (argv
[1], "%d", &VersionNumber
);
1172 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1173 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1174 VerboseMsg ("Verbose output Mode Set!");
1180 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1181 SetPrintLevel (KEY_LOG_LEVEL
);
1182 KeyMsg ("Quiet output Mode Set!");
1188 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1189 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1190 if (EFI_ERROR (Status
)) {
1191 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1195 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel
);
1198 SetPrintLevel (LogLevel
);
1199 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1206 // Section File alignment requirement
1208 if (stricmp (argv
[0], "--sectionalign") == 0) {
1209 if (InputFileAlignNum
== 0) {
1210 InputFileAlign
= (UINT32
*) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1211 if (InputFileAlign
== NULL
) {
1212 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1215 memset (InputFileAlign
, 1, MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1216 } else if (InputFileAlignNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1217 InputFileAlign
= (UINT32
*) realloc (
1219 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (UINT32
)
1222 if (InputFileAlign
== NULL
) {
1223 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1226 memset (&(InputFileAlign
[InputFileNum
]), 1, (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
)));
1229 Status
= StringtoAlignment (argv
[1], &(InputFileAlign
[InputFileAlignNum
]));
1230 if (EFI_ERROR (Status
)) {
1231 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1236 InputFileAlignNum
++;
1241 // Get Input file name
1243 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1244 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1245 if (InputFileName
== NULL
) {
1246 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1249 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1250 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1252 // InputFileName buffer too small, need to realloc
1254 InputFileName
= (CHAR8
**) realloc (
1256 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1259 if (InputFileName
== NULL
) {
1260 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1263 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1266 InputFileName
[InputFileNum
++] = argv
[0];
1271 if (InputFileAlignNum
> 0 && InputFileAlignNum
!= InputFileNum
) {
1272 Error (NULL
, 0, 1003, "Invalid option", "section alignment must be set for each section");
1276 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1279 // Parse all command line parameters to get the corresponding section type.
1281 VerboseMsg ("Section type is %s", SectionName
);
1282 if (SectionName
== NULL
) {
1284 // No specified Section type, default is SECTION_ALL.
1286 SectType
= EFI_SECTION_ALL
;
1287 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPRESSION
]) == 0) {
1288 SectType
= EFI_SECTION_COMPRESSION
;
1289 if (CompressionName
== NULL
) {
1291 // Default is PI_STD compression algorithm.
1293 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1294 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_NOT_COMPRESSED
]) == 0) {
1295 SectCompSubType
= EFI_NOT_COMPRESSED
;
1296 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_STANDARD_COMPRESSION
]) == 0) {
1297 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1299 Error (NULL
, 0, 1003, "Invalid option value", "--compress = %s", CompressionName
);
1302 VerboseMsg ("Compress method is %s", mCompressionTypeName
[SectCompSubType
]);
1303 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_GUID_DEFINED
]) == 0) {
1304 SectType
= EFI_SECTION_GUID_DEFINED
;
1306 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_NONE
) != 0) {
1308 // NONE attribute, clear attribute value.
1310 SectGuidAttribute
= SectGuidAttribute
& ~EFI_GUIDED_SECTION_NONE
;
1312 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1313 (unsigned) VendorGuid
.Data1
,
1316 VendorGuid
.Data4
[0],
1317 VendorGuid
.Data4
[1],
1318 VendorGuid
.Data4
[2],
1319 VendorGuid
.Data4
[3],
1320 VendorGuid
.Data4
[4],
1321 VendorGuid
.Data4
[5],
1322 VendorGuid
.Data4
[6],
1323 VendorGuid
.Data4
[7]);
1324 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
1325 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]);
1327 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
1328 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]);
1330 if (SectGuidHeaderLength
!= 0) {
1331 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength
);
1333 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PE32
]) == 0) {
1334 SectType
= EFI_SECTION_PE32
;
1335 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PIC
]) == 0) {
1336 SectType
= EFI_SECTION_PIC
;
1337 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_TE
]) == 0) {
1338 SectType
= EFI_SECTION_TE
;
1339 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_DXE_DEPEX
]) == 0) {
1340 SectType
= EFI_SECTION_DXE_DEPEX
;
1341 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_SMM_DEPEX
]) == 0) {
1342 SectType
= EFI_SECTION_SMM_DEPEX
;
1343 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_VERSION
]) == 0) {
1344 SectType
= EFI_SECTION_VERSION
;
1345 if (VersionNumber
< 0 || VersionNumber
> 65535) {
1346 Error (NULL
, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber
);
1349 VerboseMsg ("Version section number is %d", VersionNumber
);
1350 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_USER_INTERFACE
]) == 0) {
1351 SectType
= EFI_SECTION_USER_INTERFACE
;
1352 if (StringBuffer
[0] == '\0') {
1353 Error (NULL
, 0, 1001, "Missing option", "user interface string");
1356 VerboseMsg ("UI section string name is %s", StringBuffer
);
1357 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPATIBILITY16
]) == 0) {
1358 SectType
= EFI_SECTION_COMPATIBILITY16
;
1359 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FIRMWARE_VOLUME_IMAGE
]) == 0) {
1360 SectType
= EFI_SECTION_FIRMWARE_VOLUME_IMAGE
;
1361 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FREEFORM_SUBTYPE_GUID
]) == 0) {
1362 SectType
= EFI_SECTION_FREEFORM_SUBTYPE_GUID
;
1363 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_RAW
]) == 0) {
1364 SectType
= EFI_SECTION_RAW
;
1365 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PEI_DEPEX
]) == 0) {
1366 SectType
= EFI_SECTION_PEI_DEPEX
;
1368 Error (NULL
, 0, 1003, "Invalid option value", "SectionType = %s", SectionName
);
1373 // GuidValue is only required by Guided section.
1375 if ((SectType
!= EFI_SECTION_GUID_DEFINED
) && (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1376 fprintf (stdout
, "Warning: the input guid value is not required for this section type %s\n", SectionName
);
1380 // Check whether there is input file
1382 if ((SectType
!= EFI_SECTION_VERSION
) && (SectType
!= EFI_SECTION_USER_INTERFACE
)) {
1384 // The input file are required for other section type.
1386 if (InputFileNum
== 0) {
1387 Error (NULL
, 0, 1001, "Missing options", "Input files");
1392 // Check whether there is output file
1394 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1395 VerboseMsg ("the %uth input file name is %s", (unsigned) Index
, InputFileName
[Index
]);
1397 if (OutputFileName
== NULL
) {
1398 Error (NULL
, 0, 1001, "Missing options", "Output file");
1400 // OutFile = stdout;
1402 VerboseMsg ("Output file name is %s", OutputFileName
);
1405 // At this point, we've fully validated the command line, and opened appropriate
1406 // files, so let's go and do what we've been asked to do...
1409 // Within this switch, build and write out the section header including any
1410 // section type specific pieces. If there's an input file, it's tacked on later
1413 case EFI_SECTION_COMPRESSION
:
1414 if (InputFileAlign
!= NULL
) {
1415 free (InputFileAlign
);
1416 InputFileAlign
= NULL
;
1418 Status
= GenSectionCompressionSection (
1427 case EFI_SECTION_GUID_DEFINED
:
1428 if (InputFileAlign
!= NULL
&& (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1430 // Only process alignment for the default known CRC32 guided section.
1431 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
1433 free (InputFileAlign
);
1434 InputFileAlign
= NULL
;
1436 Status
= GenSectionGuidDefinedSection (
1442 (UINT32
) SectGuidHeaderLength
,
1447 case EFI_SECTION_VERSION
:
1448 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1450 // 2 bytes for the build number UINT16
1454 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1456 Index
+= (strlen (StringBuffer
) * 2) + 2;
1457 OutFileBuffer
= (UINT8
*) malloc (Index
);
1458 if (OutFileBuffer
== NULL
) {
1459 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1462 VersionSect
= (EFI_VERSION_SECTION
*) OutFileBuffer
;
1463 VersionSect
->CommonHeader
.Type
= SectType
;
1464 VersionSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1465 VersionSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1466 VersionSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1467 VersionSect
->BuildNumber
= (UINT16
) VersionNumber
;
1468 Ascii2UnicodeString (StringBuffer
, VersionSect
->VersionString
);
1469 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1472 case EFI_SECTION_USER_INTERFACE
:
1473 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1475 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1477 Index
+= (strlen (StringBuffer
) * 2) + 2;
1478 OutFileBuffer
= (UINT8
*) malloc (Index
);
1479 if (OutFileBuffer
== NULL
) {
1480 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1483 UiSect
= (EFI_USER_INTERFACE_SECTION
*) OutFileBuffer
;
1484 UiSect
->CommonHeader
.Type
= SectType
;
1485 UiSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1486 UiSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1487 UiSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1488 Ascii2UnicodeString (StringBuffer
, UiSect
->FileNameString
);
1489 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1492 case EFI_SECTION_ALL
:
1494 // read all input file contents into a buffer
1495 // first get the size of all file contents
1497 Status
= GetSectionContents (
1505 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1506 OutFileBuffer
= (UINT8
*) malloc (InputLength
);
1507 if (OutFileBuffer
== NULL
) {
1508 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1512 // read all input file contents into a buffer
1514 Status
= GetSectionContents (
1522 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength
);
1526 // All other section types are caught by default (they're all the same)
1528 Status
= GenSectionCommonLeafSection (
1537 if (Status
!= EFI_SUCCESS
|| OutFileBuffer
== NULL
) {
1538 Error (NULL
, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status
);
1543 // Get output file length
1545 if (SectType
!= EFI_SECTION_ALL
) {
1546 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*)OutFileBuffer
;
1547 InputLength
= *(UINT32
*)SectionHeader
->Size
& 0x00ffffff;
1548 if (InputLength
== 0xffffff) {
1549 InputLength
= ((EFI_COMMON_SECTION_HEADER2
*)SectionHeader
)->ExtendedSize
;
1554 // Write the output file
1556 OutFile
= fopen (LongFilePath (OutputFileName
), "wb");
1557 if (OutFile
== NULL
) {
1558 Error (NULL
, 0, 0001, "Error opening file for writing", OutputFileName
);
1562 fwrite (OutFileBuffer
, InputLength
, 1, OutFile
);
1565 if (InputFileName
!= NULL
) {
1566 free (InputFileName
);
1569 if (InputFileAlign
!= NULL
) {
1570 free (InputFileAlign
);
1573 if (OutFileBuffer
!= NULL
) {
1574 free (OutFileBuffer
);
1577 if (OutFile
!= NULL
) {
1581 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
1583 return GetUtilityStatus ();