3 Copyright (c) 2004 - 2011, 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 #define MAX_SECTION_SIZE 0x1000000
47 STATIC CHAR8
*mSectionTypeName
[] = {
48 NULL
, // 0x00 - reserved
49 "EFI_SECTION_COMPRESSION", // 0x01
50 "EFI_SECTION_GUID_DEFINED", // 0x02
51 NULL
, // 0x03 - reserved
52 NULL
, // 0x04 - reserved
53 NULL
, // 0x05 - reserved
54 NULL
, // 0x06 - reserved
55 NULL
, // 0x07 - reserved
56 NULL
, // 0x08 - reserved
57 NULL
, // 0x09 - reserved
58 NULL
, // 0x0A - reserved
59 NULL
, // 0x0B - reserved
60 NULL
, // 0x0C - reserved
61 NULL
, // 0x0D - reserved
62 NULL
, // 0x0E - reserved
63 NULL
, // 0x0F - reserved
64 "EFI_SECTION_PE32", // 0x10
65 "EFI_SECTION_PIC", // 0x11
66 "EFI_SECTION_TE", // 0x12
67 "EFI_SECTION_DXE_DEPEX", // 0x13
68 "EFI_SECTION_VERSION", // 0x14
69 "EFI_SECTION_USER_INTERFACE", // 0x15
70 "EFI_SECTION_COMPATIBILITY16", // 0x16
71 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17
72 "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18
73 "EFI_SECTION_RAW", // 0x19
75 "EFI_SECTION_PEI_DEPEX", // 0x1B
76 "EFI_SECTION_SMM_DEPEX" // 0x1C
79 STATIC CHAR8
*mCompressionTypeName
[] = { "PI_NONE", "PI_STD" };
81 #define EFI_GUIDED_SECTION_NONE 0x80
82 STATIC CHAR8
*mGUIDedSectionAttribue
[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};
84 STATIC CHAR8
*mAlignName
[] = {
85 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
86 "1K", "2K", "4K", "8K", "16K", "32K", "64K"
90 // Crc32 GUID section related definitions.
93 EFI_GUID_DEFINED_SECTION GuidSectionHeader
;
95 } CRC32_SECTION_HEADER
;
97 STATIC EFI_GUID mZeroGuid
= {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
98 STATIC EFI_GUID mEfiCrc32SectionGuid
= EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID
;
109 Print out version information for this utility.
121 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
148 fprintf (stdout
, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME
);
151 // Copyright declaration
153 fprintf (stdout
, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");
158 fprintf (stdout
, "Options:\n");
159 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
160 File is the SectionFile to be created.\n");
161 fprintf (stdout
, " -s [SectionType], --sectiontype [SectionType]\n\
162 SectionType defined in PI spec is one type of\n\
163 EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\
164 EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\
165 EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\
166 EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\
167 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\
168 EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\
169 EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\
170 if -s option is not given, \n\
171 EFI_SECTION_ALL is default section type.\n");
172 fprintf (stdout
, " -c [Type], --compress [Type]\n\
173 Compress method type can be PI_NONE or PI_STD.\n\
174 if -c option is not given, PI_STD is default type.\n");
175 fprintf (stdout
, " -g GuidValue, --vendor GuidValue\n\
176 GuidValue is one specific vendor guid value.\n\
177 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
178 fprintf (stdout
, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
179 GuidHeaderLength is the size of header of guided data\n");
180 fprintf (stdout
, " -r GuidAttr, --attributes GuidAttr\n\
181 GuidAttr is guid section atttributes, which may be\n\
182 PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
183 if -r option is not given, default PROCESSING_REQUIRED\n");
184 fprintf (stdout
, " -n String, --name String\n\
185 String is a NULL terminated string used in Ui section.\n");
186 fprintf (stdout
, " -j Number, --buildnumber Number\n\
187 Number is an integer value between 0000 and 9999\n\
188 used in Ver section.\n");
189 fprintf (stdout
, " --sectionalign SectionAlign\n\
190 SectionAlign points to section alignment, which support\n\
191 the alignment scope 1~64K. It is specified in same\n\
192 order that the section file is input.\n");
193 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
194 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
195 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
196 fprintf (stdout
, " --version Show program's version number and exit.\n");
197 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
201 Ascii2UnicodeString (
209 Write ascii string as unicode string format to FILE
213 String - Pointer to string that is written to FILE.
214 UniString - Pointer to unicode string
222 while (*String
!= '\0') {
223 *(UniString
++) = (CHAR16
) *(String
++);
226 // End the UniString with a NULL.
232 GenSectionCommonLeafSection (
233 CHAR8
**InputFileName
,
236 UINT8
**OutFileBuffer
242 Generate a leaf section of type other than EFI_SECTION_VERSION
243 and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
244 The function won't validate the input file's contents. For
245 common leaf sections, the input file may be a binary file.
246 The utility will add section header to the file.
250 InputFileName - Name of the input file.
252 InputFileNum - Number of input files. Should be 1 for leaf section.
254 SectionType - A valid section type string
256 OutFileBuffer - Buffer pointer to Output file contents
260 STATUS_ERROR - can't continue
261 STATUS_SUCCESS - successful return
265 UINT32 InputFileLength
;
269 EFI_COMMON_SECTION_HEADER
*CommonSect
;
272 if (InputFileNum
> 1) {
273 Error (NULL
, 0, 2000, "Invalid paramter", "more than one input file specified");
275 } else if (InputFileNum
< 1) {
276 Error (NULL
, 0, 2000, "Invalid paramter", "no input file specified");
280 // Open the input file
282 InFile
= fopen (InputFileName
[0], "rb");
283 if (InFile
== NULL
) {
284 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[0]);
288 Status
= STATUS_ERROR
;
291 // Seek to the end of the input file so we can determine its size
293 fseek (InFile
, 0, SEEK_END
);
294 InputFileLength
= ftell (InFile
);
295 fseek (InFile
, 0, SEEK_SET
);
296 DebugMsg (NULL
, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName
[0], (unsigned) InputFileLength
);
297 TotalLength
= sizeof (EFI_COMMON_SECTION_HEADER
) + InputFileLength
;
299 // Size must fit in 3 bytes
301 if (TotalLength
>= MAX_SECTION_SIZE
) {
302 Error (NULL
, 0, 2000, "Invalid paramter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName
[0], (unsigned) TotalLength
, MAX_SECTION_SIZE
>>20);
305 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
307 // Fill in the fields in the local section header structure
309 Buffer
= (UINT8
*) malloc ((size_t) TotalLength
);
310 if (Buffer
== NULL
) {
311 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
314 CommonSect
= (EFI_COMMON_SECTION_HEADER
*) Buffer
;
315 CommonSect
->Type
= SectionType
;
316 CommonSect
->Size
[0] = (UINT8
) (TotalLength
& 0xff);
317 CommonSect
->Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
318 CommonSect
->Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
321 // read data from the input file.
323 if (InputFileLength
!= 0) {
324 if (fread (Buffer
+ sizeof (EFI_COMMON_SECTION_HEADER
), (size_t) InputFileLength
, 1, InFile
) != 1) {
325 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[0]);
333 *OutFileBuffer
= Buffer
;
334 Status
= STATUS_SUCCESS
;
345 IN CHAR8
*AlignBuffer
,
346 OUT UINT32
*AlignNumber
352 Converts Align String to align value (1~64K).
356 AlignBuffer - Pointer to Align string.
357 AlignNumber - Pointer to Align value.
361 EFI_SUCCESS Successfully convert align string to align value.
362 EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.
370 if (AlignBuffer
== NULL
) {
371 return EFI_INVALID_PARAMETER
;
373 for (Index
= 0; Index
< sizeof (mAlignName
) / sizeof (CHAR8
*); Index
++) {
374 if (stricmp (AlignBuffer
, mAlignName
[Index
]) == 0) {
375 *AlignNumber
= 1 << Index
;
379 return EFI_INVALID_PARAMETER
;
384 CHAR8
**InputFileName
,
385 UINT32
*InputFileAlign
,
394 Get the contents of all section files specified in InputFileName
399 InputFileName - Name of the input file.
401 InputFileAlign - Alignment required by the input file data.
403 InputFileNum - Number of input files. Should be at least 1.
405 FileBuffer - Output buffer to contain data
407 BufferLength - On input, this is size of the FileBuffer.
408 On output, this is the actual length of the data.
412 EFI_SUCCESS on successful return
413 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
414 EFI_ABORTED if unable to open input file.
415 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
423 EFI_COMMON_SECTION_HEADER
*SectHeader
;
424 EFI_COMMON_SECTION_HEADER TempSectHeader
;
425 EFI_TE_IMAGE_HEADER TeHeader
;
427 EFI_GUID_DEFINED_SECTION GuidSectHeader
;
430 if (InputFileNum
< 1) {
431 Error (NULL
, 0, 2000, "Invalid paramter", "must specify at least one input file");
432 return EFI_INVALID_PARAMETER
;
435 if (BufferLength
== NULL
) {
436 Error (NULL
, 0, 2000, "Invalid paramter", "BufferLength can't be NULL");
437 return EFI_INVALID_PARAMETER
;
444 // Go through our array of file names and copy their contents
445 // to the output buffer.
447 for (Index
= 0; Index
< InputFileNum
; Index
++) {
449 // make sure section ends on a DWORD boundary
451 while ((Size
& 0x03) != 0) {
452 if (FileBuffer
!= NULL
&& Size
< *BufferLength
) {
453 FileBuffer
[Size
] = 0;
459 // Open file and read contents
461 InFile
= fopen (InputFileName
[Index
], "rb");
462 if (InFile
== NULL
) {
463 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
467 fseek (InFile
, 0, SEEK_END
);
468 FileSize
= ftell (InFile
);
469 fseek (InFile
, 0, SEEK_SET
);
470 DebugMsg (NULL
, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName
[Index
], (unsigned) FileSize
);
472 // Adjust section buffer when section alignment is required.
474 if (InputFileAlign
!= NULL
) {
476 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
479 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER
);
480 fread (&TempSectHeader
, 1, sizeof (TempSectHeader
), InFile
);
481 if (TempSectHeader
.Type
== EFI_SECTION_TE
) {
482 fread (&TeHeader
, 1, sizeof (TeHeader
), InFile
);
483 if (TeHeader
.Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
484 TeOffset
= TeHeader
.StrippedSize
- sizeof (TeHeader
);
486 } else if (TempSectHeader
.Type
== EFI_SECTION_GUID_DEFINED
) {
487 fseek (InFile
, 0, SEEK_SET
);
488 fread (&GuidSectHeader
, 1, sizeof (GuidSectHeader
), InFile
);
489 if ((GuidSectHeader
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
490 HeaderSize
= GuidSectHeader
.DataOffset
;
494 fseek (InFile
, 0, SEEK_SET
);
497 // Revert TeOffset to the converse value relative to Alignment
498 // This is to assure the original PeImage Header at Alignment.
501 TeOffset
= InputFileAlign
[Index
] - (TeOffset
% InputFileAlign
[Index
]);
502 TeOffset
= TeOffset
% InputFileAlign
[Index
];
506 // make sure section data meet its alignment requirement by adding one raw pad section.
508 if ((InputFileAlign
[Index
] != 0) && (((Size
+ HeaderSize
+ TeOffset
) % InputFileAlign
[Index
]) != 0)) {
509 Offset
= (Size
+ sizeof (EFI_COMMON_SECTION_HEADER
) + HeaderSize
+ TeOffset
+ InputFileAlign
[Index
] - 1) & ~(InputFileAlign
[Index
] - 1);
510 Offset
= Offset
- Size
- HeaderSize
- TeOffset
;
512 if (FileBuffer
!= NULL
&& ((Size
+ Offset
) < *BufferLength
)) {
513 memset (FileBuffer
+ Size
, 0, Offset
);
514 SectHeader
= (EFI_COMMON_SECTION_HEADER
*) (FileBuffer
+ Size
);
515 SectHeader
->Type
= EFI_SECTION_RAW
;
516 SectHeader
->Size
[0] = (UINT8
) (Offset
& 0xff);
517 SectHeader
->Size
[1] = (UINT8
) ((Offset
& 0xff00) >> 8);
518 SectHeader
->Size
[2] = (UINT8
) ((Offset
& 0xff0000) >> 16);
520 DebugMsg (NULL
, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset
);
522 Size
= Size
+ Offset
;
527 // Now read the contents of the file into the buffer
528 // Buffer must be enough to contain the file content.
530 if ((FileSize
> 0) && (FileBuffer
!= NULL
) && ((Size
+ FileSize
) <= *BufferLength
)) {
531 if (fread (FileBuffer
+ Size
, (size_t) FileSize
, 1, InFile
) != 1) {
532 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[Index
]);
543 // Set the real required buffer size.
545 if (Size
> *BufferLength
) {
546 *BufferLength
= Size
;
547 return EFI_BUFFER_TOO_SMALL
;
549 *BufferLength
= Size
;
555 GenSectionCompressionSection (
556 CHAR8
**InputFileName
,
557 UINT32
*InputFileAlign
,
559 UINT8 SectCompSubType
,
560 UINT8
**OutFileBuffer
566 Generate an encapsulating section of type EFI_SECTION_COMPRESSION
567 Input file must be already sectioned. The function won't validate
568 the input files' contents. Caller should hand in files already
573 InputFileName - Name of the input file.
575 InputFileAlign - Alignment required by the input file data.
577 InputFileNum - Number of input files. Should be at least 1.
579 SectCompSubType - Specify the compression algorithm requested.
581 OutFileBuffer - Buffer pointer to Output file contents
585 EFI_SUCCESS on successful return
586 EFI_INVALID_PARAMETER if InputFileNum is less than 1
587 EFI_ABORTED if unable to open input file.
588 EFI_OUT_OF_RESOURCES No resource to complete the operation.
593 UINT32 CompressedLength
;
597 EFI_COMPRESSION_SECTION
*CompressionSect
;
598 COMPRESS_FUNCTION CompressFunction
;
603 CompressedLength
= 0;
605 // read all input file contents into a buffer
606 // first get the size of all file contents
608 Status
= GetSectionContents (
616 if (Status
== EFI_BUFFER_TOO_SMALL
) {
617 FileBuffer
= (UINT8
*) malloc (InputLength
);
618 if (FileBuffer
== NULL
) {
619 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
620 return EFI_OUT_OF_RESOURCES
;
623 // read all input file contents into a buffer
625 Status
= GetSectionContents (
634 if (EFI_ERROR (Status
)) {
635 if (FileBuffer
!= NULL
) {
641 CompressFunction
= NULL
;
644 // Now data is in FileBuffer, compress the data
646 switch (SectCompSubType
) {
647 case EFI_NOT_COMPRESSED
:
648 CompressedLength
= InputLength
;
650 // Copy file buffer to the none compressed data.
652 OutputBuffer
= malloc (CompressedLength
+ sizeof (EFI_COMPRESSION_SECTION
));
653 if (OutputBuffer
== NULL
) {
655 return EFI_OUT_OF_RESOURCES
;
657 memcpy (OutputBuffer
+ sizeof (EFI_COMPRESSION_SECTION
), FileBuffer
, CompressedLength
);
658 FileBuffer
= OutputBuffer
;
661 case EFI_STANDARD_COMPRESSION
:
662 CompressFunction
= (COMPRESS_FUNCTION
) EfiCompress
;
666 Error (NULL
, 0, 2000, "Invalid paramter", "unknown compression type");
671 if (CompressFunction
!= NULL
) {
673 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
, &CompressedLength
);
674 if (Status
== EFI_BUFFER_TOO_SMALL
) {
675 OutputBuffer
= malloc (CompressedLength
+ sizeof (EFI_COMPRESSION_SECTION
));
678 return EFI_OUT_OF_RESOURCES
;
681 Status
= CompressFunction (FileBuffer
, InputLength
, OutputBuffer
+ sizeof (EFI_COMPRESSION_SECTION
), &CompressedLength
);
685 FileBuffer
= OutputBuffer
;
687 if (EFI_ERROR (Status
)) {
688 if (FileBuffer
!= NULL
) {
696 DebugMsg (NULL
, 0, 9, "comprss file size",
697 "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength
, (unsigned) CompressedLength
);
698 TotalLength
= CompressedLength
+ sizeof (EFI_COMPRESSION_SECTION
);
699 if (TotalLength
>= MAX_SECTION_SIZE
) {
700 Error (NULL
, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE
>>20);
701 if (FileBuffer
!= NULL
) {
704 if (OutputBuffer
!= NULL
) {
709 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
712 // Add the section header for the compressed data
714 CompressionSect
= (EFI_COMPRESSION_SECTION
*) FileBuffer
;
716 CompressionSect
->CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
717 CompressionSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
718 CompressionSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
719 CompressionSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
720 CompressionSect
->CompressionType
= SectCompSubType
;
721 CompressionSect
->UncompressedLength
= InputLength
;
726 *OutFileBuffer
= FileBuffer
;
732 GenSectionGuidDefinedSection (
733 CHAR8
**InputFileName
,
734 UINT32
*InputFileAlign
,
736 EFI_GUID
*VendorGuid
,
737 UINT16 DataAttribute
,
738 UINT32 DataHeaderSize
,
739 UINT8
**OutFileBuffer
745 Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
746 Input file must be already sectioned. The function won't validate
747 the input files' contents. Caller should hand in files already
752 InputFileName - Name of the input file.
754 InputFileAlign - Alignment required by the input file data.
756 InputFileNum - Number of input files. Should be at least 1.
758 VendorGuid - Specify vendor guid value.
760 DataAttribute - Specify attribute for the vendor guid data.
762 DataHeaderSize- Guided Data Header Size
764 OutFileBuffer - Buffer pointer to Output file contents
768 EFI_SUCCESS on successful return
769 EFI_INVALID_PARAMETER if InputFileNum is less than 1
770 EFI_ABORTED if unable to open input file.
771 EFI_OUT_OF_RESOURCES No resource to complete the operation.
779 UINT32 Crc32Checksum
;
781 CRC32_SECTION_HEADER
*Crc32GuidSect
;
782 EFI_GUID_DEFINED_SECTION
*VendorGuidSect
;
788 if (CompareGuid (VendorGuid
, &mEfiCrc32SectionGuid
) == 0) {
789 Offset
= sizeof (CRC32_SECTION_HEADER
);
791 Offset
= sizeof (EFI_GUID_DEFINED_SECTION
);
795 // read all input file contents into a buffer
796 // first get the size of all file contents
798 Status
= GetSectionContents (
806 if (Status
== EFI_BUFFER_TOO_SMALL
) {
807 FileBuffer
= (UINT8
*) malloc (InputLength
+ Offset
);
808 if (FileBuffer
== NULL
) {
809 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
810 return EFI_OUT_OF_RESOURCES
;
813 // read all input file contents into a buffer
815 Status
= GetSectionContents (
824 if (EFI_ERROR (Status
)) {
825 if (FileBuffer
!= NULL
) {
828 Error (NULL
, 0, 0001, "Error opening file for reading", InputFileName
[0]);
832 if (InputLength
== 0) {
833 Error (NULL
, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName
);
834 return EFI_NOT_FOUND
;
838 // Now data is in FileBuffer + Offset
840 if (CompareGuid (VendorGuid
, &mEfiCrc32SectionGuid
) == 0) {
842 // Default Guid section is CRC32.
845 CalculateCrc32 (FileBuffer
+ Offset
, InputLength
, &Crc32Checksum
);
847 TotalLength
= InputLength
+ sizeof (CRC32_SECTION_HEADER
);
848 if (TotalLength
>= MAX_SECTION_SIZE
) {
849 Error (NULL
, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE
>>20);
854 Crc32GuidSect
= (CRC32_SECTION_HEADER
*) FileBuffer
;
855 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
856 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
857 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
858 Crc32GuidSect
->GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
859 memcpy (&(Crc32GuidSect
->GuidSectionHeader
.SectionDefinitionGuid
), &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
860 Crc32GuidSect
->GuidSectionHeader
.Attributes
= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
861 Crc32GuidSect
->GuidSectionHeader
.DataOffset
= sizeof (CRC32_SECTION_HEADER
);
862 Crc32GuidSect
->CRC32Checksum
= Crc32Checksum
;
863 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect
->GuidSectionHeader
.DataOffset
);
866 TotalLength
= InputLength
+ sizeof (EFI_GUID_DEFINED_SECTION
);
867 if (TotalLength
>= MAX_SECTION_SIZE
) {
868 Error (NULL
, 0, 2000, "Invalid paramter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE
>>20);
873 VendorGuidSect
= (EFI_GUID_DEFINED_SECTION
*) FileBuffer
;
874 VendorGuidSect
->CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
875 VendorGuidSect
->CommonHeader
.Size
[0] = (UINT8
) (TotalLength
& 0xff);
876 VendorGuidSect
->CommonHeader
.Size
[1] = (UINT8
) ((TotalLength
& 0xff00) >> 8);
877 VendorGuidSect
->CommonHeader
.Size
[2] = (UINT8
) ((TotalLength
& 0xff0000) >> 16);
878 memcpy (&(VendorGuidSect
->SectionDefinitionGuid
), VendorGuid
, sizeof (EFI_GUID
));
879 VendorGuidSect
->Attributes
= DataAttribute
;
880 VendorGuidSect
->DataOffset
= (UINT16
) (sizeof (EFI_GUID_DEFINED_SECTION
) + DataHeaderSize
);
881 DebugMsg (NULL
, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect
->DataOffset
);
883 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength
);
888 *OutFileBuffer
= FileBuffer
;
906 command line parameters
910 EFI_SUCCESS Section header successfully generated and section concatenated.
911 EFI_ABORTED Could not generate the section
912 EFI_OUT_OF_RESOURCES No resource to complete the operation.
919 CHAR8
**InputFileName
;
920 CHAR8
*OutputFileName
;
922 CHAR8
*CompressionName
;
924 EFI_GUID VendorGuid
= mZeroGuid
;
927 UINT8 SectCompSubType
;
928 UINT16 SectGuidAttribute
;
929 UINT64 SectGuidHeaderLength
;
930 EFI_VERSION_SECTION
*VersionSect
;
931 EFI_USER_INTERFACE_SECTION
*UiSect
;
933 UINT8
*OutFileBuffer
;
936 UINT32
*InputFileAlign
;
937 UINT32 InputFileAlignNum
;
939 InputFileAlign
= NULL
;
940 InputFileAlignNum
= 0;
941 InputFileName
= NULL
;
942 OutputFileName
= NULL
;
944 CompressionName
= NULL
;
949 SectType
= EFI_SECTION_ALL
;
951 SectGuidAttribute
= EFI_GUIDED_SECTION_NONE
;
952 OutFileBuffer
= NULL
;
954 Status
= STATUS_SUCCESS
;
956 SectGuidHeaderLength
= 0;
960 SetUtilityName (UTILITY_NAME
);
963 Error (NULL
, 0, 1001, "Missing options", "No options input");
969 // Parse command line
974 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
977 return STATUS_SUCCESS
;
980 if (stricmp (argv
[0], "--version") == 0) {
982 return STATUS_SUCCESS
;
986 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--SectionType") == 0)) {
987 SectionName
= argv
[1];
988 if (SectionName
== NULL
) {
989 Error (NULL
, 0, 1003, "Invalid option value", "Section Type can't be NULL");
997 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
998 OutputFileName
= argv
[1];
999 if (OutputFileName
== NULL
) {
1000 Error (NULL
, 0, 1003, "Invalid option value", "Output file can't be NULL");
1008 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--compress") == 0)) {
1009 CompressionName
= argv
[1];
1010 if (CompressionName
== NULL
) {
1011 Error (NULL
, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
1019 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--vendor") == 0)) {
1020 Status
= StringToGuid (argv
[1], &VendorGuid
);
1021 if (EFI_ERROR (Status
)) {
1022 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1030 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--attributes") == 0)) {
1031 if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]) == 0) {
1032 SectGuidAttribute
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1033 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]) == 0) {
1034 SectGuidAttribute
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
1035 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[0]) == 0) {
1039 SectGuidAttribute
|= EFI_GUIDED_SECTION_NONE
;
1041 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1049 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--HeaderLength") == 0)) {
1050 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &SectGuidHeaderLength
);
1051 if (EFI_ERROR (Status
)) {
1052 Error (NULL
, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv
[0], argv
[1]);
1060 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--name") == 0)) {
1061 StringBuffer
= argv
[1];
1062 if (StringBuffer
== NULL
) {
1063 Error (NULL
, 0, 1003, "Invalid option value", "Name can't be NULL");
1071 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--buildnumber") == 0)) {
1072 if (argv
[1] == NULL
) {
1073 Error (NULL
, 0, 1003, "Invalid option value", "build number can't be NULL");
1077 // Verify string is a integrator number
1079 for (Index
= 0; Index
< strlen (argv
[1]); Index
++) {
1080 if ((argv
[1][Index
] != '-') && (isdigit ((int)argv
[1][Index
]) == 0)) {
1081 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1086 sscanf (argv
[1], "%d", &VersionNumber
);
1092 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1093 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1094 VerboseMsg ("Verbose output Mode Set!");
1100 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1101 SetPrintLevel (KEY_LOG_LEVEL
);
1102 KeyMsg ("Quiet output Mode Set!");
1108 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1109 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1110 if (EFI_ERROR (Status
)) {
1111 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1115 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel
);
1118 SetPrintLevel (LogLevel
);
1119 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1126 // Section File alignment requirement
1128 if (stricmp (argv
[0], "--sectionalign") == 0) {
1129 if (InputFileAlignNum
== 0) {
1130 InputFileAlign
= (UINT32
*) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1131 if (InputFileAlign
== NULL
) {
1132 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1135 memset (InputFileAlign
, 1, MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1136 } else if (InputFileAlignNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1137 InputFileAlign
= (UINT32
*) realloc (
1139 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (UINT32
)
1142 if (InputFileAlign
== NULL
) {
1143 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1146 memset (&(InputFileAlign
[InputFileNum
]), 1, (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
)));
1149 Status
= StringtoAlignment (argv
[1], &(InputFileAlign
[InputFileAlignNum
]));
1150 if (EFI_ERROR (Status
)) {
1151 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1156 InputFileAlignNum
++;
1161 // Get Input file name
1163 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1164 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1165 if (InputFileName
== NULL
) {
1166 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1169 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1170 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1172 // InputFileName buffer too small, need to realloc
1174 InputFileName
= (CHAR8
**) realloc (
1176 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1179 if (InputFileName
== NULL
) {
1180 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1183 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1186 InputFileName
[InputFileNum
++] = argv
[0];
1191 if (InputFileAlignNum
> 0 && InputFileAlignNum
!= InputFileNum
) {
1192 Error (NULL
, 0, 1003, "Invalid option", "section alignment must be set for each section");
1196 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1199 // Parse all command line parameters to get the corresponding section type.
1201 VerboseMsg ("Section type is %s", SectionName
);
1202 if (SectionName
== NULL
) {
1204 // No specified Section type, default is SECTION_ALL.
1206 SectType
= EFI_SECTION_ALL
;
1207 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPRESSION
]) == 0) {
1208 SectType
= EFI_SECTION_COMPRESSION
;
1209 if (CompressionName
== NULL
) {
1211 // Default is PI_STD compression algorithm.
1213 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1214 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_NOT_COMPRESSED
]) == 0) {
1215 SectCompSubType
= EFI_NOT_COMPRESSED
;
1216 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_STANDARD_COMPRESSION
]) == 0) {
1217 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1219 Error (NULL
, 0, 1003, "Invalid option value", "--compress = %s", CompressionName
);
1222 VerboseMsg ("Compress method is %s", mCompressionTypeName
[SectCompSubType
]);
1223 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_GUID_DEFINED
]) == 0) {
1224 SectType
= EFI_SECTION_GUID_DEFINED
;
1226 if (CompareGuid (&VendorGuid
, &mZeroGuid
) == 0) {
1227 memcpy (&VendorGuid
, &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
1230 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_NONE
) != 0) {
1232 // NONE attribute, clear attribute value.
1234 SectGuidAttribute
= SectGuidAttribute
& ~EFI_GUIDED_SECTION_NONE
;
1236 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1237 (unsigned) VendorGuid
.Data1
,
1240 VendorGuid
.Data4
[0],
1241 VendorGuid
.Data4
[1],
1242 VendorGuid
.Data4
[2],
1243 VendorGuid
.Data4
[3],
1244 VendorGuid
.Data4
[4],
1245 VendorGuid
.Data4
[5],
1246 VendorGuid
.Data4
[6],
1247 VendorGuid
.Data4
[7]);
1248 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
1249 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]);
1251 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
1252 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]);
1254 if (SectGuidHeaderLength
!= 0) {
1255 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength
);
1257 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PE32
]) == 0) {
1258 SectType
= EFI_SECTION_PE32
;
1259 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PIC
]) == 0) {
1260 SectType
= EFI_SECTION_PIC
;
1261 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_TE
]) == 0) {
1262 SectType
= EFI_SECTION_TE
;
1263 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_DXE_DEPEX
]) == 0) {
1264 SectType
= EFI_SECTION_DXE_DEPEX
;
1265 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_SMM_DEPEX
]) == 0) {
1266 SectType
= EFI_SECTION_SMM_DEPEX
;
1267 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_VERSION
]) == 0) {
1268 SectType
= EFI_SECTION_VERSION
;
1269 if (VersionNumber
< 0 || VersionNumber
> 9999) {
1270 Error (NULL
, 0, 1003, "Invalid option value", "%d is not in 0~9999", VersionNumber
);
1273 VerboseMsg ("Version section number is %d", VersionNumber
);
1274 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_USER_INTERFACE
]) == 0) {
1275 SectType
= EFI_SECTION_USER_INTERFACE
;
1276 if (StringBuffer
[0] == '\0') {
1277 Error (NULL
, 0, 1001, "Missing option", "user interface string");
1280 VerboseMsg ("UI section string name is %s", StringBuffer
);
1281 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPATIBILITY16
]) == 0) {
1282 SectType
= EFI_SECTION_COMPATIBILITY16
;
1283 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FIRMWARE_VOLUME_IMAGE
]) == 0) {
1284 SectType
= EFI_SECTION_FIRMWARE_VOLUME_IMAGE
;
1285 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FREEFORM_SUBTYPE_GUID
]) == 0) {
1286 SectType
= EFI_SECTION_FREEFORM_SUBTYPE_GUID
;
1287 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_RAW
]) == 0) {
1288 SectType
= EFI_SECTION_RAW
;
1289 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PEI_DEPEX
]) == 0) {
1290 SectType
= EFI_SECTION_PEI_DEPEX
;
1292 Error (NULL
, 0, 1003, "Invalid option value", "SectionType = %s", SectionName
);
1297 // GuidValue is only required by Guided section.
1299 if ((SectType
!= EFI_SECTION_GUID_DEFINED
) && (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1300 fprintf (stdout
, "Warning: the input guid value is not required for this section type %s\n", SectionName
);
1304 // Check whether there is input file
1306 if ((SectType
!= EFI_SECTION_VERSION
) && (SectType
!= EFI_SECTION_USER_INTERFACE
)) {
1308 // The input file are required for other section type.
1310 if (InputFileNum
== 0) {
1311 Error (NULL
, 0, 1001, "Missing options", "Input files");
1316 // Check whether there is output file
1318 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1319 VerboseMsg ("the %uth input file name is %s", (unsigned) Index
, InputFileName
[Index
]);
1321 if (OutputFileName
== NULL
) {
1322 Error (NULL
, 0, 1001, "Missing options", "Output file");
1324 // OutFile = stdout;
1326 VerboseMsg ("Output file name is %s", OutputFileName
);
1329 // At this point, we've fully validated the command line, and opened appropriate
1330 // files, so let's go and do what we've been asked to do...
1333 // Within this switch, build and write out the section header including any
1334 // section type specific pieces. If there's an input file, it's tacked on later
1337 case EFI_SECTION_COMPRESSION
:
1338 if (InputFileAlign
!= NULL
) {
1339 free (InputFileAlign
);
1340 InputFileAlign
= NULL
;
1342 Status
= GenSectionCompressionSection (
1351 case EFI_SECTION_GUID_DEFINED
:
1352 if (InputFileAlign
!= NULL
&& (CompareGuid (&VendorGuid
, &mEfiCrc32SectionGuid
) != 0)) {
1354 // Only process alignment for the default known CRC32 guided section.
1355 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
1357 free (InputFileAlign
);
1358 InputFileAlign
= NULL
;
1360 Status
= GenSectionGuidDefinedSection (
1366 (UINT32
) SectGuidHeaderLength
,
1371 case EFI_SECTION_VERSION
:
1372 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1374 // 2 bytes for the build number UINT16
1378 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1380 Index
+= (strlen (StringBuffer
) * 2) + 2;
1381 OutFileBuffer
= (UINT8
*) malloc (Index
);
1382 if (OutFileBuffer
== NULL
) {
1383 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1386 VersionSect
= (EFI_VERSION_SECTION
*) OutFileBuffer
;
1387 VersionSect
->CommonHeader
.Type
= SectType
;
1388 VersionSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1389 VersionSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1390 VersionSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1391 VersionSect
->BuildNumber
= (UINT16
) VersionNumber
;
1392 Ascii2UnicodeString (StringBuffer
, VersionSect
->VersionString
);
1393 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1396 case EFI_SECTION_USER_INTERFACE
:
1397 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1399 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1401 Index
+= (strlen (StringBuffer
) * 2) + 2;
1402 OutFileBuffer
= (UINT8
*) malloc (Index
);
1403 if (OutFileBuffer
== NULL
) {
1404 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1407 UiSect
= (EFI_USER_INTERFACE_SECTION
*) OutFileBuffer
;
1408 UiSect
->CommonHeader
.Type
= SectType
;
1409 UiSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1410 UiSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1411 UiSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1412 Ascii2UnicodeString (StringBuffer
, UiSect
->FileNameString
);
1413 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1416 case EFI_SECTION_ALL
:
1418 // read all input file contents into a buffer
1419 // first get the size of all file contents
1421 Status
= GetSectionContents (
1429 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1430 OutFileBuffer
= (UINT8
*) malloc (InputLength
);
1431 if (OutFileBuffer
== NULL
) {
1432 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1436 // read all input file contents into a buffer
1438 Status
= GetSectionContents (
1446 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength
);
1450 // All other section types are caught by default (they're all the same)
1452 Status
= GenSectionCommonLeafSection (
1461 if (Status
!= EFI_SUCCESS
|| OutFileBuffer
== NULL
) {
1462 Error (NULL
, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status
);
1467 // Get output file length
1469 if (SectType
!= EFI_SECTION_ALL
) {
1470 InputLength
= SECTION_SIZE (OutFileBuffer
);
1474 // Write the output file
1476 OutFile
= fopen (OutputFileName
, "wb");
1477 if (OutFile
== NULL
) {
1478 Error (NULL
, 0, 0001, "Error opening file for writing", OutputFileName
);
1482 fwrite (OutFileBuffer
, InputLength
, 1, OutFile
);
1485 if (InputFileName
!= NULL
) {
1486 free (InputFileName
);
1489 if (InputFileAlign
!= NULL
) {
1490 free (InputFileAlign
);
1493 if (OutFileBuffer
!= NULL
) {
1494 free (OutFileBuffer
);
1497 if (OutFile
!= NULL
) {
1501 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
1503 return GetUtilityStatus ();