3 Copyright (c) 2004 - 2010, 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>
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\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_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.
920 CHAR8
**InputFileName
;
921 CHAR8
*OutputFileName
;
923 CHAR8
*CompressionName
;
925 EFI_GUID VendorGuid
= mZeroGuid
;
928 UINT8 SectCompSubType
;
929 UINT16 SectGuidAttribute
;
930 UINT64 SectGuidHeaderLength
;
931 EFI_VERSION_SECTION
*VersionSect
;
932 EFI_USER_INTERFACE_SECTION
*UiSect
;
934 UINT8
*OutFileBuffer
;
937 UINT32
*InputFileAlign
;
938 UINT32 InputFileAlignNum
;
940 InputFileAlign
= NULL
;
941 InputFileAlignNum
= 0;
942 InputFileName
= NULL
;
943 OutputFileName
= NULL
;
945 CompressionName
= NULL
;
951 SectType
= EFI_SECTION_ALL
;
953 SectGuidAttribute
= EFI_GUIDED_SECTION_NONE
;
954 OutFileBuffer
= NULL
;
956 Status
= STATUS_SUCCESS
;
958 SectGuidHeaderLength
= 0;
962 SetUtilityName (UTILITY_NAME
);
965 Error (NULL
, 0, 1001, "Missing options", "No options input");
971 // Parse command line
976 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
979 return STATUS_SUCCESS
;
982 if (stricmp (argv
[0], "--version") == 0) {
984 return STATUS_SUCCESS
;
988 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--SectionType") == 0)) {
989 SectionName
= argv
[1];
990 if (SectionName
== NULL
) {
991 Error (NULL
, 0, 1003, "Invalid option value", "Section Type can't be NULL");
999 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
1000 OutputFileName
= argv
[1];
1001 if (OutputFileName
== NULL
) {
1002 Error (NULL
, 0, 1003, "Invalid option value", "Output file can't be NULL");
1010 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--compress") == 0)) {
1011 CompressionName
= argv
[1];
1012 if (CompressionName
== NULL
) {
1013 Error (NULL
, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
1021 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--vendor") == 0)) {
1022 Status
= StringToGuid (argv
[1], &VendorGuid
);
1023 if (EFI_ERROR (Status
)) {
1024 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1032 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--attributes") == 0)) {
1033 if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]) == 0) {
1034 SectGuidAttribute
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1035 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]) == 0) {
1036 SectGuidAttribute
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
1037 } else if (stricmp (argv
[1], mGUIDedSectionAttribue
[0]) == 0) {
1041 SectGuidAttribute
|= EFI_GUIDED_SECTION_NONE
;
1043 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1051 if ((stricmp (argv
[0], "-l") == 0) || (stricmp (argv
[0], "--HeaderLength") == 0)) {
1052 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &SectGuidHeaderLength
);
1053 if (EFI_ERROR (Status
)) {
1054 Error (NULL
, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv
[0], argv
[1]);
1062 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--name") == 0)) {
1063 StringBuffer
= argv
[1];
1064 if (StringBuffer
== NULL
) {
1065 Error (NULL
, 0, 1003, "Invalid option value", "Name can't be NULL");
1073 if ((stricmp (argv
[0], "-j") == 0) || (stricmp (argv
[0], "--buildnumber") == 0)) {
1074 if (argv
[1] == NULL
) {
1075 Error (NULL
, 0, 1003, "Invalid option value", "build number can't be NULL");
1079 // Verify string is a integrator number
1081 for (Index
= 0; Index
< strlen (argv
[1]); Index
++) {
1082 if ((argv
[1][Index
] != '-') && (isdigit ((int)argv
[1][Index
]) == 0)) {
1083 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1088 sscanf (argv
[1], "%d", &VersionNumber
);
1094 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
1095 SetPrintLevel (VERBOSE_LOG_LEVEL
);
1096 VerboseMsg ("Verbose output Mode Set!");
1102 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
1103 SetPrintLevel (KEY_LOG_LEVEL
);
1104 KeyMsg ("Quiet output Mode Set!");
1110 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
1111 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
1112 if (EFI_ERROR (Status
)) {
1113 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1117 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0~9, currnt input level is %d", (int) LogLevel
);
1120 SetPrintLevel (LogLevel
);
1121 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
1128 // Section File alignment requirement
1130 if (stricmp (argv
[0], "--sectionalign") == 0) {
1131 if (InputFileAlignNum
== 0) {
1132 InputFileAlign
= (UINT32
*) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1133 if (InputFileAlign
== NULL
) {
1134 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1137 memset (InputFileAlign
, 1, MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
1138 } else if (InputFileAlignNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1139 InputFileAlign
= (UINT32
*) realloc (
1141 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (UINT32
)
1144 if (InputFileAlign
== NULL
) {
1145 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1148 memset (&(InputFileAlign
[InputFileNum
]), 1, (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
)));
1151 Status
= StringtoAlignment (argv
[1], &(InputFileAlign
[InputFileAlignNum
]));
1152 if (EFI_ERROR (Status
)) {
1153 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
1158 InputFileAlignNum
++;
1163 // Get Input file name
1165 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
1166 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
1167 if (InputFileName
== NULL
) {
1168 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1171 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1172 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
1174 // InputFileName buffer too small, need to realloc
1176 InputFileName
= (CHAR8
**) realloc (
1178 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
1181 if (InputFileName
== NULL
) {
1182 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1185 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
1188 InputFileName
[InputFileNum
++] = argv
[0];
1193 if (InputFileAlignNum
> 0 && InputFileAlignNum
!= InputFileNum
) {
1194 Error (NULL
, 0, 1003, "Invalid option", "section alignment must be set for each section");
1198 VerboseMsg ("%s tool start.", UTILITY_NAME
);
1201 // Parse all command line parameters to get the corresponding section type.
1203 VerboseMsg ("Section type is %s", SectionName
);
1204 if (SectionName
== NULL
) {
1206 // No specified Section type, default is SECTION_ALL.
1208 SectType
= EFI_SECTION_ALL
;
1209 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPRESSION
]) == 0) {
1210 SectType
= EFI_SECTION_COMPRESSION
;
1211 if (CompressionName
== NULL
) {
1213 // Default is PI_STD compression algorithm.
1215 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1216 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_NOT_COMPRESSED
]) == 0) {
1217 SectCompSubType
= EFI_NOT_COMPRESSED
;
1218 } else if (stricmp (CompressionName
, mCompressionTypeName
[EFI_STANDARD_COMPRESSION
]) == 0) {
1219 SectCompSubType
= EFI_STANDARD_COMPRESSION
;
1221 Error (NULL
, 0, 1003, "Invalid option value", "--compress = %s", CompressionName
);
1224 VerboseMsg ("Compress method is %s", mCompressionTypeName
[SectCompSubType
]);
1225 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_GUID_DEFINED
]) == 0) {
1226 SectType
= EFI_SECTION_GUID_DEFINED
;
1228 if (CompareGuid (&VendorGuid
, &mZeroGuid
) == 0) {
1229 memcpy (&VendorGuid
, &mEfiCrc32SectionGuid
, sizeof (EFI_GUID
));
1232 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_NONE
) != 0) {
1234 // NONE attribute, clear attribute value.
1236 SectGuidAttribute
= SectGuidAttribute
& ~EFI_GUIDED_SECTION_NONE
;
1238 VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1239 (unsigned) VendorGuid
.Data1
,
1242 VendorGuid
.Data4
[0],
1243 VendorGuid
.Data4
[1],
1244 VendorGuid
.Data4
[2],
1245 VendorGuid
.Data4
[3],
1246 VendorGuid
.Data4
[4],
1247 VendorGuid
.Data4
[5],
1248 VendorGuid
.Data4
[6],
1249 VendorGuid
.Data4
[7]);
1250 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) {
1251 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_PROCESSING_REQUIRED
]);
1253 if ((SectGuidAttribute
& EFI_GUIDED_SECTION_AUTH_STATUS_VALID
) != 0) {
1254 VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue
[EFI_GUIDED_SECTION_AUTH_STATUS_VALID
]);
1256 if (SectGuidHeaderLength
!= 0) {
1257 VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength
);
1259 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PE32
]) == 0) {
1260 SectType
= EFI_SECTION_PE32
;
1261 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PIC
]) == 0) {
1262 SectType
= EFI_SECTION_PIC
;
1263 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_TE
]) == 0) {
1264 SectType
= EFI_SECTION_TE
;
1265 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_DXE_DEPEX
]) == 0) {
1266 SectType
= EFI_SECTION_DXE_DEPEX
;
1267 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_SMM_DEPEX
]) == 0) {
1268 SectType
= EFI_SECTION_SMM_DEPEX
;
1269 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_VERSION
]) == 0) {
1270 SectType
= EFI_SECTION_VERSION
;
1271 if (VersionNumber
< 0 || VersionNumber
> 9999) {
1272 Error (NULL
, 0, 1003, "Invalid option value", "%d is not in 0~9999", VersionNumber
);
1275 VerboseMsg ("Version section number is %d", VersionNumber
);
1276 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_USER_INTERFACE
]) == 0) {
1277 SectType
= EFI_SECTION_USER_INTERFACE
;
1278 if (StringBuffer
[0] == '\0') {
1279 Error (NULL
, 0, 1001, "Missing option", "user interface string");
1282 VerboseMsg ("UI section string name is %s", StringBuffer
);
1283 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_COMPATIBILITY16
]) == 0) {
1284 SectType
= EFI_SECTION_COMPATIBILITY16
;
1285 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FIRMWARE_VOLUME_IMAGE
]) == 0) {
1286 SectType
= EFI_SECTION_FIRMWARE_VOLUME_IMAGE
;
1287 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_FREEFORM_SUBTYPE_GUID
]) == 0) {
1288 SectType
= EFI_SECTION_FREEFORM_SUBTYPE_GUID
;
1289 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_RAW
]) == 0) {
1290 SectType
= EFI_SECTION_RAW
;
1291 } else if (stricmp (SectionName
, mSectionTypeName
[EFI_SECTION_PEI_DEPEX
]) == 0) {
1292 SectType
= EFI_SECTION_PEI_DEPEX
;
1294 Error (NULL
, 0, 1003, "Invalid option value", "SectionType = %s", SectionName
);
1299 // GuidValue is only required by Guided section.
1301 if ((SectType
!= EFI_SECTION_GUID_DEFINED
) && (CompareGuid (&VendorGuid
, &mZeroGuid
) != 0)) {
1302 fprintf (stdout
, "Warning: the input guid value is not required for this section type %s\n", SectionName
);
1306 // Check whether there is input file
1308 if ((SectType
!= EFI_SECTION_VERSION
) && (SectType
!= EFI_SECTION_USER_INTERFACE
)) {
1310 // The input file are required for other section type.
1312 if (InputFileNum
== 0) {
1313 Error (NULL
, 0, 1001, "Missing options", "Input files");
1318 // Check whether there is output file
1320 for (Index
= 0; Index
< InputFileNum
; Index
++) {
1321 VerboseMsg ("the %uth input file name is %s", (unsigned) Index
, InputFileName
[Index
]);
1323 if (OutputFileName
== NULL
) {
1324 Error (NULL
, 0, 1001, "Missing options", "Output file");
1326 // OutFile = stdout;
1328 VerboseMsg ("Output file name is %s", OutputFileName
);
1331 // At this point, we've fully validated the command line, and opened appropriate
1332 // files, so let's go and do what we've been asked to do...
1335 // Within this switch, build and write out the section header including any
1336 // section type specific pieces. If there's an input file, it's tacked on later
1339 case EFI_SECTION_COMPRESSION
:
1340 if (InputFileAlign
!= NULL
) {
1341 free (InputFileAlign
);
1342 InputFileAlign
= NULL
;
1344 Status
= GenSectionCompressionSection (
1353 case EFI_SECTION_GUID_DEFINED
:
1354 if (InputFileAlign
!= NULL
&& (CompareGuid (&VendorGuid
, &mEfiCrc32SectionGuid
) != 0)) {
1356 // Only process alignment for the default known CRC32 guided section.
1357 // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
1359 free (InputFileAlign
);
1360 InputFileAlign
= NULL
;
1362 Status
= GenSectionGuidDefinedSection (
1368 (UINT32
) SectGuidHeaderLength
,
1373 case EFI_SECTION_VERSION
:
1374 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1376 // 2 bytes for the build number UINT16
1380 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1382 Index
+= (strlen (StringBuffer
) * 2) + 2;
1383 OutFileBuffer
= (UINT8
*) malloc (Index
);
1384 if (OutFileBuffer
== NULL
) {
1385 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1388 VersionSect
= (EFI_VERSION_SECTION
*) OutFileBuffer
;
1389 VersionSect
->CommonHeader
.Type
= SectType
;
1390 VersionSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1391 VersionSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1392 VersionSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1393 VersionSect
->BuildNumber
= (UINT16
) VersionNumber
;
1394 Ascii2UnicodeString (StringBuffer
, VersionSect
->VersionString
);
1395 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1398 case EFI_SECTION_USER_INTERFACE
:
1399 Index
= sizeof (EFI_COMMON_SECTION_HEADER
);
1401 // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
1403 Index
+= (strlen (StringBuffer
) * 2) + 2;
1404 OutFileBuffer
= (UINT8
*) malloc (Index
);
1405 if (OutFileBuffer
== NULL
) {
1406 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1409 UiSect
= (EFI_USER_INTERFACE_SECTION
*) OutFileBuffer
;
1410 UiSect
->CommonHeader
.Type
= SectType
;
1411 UiSect
->CommonHeader
.Size
[0] = (UINT8
) (Index
& 0xff);
1412 UiSect
->CommonHeader
.Size
[1] = (UINT8
) ((Index
& 0xff00) >> 8);
1413 UiSect
->CommonHeader
.Size
[2] = (UINT8
) ((Index
& 0xff0000) >> 16);
1414 Ascii2UnicodeString (StringBuffer
, UiSect
->FileNameString
);
1415 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index
);
1418 case EFI_SECTION_ALL
:
1420 // read all input file contents into a buffer
1421 // first get the size of all file contents
1423 Status
= GetSectionContents (
1431 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1432 OutFileBuffer
= (UINT8
*) malloc (InputLength
);
1433 if (OutFileBuffer
== NULL
) {
1434 Error (NULL
, 0, 4001, "Resource", "memory cannot be allcoated");
1438 // read all input file contents into a buffer
1440 Status
= GetSectionContents (
1448 VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength
);
1452 // All other section types are caught by default (they're all the same)
1454 Status
= GenSectionCommonLeafSection (
1463 if (Status
!= EFI_SUCCESS
|| OutFileBuffer
== NULL
) {
1464 Error (NULL
, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status
);
1469 // Get output file length
1471 if (SectType
!= EFI_SECTION_ALL
) {
1472 InputLength
= SECTION_SIZE (OutFileBuffer
);
1476 // Write the output file
1478 OutFile
= fopen (OutputFileName
, "wb");
1479 if (OutFile
== NULL
) {
1480 Error (NULL
, 0, 0001, "Error opening file for writing", OutputFileName
);
1484 fwrite (OutFileBuffer
, InputLength
, 1, OutFile
);
1487 if (InputFileName
!= NULL
) {
1488 free (InputFileName
);
1491 if (InputFileAlign
!= NULL
) {
1492 free (InputFileAlign
);
1495 if (OutFileBuffer
!= NULL
) {
1496 free (OutFileBuffer
);
1499 if (OutFile
!= NULL
) {
1503 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
1505 return GetUtilityStatus ();