2019-09-03 11:58:42 +02:00
/** @file
Converts a pe32 + image to an FW , Te image type , or other specific image .
Copyright ( c ) 2004 - 2018 , Intel Corporation . All rights reserved . < BR >
SPDX - License - Identifier : BSD - 2 - Clause - Patent
* */
# include "WinNtInclude.h"
# ifndef __GNUC__
# include <windows.h>
# include <io.h>
# include <sys/types.h>
# include <sys/stat.h>
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <time.h>
# include <ctype.h>
# include <Common/UefiBaseTypes.h>
# include <IndustryStandard/PeImage.h>
# include <Common/UefiInternalFormRepresentation.h>
//
// Acpi Table definition
//
# include <IndustryStandard/Acpi.h>
# include <IndustryStandard/Acpi1_0.h>
# include <IndustryStandard/Acpi2_0.h>
# include <IndustryStandard/Acpi3_0.h>
# include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
# include "CommonLib.h"
# include "PeCoffLib.h"
# include "ParseInf.h"
# include "EfiUtilityMsgs.h"
# include "GenFw.h"
//
// Version of this utility
//
# define UTILITY_NAME "GenFw"
# define UTILITY_MAJOR_VERSION 0
# define UTILITY_MINOR_VERSION 2
# define HII_RESOURCE_SECTION_INDEX 1
# define HII_RESOURCE_SECTION_NAME "HII"
# define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
# define DEFAULT_MC_ALIGNMENT 16
# define STATUS_IGNORE 0xA
//
// Structure definition for a microcode header
//
typedef struct {
UINT32 HeaderVersion ;
UINT32 PatchId ;
UINT32 Date ;
UINT32 CpuId ;
UINT32 Checksum ;
UINT32 LoaderVersion ;
UINT32 PlatformId ;
UINT32 DataSize ; // if 0, then TotalSize = 2048, and TotalSize field is invalid
UINT32 TotalSize ; // number of bytes
UINT32 Reserved [ 3 ] ;
} MICROCODE_IMAGE_HEADER ;
static EFI_GUID mZeroGuid = { 0x0 , 0x0 , 0x0 , { 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 } } ;
static const char * gHiiPackageRCFileHeader [ ] = {
" // " ,
" // DO NOT EDIT -- auto-generated file " ,
" // " ,
NULL
} ;
//
// Module image information
//
CHAR8 * mInImageName ;
UINT32 mImageTimeStamp = 0 ;
UINT32 mImageSize = 0 ;
UINT32 mOutImageType = FW_DUMMY_IMAGE ;
BOOLEAN mIsConvertXip = FALSE ;
STATIC
EFI_STATUS
ZeroDebugData (
IN OUT UINT8 * FileBuffer ,
BOOLEAN ZeroDebug
) ;
STATIC
EFI_STATUS
SetStamp (
IN OUT UINT8 * FileBuffer ,
IN CHAR8 * TimeStamp
) ;
STATIC
STATUS
MicrocodeReadData (
FILE * InFptr ,
UINT32 * Data
) ;
STATIC
VOID
Version (
VOID
)
/*++
Routine Description :
Print out version information for this utility .
Arguments :
None
Returns :
None
- - */
{
fprintf ( stdout , " %s Version %d.%d %s \n " , UTILITY_NAME , UTILITY_MAJOR_VERSION , UTILITY_MINOR_VERSION , __BUILD_VERSION ) ;
}
STATIC
VOID
Usage (
VOID
)
/*++
Routine Description :
Print Help message .
Arguments :
VOID
Returns :
None
- - */
{
//
// Summary usage
//
fprintf ( stdout , " \n Usage: %s [options] <input_file> \n \n " , UTILITY_NAME ) ;
//
// Copyright declaration
//
fprintf ( stdout , " Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved. \n \n " ) ;
//
// Details Option
//
fprintf ( stdout , " Options: \n " ) ;
fprintf ( stdout , " -o FileName, --outputfile FileName \n \
File will be created to store the output content . \ n " );
fprintf ( stdout , " -e EFI_FILETYPE, --efiImage EFI_FILETYPE \n \
Create Efi Image . EFI_FILETYPE is one of BASE , SMM_CORE , \ n \
PEI_CORE , PEIM , DXE_CORE , DXE_DRIVER , UEFI_APPLICATION , \ n \
SEC , DXE_SAL_DRIVER , UEFI_DRIVER , DXE_RUNTIME_DRIVER , \ n \
DXE_SMM_DRIVER , SECURITY_CORE , COMBINED_PEIM_DRIVER , \ n \
MM_STANDALONE , MM_CORE_STANDALONE , \ n \
PIC_PEIM , RELOCATABLE_PEIM , BS_DRIVER , RT_DRIVER , \ n \
APPLICATION , SAL_RT_DRIVER to support all module types \ n \
It can only be used together with - - keepexceptiontable , \ n \
- - keepzeropending , - - keepoptionalheader , - r , - o option . \ n \
It is a action option . If it is combined with other action options , \ n \
the later input action option will override the previous one . \ n " );
fprintf ( stdout , " -c, --acpi Create Acpi table. \n \
It can ' t be combined with other action options \ n \
except for - o , - r option . It is a action option . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );
fprintf ( stdout , " -t, --terse Create Te Image. \n \
It can only be used together with - - keepexceptiontable , \ n \
- - keepzeropending , - - keepoptionalheader , - r , - o option . \ n \
It is a action option . If it is combined with other action options , \ n \
the later input action option will override the previous one . \ n " );
fprintf ( stdout , " -u, --dump Dump TeImage Header. \n \
It can ' t be combined with other action options \ n \
except for - o , - r option . It is a action option . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );
fprintf ( stdout , " -z, --zero Zero the Debug Data Fields in the PE input image file. \n \
It also zeros the time stamp fields . \ n \
This option can be used to compare the binary efi image . \ n \
It can ' t be combined with other action options \ n \
except for - o , - r option . It is a action option . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );
fprintf ( stdout , " -b, --exe2bin Convert the input EXE to the output BIN file. \n \
It can ' t be combined with other action options \ n \
except for - o , - r option . It is a action option . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );;
fprintf ( stdout , " -l, --stripped Strip off the relocation info from PE or TE image. \n \
It can ' t be combined with other action options \ n \
except for - o , - r option . It is a action option . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );
fprintf ( stdout , " -s timedate, --stamp timedate \n \
timedate format is \ " yyyy-mm-dd 00:00:00 \" . if timedata \n \
is set to NOW , current system time is used . The support \ n \
date scope is 1970 - 01 - 01 00 + timezone : 00 : 00 \ n \
~ 2038 - 01 - 19 03 + timezone : 14 : 07 \ n \
The scope is adjusted according to the different zones . \ n \
It can ' t be combined with other action options \ n \
except for - o , - r option . It is a action option . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );
fprintf ( stdout , " -m, --mcifile Convert input microcode txt file to microcode bin file. \n \
It can ' t be combined with other action options \ n \
except for - o option . It is a action option . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );
fprintf ( stdout , " -j, --join Combine multi microcode bin files to one file. \n \
It can be specified with - a , - p , - o option . \ n \
No other options can be combined with it . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );
fprintf ( stdout , " -a NUM, --align NUM NUM is one HEX or DEC format alignment value. \n \
This option is only used together with - j option . \ n " );
fprintf ( stdout , " -p NUM, --pad NUM NUM is one HEX or DEC format padding value. \n \
This option is only used together with - j option . \ n " );
fprintf ( stdout , " --keepexceptiontable Don't clear exception table. \n \
This option can be used together with - e or - t . \ n \
It doesn ' t work for other options . \ n " );
fprintf ( stdout , " --keepoptionalheader Don't zero PE/COFF optional header fields. \n \
This option can be used together with - e or - t . \ n \
It doesn ' t work for other options . \ n " );
fprintf ( stdout , " --keepzeropending Don't strip zero pending of .reloc. \n \
This option can be used together with - e or - t . \ n \
It doesn ' t work for other options . \ n " );
fprintf ( stdout , " -r, --replace Overwrite the input file with the output content. \n \
If more input files are specified , \ n \
the last input file will be as the output file . \ n " );
fprintf ( stdout , " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid \n \
Guid is used to specify hii package list guid . \ n \
Its format is xxxxxxxx - xxxx - xxxx - xxxx - xxxxxxxxxxxx \ n \
If not specified , the first Form FormSet guid is used . \ n " );
fprintf ( stdout , " --hiipackage Combine all input binary hii packages into \n \
a single package list as the text resource data ( RC ) . \ n \
It can ' t be combined with other action options \ n \
except for - o option . It is a action option . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );
fprintf ( stdout , " --hiibinpackage Combine all input binary hii packages into \n \
a single package list as the binary resource section . \ n \
It can ' t be combined with other action options \ n \
except for - o option . It is a action option . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );
fprintf ( stdout , " --rebase NewAddress Rebase image to new base address. New address \n \
is also set to the first none code section header . \ n \
It can ' t be combined with other action options \ n \
except for - o or - r option . It is a action option . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );
fprintf ( stdout , " --address NewAddress Set new address into the first none code \n \
section header of the input image . \ n \
It can ' t be combined with other action options \ n \
except for - o or - r option . It is a action option . \ n \
If it is combined with other action options , the later \ n \
input action option will override the previous one . \ n " );
fprintf ( stdout , " -v, --verbose Turn on verbose output with informational messages. \n " ) ;
fprintf ( stdout , " -q, --quiet Disable all messages except key message and fatal error \n " ) ;
fprintf ( stdout , " -d, --debug level Enable debug messages, at input debug level. \n " ) ;
fprintf ( stdout , " --version Show program's version number and exit \n " ) ;
fprintf ( stdout , " -h, --help Show this help message and exit \n " ) ;
}
STATIC
STATUS
CheckAcpiTable (
VOID * AcpiTable ,
UINT32 Length
)
/*++
Routine Description :
Check Acpi Table
Arguments :
AcpiTable Buffer for AcpiSection
Length AcpiSection Length
Returns :
0 success
non - zero otherwise
- - */
{
EFI_ACPI_DESCRIPTION_HEADER * AcpiHeader ;
EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * Facs ;
UINT32 ExpectedLength ;
AcpiHeader = ( EFI_ACPI_DESCRIPTION_HEADER * ) AcpiTable ;
//
// Generic check for AcpiTable length.
//
if ( AcpiHeader - > Length > Length ) {
Error ( NULL , 0 , 3000 , " Invalid " , " AcpiTable length check failed. " , NULL ) ;
return STATUS_ERROR ;
}
//
// Currently, we only check must-have tables: FADT, FACS, DSDT,
// and some important tables: MADT, MCFG.
//
switch ( AcpiHeader - > Signature ) {
//
// "FACP" Fixed ACPI Description Table
//
case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE :
switch ( AcpiHeader - > Revision ) {
case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION :
ExpectedLength = sizeof ( EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE ) ;
break ;
case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION :
ExpectedLength = sizeof ( EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE ) ;
break ;
case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION :
ExpectedLength = sizeof ( EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE ) ;
break ;
default :
if ( AcpiHeader - > Revision > EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION ) {
ExpectedLength = AcpiHeader - > Length ;
break ;
}
Error ( NULL , 0 , 3000 , " Invalid " , " FACP revision check failed. " ) ;
return STATUS_ERROR ;
}
if ( ExpectedLength ! = AcpiHeader - > Length ) {
Error ( NULL , 0 , 3000 , " Invalid " , " FACP length check failed. " ) ;
return STATUS_ERROR ;
}
break ;
//
// "FACS" Firmware ACPI Control Structure
//
case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE :
Facs = ( EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE * ) AcpiTable ;
if ( Facs - > Version > EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION ) {
break ;
}
if ( ( Facs - > Version ! = EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION ) & &
( Facs - > Version ! = EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION ) & &
( Facs - > Version ! = EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " FACS version check failed. " ) ;
return STATUS_ERROR ;
}
if ( ( Facs - > Length ! = sizeof ( EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE ) ) & &
( Facs - > Length ! = sizeof ( EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE ) ) & &
( Facs - > Length ! = sizeof ( EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE ) ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " FACS length check failed. " ) ;
return STATUS_ERROR ;
}
break ;
//
// "DSDT" Differentiated System Description Table
//
case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE :
if ( AcpiHeader - > Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION ) {
break ;
}
if ( AcpiHeader - > Length < = sizeof ( EFI_ACPI_DESCRIPTION_HEADER ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " DSDT length check failed. " ) ;
return STATUS_ERROR ;
}
break ;
//
// "APIC" Multiple APIC Description Table
//
case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE :
if ( AcpiHeader - > Revision > EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION ) {
break ;
}
if ( ( AcpiHeader - > Revision ! = EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION ) & &
( AcpiHeader - > Revision ! = EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION ) & &
( AcpiHeader - > Revision ! = EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " APIC revision check failed. " ) ;
return STATUS_ERROR ;
}
if ( AcpiHeader - > Length < = sizeof ( EFI_ACPI_DESCRIPTION_HEADER ) + sizeof ( UINT32 ) + sizeof ( UINT32 ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " APIC length check failed. " ) ;
return STATUS_ERROR ;
}
break ;
//
// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
//
case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE :
if ( AcpiHeader - > Revision > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION ) {
break ;
}
if ( AcpiHeader - > Revision ! = EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION ) {
Error ( NULL , 0 , 3000 , " Invalid " , " MCFG revision check failed. " ) ;
return STATUS_ERROR ;
}
if ( AcpiHeader - > Length < = sizeof ( EFI_ACPI_DESCRIPTION_HEADER ) + sizeof ( UINT64 ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " MCFG length check failed. " ) ;
return STATUS_ERROR ;
}
break ;
//
// Other table pass check
//
default :
break ;
}
return STATUS_SUCCESS ;
}
VOID
SetHiiResourceHeader (
UINT8 * HiiBinData ,
UINT32 OffsetToFile
)
{
UINT32 Index ;
EFI_IMAGE_RESOURCE_DIRECTORY * ResourceDirectory ;
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY * ResourceDirectoryEntry ;
EFI_IMAGE_RESOURCE_DIRECTORY_STRING * ResourceDirectoryString ;
EFI_IMAGE_RESOURCE_DATA_ENTRY * ResourceDataEntry ;
//
// Fill Resource section entry
//
ResourceDirectory = ( EFI_IMAGE_RESOURCE_DIRECTORY * ) ( HiiBinData ) ;
ResourceDirectoryEntry = ( EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY * ) ( ResourceDirectory + 1 ) ;
for ( Index = 0 ; Index < ResourceDirectory - > NumberOfNamedEntries ; Index + + ) {
if ( ResourceDirectoryEntry - > u1 . s . NameIsString ) {
ResourceDirectoryString = ( EFI_IMAGE_RESOURCE_DIRECTORY_STRING * ) ( HiiBinData + ResourceDirectoryEntry - > u1 . s . NameOffset ) ;
if ( ResourceDirectoryString - > Length = = 3 & &
ResourceDirectoryString - > String [ 0 ] = = L ' H ' & &
ResourceDirectoryString - > String [ 1 ] = = L ' I ' & &
ResourceDirectoryString - > String [ 2 ] = = L ' I ' ) {
//
// Resource Type "HII" found
//
if ( ResourceDirectoryEntry - > u2 . s . DataIsDirectory ) {
//
// Move to next level - resource Name
//
ResourceDirectory = ( EFI_IMAGE_RESOURCE_DIRECTORY * ) ( HiiBinData + ResourceDirectoryEntry - > u2 . s . OffsetToDirectory ) ;
ResourceDirectoryEntry = ( EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY * ) ( ResourceDirectory + 1 ) ;
if ( ResourceDirectoryEntry - > u2 . s . DataIsDirectory ) {
//
// Move to next level - resource Language
//
ResourceDirectory = ( EFI_IMAGE_RESOURCE_DIRECTORY * ) ( HiiBinData + ResourceDirectoryEntry - > u2 . s . OffsetToDirectory ) ;
ResourceDirectoryEntry = ( EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY * ) ( ResourceDirectory + 1 ) ;
}
}
//
// Now it ought to be resource Data and update its OffsetToData value
//
if ( ! ResourceDirectoryEntry - > u2 . s . DataIsDirectory ) {
ResourceDataEntry = ( EFI_IMAGE_RESOURCE_DATA_ENTRY * ) ( HiiBinData + ResourceDirectoryEntry - > u2 . OffsetToData ) ;
ResourceDataEntry - > OffsetToData = ResourceDataEntry - > OffsetToData + OffsetToFile ;
break ;
}
}
}
ResourceDirectoryEntry + + ;
}
return ;
}
EFI_IMAGE_OPTIONAL_HEADER_UNION *
GetPeCoffHeader (
void * Data
)
{
EFI_IMAGE_DOS_HEADER * DosHdr ;
EFI_IMAGE_OPTIONAL_HEADER_UNION * PeHdr ;
//
// Read the dos & pe hdrs of the image
//
DosHdr = ( EFI_IMAGE_DOS_HEADER * ) Data ;
if ( DosHdr - > e_magic ! = EFI_IMAGE_DOS_SIGNATURE ) {
// NO DOS header, check for PE/COFF header
PeHdr = ( EFI_IMAGE_OPTIONAL_HEADER_UNION * ) ( Data ) ;
if ( PeHdr - > Pe32 . Signature ! = EFI_IMAGE_NT_SIGNATURE ) {
return NULL ;
}
} else {
PeHdr = ( EFI_IMAGE_OPTIONAL_HEADER_UNION * ) ( ( ( UINT8 * ) Data ) + DosHdr - > e_lfanew ) ;
if ( PeHdr - > Pe32 . Signature ! = EFI_IMAGE_NT_SIGNATURE ) {
return NULL ;
}
}
return PeHdr ;
}
void
PeCoffConvertImageToXip (
UINT8 * * FileBuffer ,
UINT32 * FileLength
)
{
EFI_IMAGE_OPTIONAL_HEADER_UNION * PeHdr ;
EFI_IMAGE_OPTIONAL_HEADER_UNION * NewPeHdr ;
EFI_IMAGE_SECTION_HEADER * SectionHeader ;
UINTN TotalNecessaryFileSize ;
UINTN SectionSize ;
UINT8 * XipFile ;
UINT32 XipLength ;
UINTN Index ;
UINTN FirstSectionOffset ;
BOOLEAN ConversionNeeded ;
PeHdr = GetPeCoffHeader ( ( void * ) * FileBuffer ) ;
if ( PeHdr = = NULL ) {
return ;
}
if ( PeHdr - > Pe32 . OptionalHeader . SectionAlignment ! = PeHdr - > Pe32 . OptionalHeader . FileAlignment ) {
//
// The only reason to expand zero fill sections is to make them compatible with XIP images.
// If SectionAlignment is not equal to FileAlignment then it is not an XIP type image.
//
return ;
}
//
// Calculate size of XIP file, and determine if the conversion is needed.
//
ConversionNeeded = FALSE ;
XipLength = 0 ;
FirstSectionOffset = * FileLength ;
TotalNecessaryFileSize = 0 ;
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) & ( PeHdr - > Pe32 . OptionalHeader ) + PeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) ;
for ( Index = 0 ; Index < PeHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + , SectionHeader + + ) {
SectionSize = MAX ( SectionHeader - > Misc . VirtualSize , SectionHeader - > SizeOfRawData ) ;
TotalNecessaryFileSize + = SectionSize ;
if ( SectionSize > 0 ) {
FirstSectionOffset = MIN ( FirstSectionOffset , SectionHeader - > VirtualAddress ) ;
XipLength = MAX ( XipLength , SectionHeader - > VirtualAddress + SectionSize ) ;
if ( SectionHeader - > VirtualAddress ! = SectionHeader - > PointerToRawData ) {
ConversionNeeded = TRUE ;
}
}
if ( SectionHeader - > Misc . VirtualSize > SectionHeader - > SizeOfRawData ) {
ConversionNeeded = TRUE ;
}
}
if ( FirstSectionOffset < PeHdr - > Pe32 . OptionalHeader . SizeOfHeaders ) {
//
// If one of the sections should be loaded to an offset overlapping with
// the executable header, then it cannot be made into an XIP image.
//
VerboseMsg ( " PE/COFF conversion to XIP is impossible due to overlap " ) ;
VerboseMsg ( " of section data with the executable header. " ) ;
return ;
}
if ( FirstSectionOffset = = * FileLength ) {
//
// If we never found a section with a non-zero size, then we
// skip the conversion.
//
return ;
}
TotalNecessaryFileSize + = FirstSectionOffset ;
if ( ! ConversionNeeded ) {
return ;
}
if ( XipLength > ( 2 * TotalNecessaryFileSize ) ) {
VerboseMsg ( " PE/COFF conversion to XIP appears to be larger than necessary. " ) ;
VerboseMsg ( " The image linking process may have left unused memory ranges. " ) ;
}
if ( PeHdr - > Pe32 . FileHeader . PointerToSymbolTable ! = 0 ) {
//
// This field is obsolete and should be zero
//
PeHdr - > Pe32 . FileHeader . PointerToSymbolTable = 0 ;
}
//
// Allocate the extra space that we need to grow the image
//
XipFile = malloc ( XipLength ) ;
if ( XipFile = = NULL ) {
Error ( NULL , 0 , 4001 , " Resource " , " memory cannot be allocated! " ) ;
return ;
}
memset ( XipFile , 0 , XipLength ) ;
//
// Copy the file headers
//
memcpy ( XipFile , * FileBuffer , PeHdr - > Pe32 . OptionalHeader . SizeOfHeaders ) ;
NewPeHdr = GetPeCoffHeader ( ( void * ) XipFile ) ;
if ( NewPeHdr = = NULL ) {
free ( XipFile ) ;
return ;
}
//
// Copy the section data over to the appropriate XIP offsets
//
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) & ( NewPeHdr - > Pe32 . OptionalHeader ) + NewPeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) ;
for ( Index = 0 ; Index < PeHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + , SectionHeader + + ) {
if ( SectionHeader - > SizeOfRawData > 0 ) {
memcpy (
XipFile + SectionHeader - > VirtualAddress ,
* FileBuffer + SectionHeader - > PointerToRawData ,
SectionHeader - > SizeOfRawData
) ;
}
//
// Make the size of raw data in section header alignment.
//
SectionHeader - > SizeOfRawData = ( SectionHeader - > Misc . VirtualSize + PeHdr - > Pe32 . OptionalHeader . FileAlignment - 1 ) & ( ~ ( PeHdr - > Pe32 . OptionalHeader . FileAlignment - 1 ) ) ;
SectionHeader - > PointerToRawData = SectionHeader - > VirtualAddress ;
}
free ( * FileBuffer ) ;
* FileLength = XipLength ;
* FileBuffer = XipFile ;
mIsConvertXip = TRUE ;
}
UINT8 *
CreateHiiResouceSectionHeader (
UINT32 * pSectionHeaderSize ,
UINT32 HiiDataSize
)
/*++
Routine Description :
Create COFF resource section header
Arguments :
pSectionHeaderSize - Pointer to section header size .
HiiDataSize - Size of the total HII data in section .
Returns :
The created section header buffer .
- - */
{
UINT32 HiiSectionHeaderSize ;
UINT32 HiiSectionOffset ;
UINT8 * HiiSectionHeader ;
EFI_IMAGE_RESOURCE_DIRECTORY * ResourceDirectory ;
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY * TypeResourceDirectoryEntry ;
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY * NameResourceDirectoryEntry ;
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY * LanguageResourceDirectoryEntry ;
EFI_IMAGE_RESOURCE_DIRECTORY_STRING * ResourceDirectoryString ;
EFI_IMAGE_RESOURCE_DATA_ENTRY * ResourceDataEntry ;
//
// Calculate the total size for the resource header (include Type, Name and Language)
// then allocate memory for the resource header.
//
HiiSectionHeaderSize = 3 * ( sizeof ( EFI_IMAGE_RESOURCE_DIRECTORY ) + sizeof ( EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY ) )
+ 3 * ( sizeof ( UINT16 ) + 3 * sizeof ( CHAR16 ) )
+ sizeof ( EFI_IMAGE_RESOURCE_DATA_ENTRY ) ;
HiiSectionHeader = malloc ( HiiSectionHeaderSize ) ;
if ( HiiSectionHeader = = NULL ) {
Error ( NULL , 0 , 4001 , " Resource " , " memory cannot be allocated! " ) ;
return NULL ;
}
memset ( HiiSectionHeader , 0 , HiiSectionHeaderSize ) ;
HiiSectionOffset = 0 ;
//
// Create Type entry
//
ResourceDirectory = ( EFI_IMAGE_RESOURCE_DIRECTORY * ) ( HiiSectionHeader + HiiSectionOffset ) ;
HiiSectionOffset + = sizeof ( EFI_IMAGE_RESOURCE_DIRECTORY ) ;
ResourceDirectory - > NumberOfNamedEntries = 1 ;
TypeResourceDirectoryEntry = ( EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY * ) ( HiiSectionHeader + HiiSectionOffset ) ;
HiiSectionOffset + = sizeof ( EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY ) ;
TypeResourceDirectoryEntry - > u1 . s . NameIsString = 1 ;
TypeResourceDirectoryEntry - > u2 . s . DataIsDirectory = 1 ;
TypeResourceDirectoryEntry - > u2 . s . OffsetToDirectory = HiiSectionOffset ;
//
// Create Name entry
//
ResourceDirectory = ( EFI_IMAGE_RESOURCE_DIRECTORY * ) ( HiiSectionHeader + HiiSectionOffset ) ;
HiiSectionOffset + = sizeof ( EFI_IMAGE_RESOURCE_DIRECTORY ) ;
ResourceDirectory - > NumberOfNamedEntries = 1 ;
NameResourceDirectoryEntry = ( EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY * ) ( HiiSectionHeader + HiiSectionOffset ) ;
HiiSectionOffset + = sizeof ( EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY ) ;
NameResourceDirectoryEntry - > u1 . s . NameIsString = 1 ;
NameResourceDirectoryEntry - > u2 . s . DataIsDirectory = 1 ;
NameResourceDirectoryEntry - > u2 . s . OffsetToDirectory = HiiSectionOffset ;
//
// Create Language entry
//
ResourceDirectory = ( EFI_IMAGE_RESOURCE_DIRECTORY * ) ( HiiSectionHeader + HiiSectionOffset ) ;
HiiSectionOffset + = sizeof ( EFI_IMAGE_RESOURCE_DIRECTORY ) ;
ResourceDirectory - > NumberOfNamedEntries = 1 ;
LanguageResourceDirectoryEntry = ( EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY * ) ( HiiSectionHeader + HiiSectionOffset ) ;
HiiSectionOffset + = sizeof ( EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY ) ;
LanguageResourceDirectoryEntry - > u1 . s . NameIsString = 1 ;
//
// Create string entry for Type
//
TypeResourceDirectoryEntry - > u1 . s . NameOffset = HiiSectionOffset ;
ResourceDirectoryString = ( EFI_IMAGE_RESOURCE_DIRECTORY_STRING * ) ( HiiSectionHeader + HiiSectionOffset ) ;
ResourceDirectoryString - > Length = 3 ;
ResourceDirectoryString - > String [ 0 ] = L ' H ' ;
ResourceDirectoryString - > String [ 1 ] = L ' I ' ;
ResourceDirectoryString - > String [ 2 ] = L ' I ' ;
HiiSectionOffset = HiiSectionOffset + sizeof ( ResourceDirectoryString - > Length ) + ResourceDirectoryString - > Length * sizeof ( ResourceDirectoryString - > String [ 0 ] ) ;
//
// Create string entry for Name
//
NameResourceDirectoryEntry - > u1 . s . NameOffset = HiiSectionOffset ;
ResourceDirectoryString = ( EFI_IMAGE_RESOURCE_DIRECTORY_STRING * ) ( HiiSectionHeader + HiiSectionOffset ) ;
ResourceDirectoryString - > Length = 3 ;
ResourceDirectoryString - > String [ 0 ] = L ' E ' ;
ResourceDirectoryString - > String [ 1 ] = L ' F ' ;
ResourceDirectoryString - > String [ 2 ] = L ' I ' ;
HiiSectionOffset = HiiSectionOffset + sizeof ( ResourceDirectoryString - > Length ) + ResourceDirectoryString - > Length * sizeof ( ResourceDirectoryString - > String [ 0 ] ) ;
//
// Create string entry for Language
//
LanguageResourceDirectoryEntry - > u1 . s . NameOffset = HiiSectionOffset ;
ResourceDirectoryString = ( EFI_IMAGE_RESOURCE_DIRECTORY_STRING * ) ( HiiSectionHeader + HiiSectionOffset ) ;
ResourceDirectoryString - > Length = 3 ;
ResourceDirectoryString - > String [ 0 ] = L ' B ' ;
ResourceDirectoryString - > String [ 1 ] = L ' I ' ;
ResourceDirectoryString - > String [ 2 ] = L ' N ' ;
HiiSectionOffset = HiiSectionOffset + sizeof ( ResourceDirectoryString - > Length ) + ResourceDirectoryString - > Length * sizeof ( ResourceDirectoryString - > String [ 0 ] ) ;
//
// Create Leaf data
//
LanguageResourceDirectoryEntry - > u2 . OffsetToData = HiiSectionOffset ;
ResourceDataEntry = ( EFI_IMAGE_RESOURCE_DATA_ENTRY * ) ( HiiSectionHeader + HiiSectionOffset ) ;
HiiSectionOffset + = sizeof ( EFI_IMAGE_RESOURCE_DATA_ENTRY ) ;
ResourceDataEntry - > OffsetToData = HiiSectionOffset ;
ResourceDataEntry - > Size = HiiDataSize ;
* pSectionHeaderSize = HiiSectionHeaderSize ;
return HiiSectionHeader ;
}
EFI_STATUS
RebaseImageRead (
IN VOID * FileHandle ,
IN UINTN FileOffset ,
IN OUT UINT32 * ReadSize ,
OUT VOID * Buffer
)
/*++
Routine Description :
Support routine for the PE / COFF Loader that reads a buffer from a PE / COFF file
Arguments :
FileHandle - The handle to the PE / COFF file
FileOffset - The offset , in bytes , into the file to read
ReadSize - The number of bytes to read from the file starting at FileOffset
Buffer - A pointer to the buffer to read the data into .
Returns :
EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE / COFF file starting at FileOffset
- - */
{
CHAR8 * Destination8 ;
CHAR8 * Source8 ;
UINT32 Length ;
Destination8 = Buffer ;
Source8 = ( CHAR8 * ) ( ( UINTN ) FileHandle + FileOffset ) ;
Length = * ReadSize ;
while ( Length - - ) {
* ( Destination8 + + ) = * ( Source8 + + ) ;
}
return EFI_SUCCESS ;
}
EFI_STATUS
SetAddressToSectionHeader (
IN CHAR8 * FileName ,
IN OUT UINT8 * FileBuffer ,
IN UINT64 NewPe32BaseAddress
)
/*++
Routine Description :
Set new base address into the section header of PeImage
Arguments :
FileName - Name of file
FileBuffer - Pointer to PeImage .
NewPe32BaseAddress - New Base Address for PE image .
Returns :
EFI_SUCCESS Set new base address into this image successfully .
- - */
{
EFI_STATUS Status ;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext ;
UINTN Index ;
EFI_IMAGE_OPTIONAL_HEADER_UNION * ImgHdr ;
EFI_IMAGE_SECTION_HEADER * SectionHeader ;
//
// Initialize context
//
memset ( & ImageContext , 0 , sizeof ( ImageContext ) ) ;
ImageContext . Handle = ( VOID * ) FileBuffer ;
ImageContext . ImageRead = ( PE_COFF_LOADER_READ_FILE ) RebaseImageRead ;
Status = PeCoffLoaderGetImageInfo ( & ImageContext ) ;
if ( EFI_ERROR ( Status ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " The input PeImage %s is not valid " , FileName ) ;
return Status ;
}
if ( ImageContext . RelocationsStripped ) {
Error ( NULL , 0 , 3000 , " Invalid " , " The input PeImage %s has no relocation to be fixed up " , FileName ) ;
return Status ;
}
//
// Get PeHeader pointer
//
ImgHdr = ( EFI_IMAGE_OPTIONAL_HEADER_UNION * ) ( FileBuffer + ImageContext . PeCoffHeaderOffset ) ;
//
// Get section header list
//
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) (
( UINTN ) ImgHdr +
sizeof ( UINT32 ) +
sizeof ( EFI_IMAGE_FILE_HEADER ) +
ImgHdr - > Pe32 . FileHeader . SizeOfOptionalHeader
) ;
//
// Set base address into the first section header that doesn't point to code section.
//
for ( Index = 0 ; Index < ImgHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + , SectionHeader + + ) {
if ( ( SectionHeader - > Characteristics & EFI_IMAGE_SCN_CNT_CODE ) = = 0 ) {
* ( UINT64 * ) & SectionHeader - > PointerToRelocations = NewPe32BaseAddress ;
break ;
}
}
//
// BaseAddress is set to section header.
//
return EFI_SUCCESS ;
}
EFI_STATUS
RebaseImage (
IN CHAR8 * FileName ,
IN OUT UINT8 * FileBuffer ,
IN UINT64 NewPe32BaseAddress
)
/*++
Routine Description :
Set new base address into PeImage , and fix up PeImage based on new address .
Arguments :
FileName - Name of file
FileBuffer - Pointer to PeImage .
NewPe32BaseAddress - New Base Address for PE image .
Returns :
EFI_INVALID_PARAMETER - BaseAddress is not valid .
EFI_SUCCESS - Update PeImage is correctly .
- - */
{
EFI_STATUS Status ;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext ;
UINTN Index ;
EFI_IMAGE_OPTIONAL_HEADER_UNION * ImgHdr ;
UINT8 * MemoryImagePointer ;
EFI_IMAGE_SECTION_HEADER * SectionHeader ;
//
// Initialize context
//
memset ( & ImageContext , 0 , sizeof ( ImageContext ) ) ;
ImageContext . Handle = ( VOID * ) FileBuffer ;
ImageContext . ImageRead = ( PE_COFF_LOADER_READ_FILE ) RebaseImageRead ;
Status = PeCoffLoaderGetImageInfo ( & ImageContext ) ;
if ( EFI_ERROR ( Status ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " The input PeImage %s is not valid " , FileName ) ;
return Status ;
}
if ( ImageContext . RelocationsStripped ) {
Error ( NULL , 0 , 3000 , " Invalid " , " The input PeImage %s has no relocation to be fixed up " , FileName ) ;
return Status ;
}
//
// Get PeHeader pointer
//
ImgHdr = ( EFI_IMAGE_OPTIONAL_HEADER_UNION * ) ( FileBuffer + ImageContext . PeCoffHeaderOffset ) ;
//
// Load and Relocate Image Data
//
MemoryImagePointer = ( UINT8 * ) malloc ( ( UINTN ) ImageContext . ImageSize + ImageContext . SectionAlignment ) ;
if ( MemoryImagePointer = = NULL ) {
Error ( NULL , 0 , 4001 , " Resource " , " memory cannot be allocated on rebase of %s " , FileName ) ;
return EFI_OUT_OF_RESOURCES ;
}
memset ( ( VOID * ) MemoryImagePointer , 0 , ( UINTN ) ImageContext . ImageSize + ImageContext . SectionAlignment ) ;
ImageContext . ImageAddress = ( ( UINTN ) MemoryImagePointer + ImageContext . SectionAlignment - 1 ) & ( ~ ( ( INT64 ) ImageContext . SectionAlignment - 1 ) ) ;
Status = PeCoffLoaderLoadImage ( & ImageContext ) ;
if ( EFI_ERROR ( Status ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " LocateImage() call failed on rebase of %s " , FileName ) ;
free ( ( VOID * ) MemoryImagePointer ) ;
return Status ;
}
ImageContext . DestinationAddress = NewPe32BaseAddress ;
Status = PeCoffLoaderRelocateImage ( & ImageContext ) ;
if ( EFI_ERROR ( Status ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " RelocateImage() call failed on rebase of %s " , FileName ) ;
free ( ( VOID * ) MemoryImagePointer ) ;
return Status ;
}
//
// Copy Relocated data to raw image file.
//
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) (
( UINTN ) ImgHdr +
sizeof ( UINT32 ) +
sizeof ( EFI_IMAGE_FILE_HEADER ) +
ImgHdr - > Pe32 . FileHeader . SizeOfOptionalHeader
) ;
for ( Index = 0 ; Index < ImgHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + , SectionHeader + + ) {
CopyMem (
FileBuffer + SectionHeader - > PointerToRawData ,
( VOID * ) ( UINTN ) ( ImageContext . ImageAddress + SectionHeader - > VirtualAddress ) ,
SectionHeader - > SizeOfRawData
) ;
}
free ( ( VOID * ) MemoryImagePointer ) ;
//
// Update Image Base Address
//
if ( ImgHdr - > Pe32 . OptionalHeader . Magic = = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC ) {
ImgHdr - > Pe32 . OptionalHeader . ImageBase = ( UINT32 ) NewPe32BaseAddress ;
} else if ( ImgHdr - > Pe32Plus . OptionalHeader . Magic = = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC ) {
ImgHdr - > Pe32Plus . OptionalHeader . ImageBase = NewPe32BaseAddress ;
} else {
Error ( NULL , 0 , 3000 , " Invalid " , " unknown PE magic signature %X in PE32 image %s " ,
ImgHdr - > Pe32 . OptionalHeader . Magic ,
FileName
) ;
return EFI_ABORTED ;
}
//
// Set new base address into section header
//
Status = SetAddressToSectionHeader ( FileName , FileBuffer , NewPe32BaseAddress ) ;
return Status ;
}
int
main (
int argc ,
char * argv [ ]
)
/*++
Routine Description :
Main function .
Arguments :
argc - Number of command line parameters .
argv - Array of pointers to command line parameter strings .
Returns :
STATUS_SUCCESS - Utility exits successfully .
STATUS_ERROR - Some error occurred during execution .
- - */
{
UINT32 Type ;
UINT32 InputFileNum ;
CHAR8 * * InputFileName ;
char * OutImageName ;
char * ModuleType ;
CHAR8 * TimeStamp ;
FILE * fpIn ;
FILE * fpOut ;
FILE * fpInOut ;
UINT32 Data ;
UINT32 * DataPointer ;
UINT32 * OldDataPointer ;
UINT32 CheckSum ;
UINT32 Index ;
UINT32 Index1 ;
UINT32 Index2 ;
UINT64 Temp64 ;
UINT32 MciAlignment ;
UINT8 MciPadValue ;
UINT32 AllignedRelocSize ;
UINT8 * FileBuffer ;
UINT32 FileLength ;
UINT8 * OutputFileBuffer ;
UINT32 OutputFileLength ;
UINT8 * InputFileBuffer ;
UINT32 InputFileLength ;
RUNTIME_FUNCTION * RuntimeFunction ;
UNWIND_INFO * UnwindInfo ;
STATUS Status ;
BOOLEAN ReplaceFlag ;
BOOLEAN KeepExceptionTableFlag ;
BOOLEAN KeepOptionalHeaderFlag ;
BOOLEAN KeepZeroPendingFlag ;
UINT64 LogLevel ;
EFI_TE_IMAGE_HEADER TEImageHeader ;
EFI_TE_IMAGE_HEADER * TeHdr ;
EFI_IMAGE_SECTION_HEADER * SectionHeader ;
EFI_IMAGE_DOS_HEADER * DosHdr ;
EFI_IMAGE_OPTIONAL_HEADER_UNION * PeHdr ;
EFI_IMAGE_OPTIONAL_HEADER32 * Optional32 ;
EFI_IMAGE_OPTIONAL_HEADER64 * Optional64 ;
EFI_IMAGE_DOS_HEADER BackupDosHdr ;
MICROCODE_IMAGE_HEADER * MciHeader ;
UINT8 * HiiPackageListBuffer ;
UINT8 * HiiPackageDataPointer ;
EFI_GUID HiiPackageListGuid ;
EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader ;
EFI_HII_PACKAGE_HEADER HiiPackageHeader ;
EFI_IFR_FORM_SET IfrFormSet ;
UINT8 NumberOfFormPackage ;
EFI_HII_PACKAGE_HEADER EndPackage ;
UINT32 HiiSectionHeaderSize ;
UINT8 * HiiSectionHeader ;
UINT64 NewBaseAddress ;
BOOLEAN NegativeAddr ;
FILE * ReportFile ;
CHAR8 * ReportFileName ;
UINTN FileLen ;
time_t InputFileTime ;
time_t OutputFileTime ;
struct stat Stat_Buf ;
2019-09-20 06:56:20 +02:00
BOOLEAN ZeroDebugFlag ;
2019-09-03 11:58:42 +02:00
SetUtilityName ( UTILITY_NAME ) ;
//
// Assign to fix compile warning
//
FileLen = 0 ;
InputFileNum = 0 ;
InputFileName = NULL ;
mInImageName = NULL ;
OutImageName = NULL ;
ModuleType = NULL ;
Type = 0 ;
Status = STATUS_SUCCESS ;
FileBuffer = NULL ;
fpIn = NULL ;
fpOut = NULL ;
fpInOut = NULL ;
TimeStamp = NULL ;
MciAlignment = DEFAULT_MC_ALIGNMENT ;
MciPadValue = DEFAULT_MC_PAD_BYTE_VALUE ;
FileLength = 0 ;
MciHeader = NULL ;
CheckSum = 0 ;
ReplaceFlag = FALSE ;
LogLevel = 0 ;
OutputFileBuffer = NULL ;
OutputFileLength = 0 ;
InputFileBuffer = NULL ;
InputFileLength = 0 ;
Optional32 = NULL ;
Optional64 = NULL ;
KeepExceptionTableFlag = FALSE ;
KeepOptionalHeaderFlag = FALSE ;
KeepZeroPendingFlag = FALSE ;
NumberOfFormPackage = 0 ;
HiiPackageListBuffer = NULL ;
HiiPackageDataPointer = NULL ;
EndPackage . Length = sizeof ( EFI_HII_PACKAGE_HEADER ) ;
EndPackage . Type = EFI_HII_PACKAGE_END ;
memset ( & HiiPackageListGuid , 0 , sizeof ( HiiPackageListGuid ) ) ;
HiiSectionHeaderSize = 0 ;
HiiSectionHeader = NULL ;
NewBaseAddress = 0 ;
NegativeAddr = FALSE ;
InputFileTime = 0 ;
OutputFileTime = 0 ;
2019-09-20 06:56:20 +02:00
ZeroDebugFlag = FALSE ;
2019-09-03 11:58:42 +02:00
2020-11-09 14:19:33 +01:00
SetPrintLevel ( INFO_LOG_LEVEL + 1 ) ;
2019-09-03 11:58:42 +02:00
if ( argc = = 1 ) {
Error ( NULL , 0 , 1001 , " Missing options " , " No input options. " ) ;
Usage ( ) ;
return STATUS_ERROR ;
}
argc - - ;
argv + + ;
if ( ( stricmp ( argv [ 0 ] , " -h " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --help " ) = = 0 ) ) {
Version ( ) ;
Usage ( ) ;
return STATUS_SUCCESS ;
}
if ( stricmp ( argv [ 0 ] , " --version " ) = = 0 ) {
Version ( ) ;
return STATUS_SUCCESS ;
}
while ( argc > 0 ) {
if ( ( stricmp ( argv [ 0 ] , " -o " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --outputfile " ) = = 0 ) ) {
if ( argv [ 1 ] = = NULL | | argv [ 1 ] [ 0 ] = = ' - ' ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " Output file name is missing for -o option " ) ;
goto Finish ;
}
OutImageName = argv [ 1 ] ;
argc - = 2 ;
argv + = 2 ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -e " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --efiImage " ) = = 0 ) ) {
if ( argv [ 1 ] = = NULL | | argv [ 1 ] [ 0 ] = = ' - ' ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " Module Type is missing for -o option " ) ;
goto Finish ;
}
ModuleType = argv [ 1 ] ;
2019-09-20 06:56:20 +02:00
if ( mOutImageType = = FW_ZERO_DEBUG_IMAGE ) {
ZeroDebugFlag = TRUE ;
}
2019-09-03 11:58:42 +02:00
if ( mOutImageType ! = FW_TE_IMAGE ) {
mOutImageType = FW_EFI_IMAGE ;
}
argc - = 2 ;
argv + = 2 ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -l " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --stripped " ) = = 0 ) ) {
mOutImageType = FW_RELOC_STRIPEED_IMAGE ;
argc - - ;
argv + + ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -c " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --acpi " ) = = 0 ) ) {
mOutImageType = FW_ACPI_IMAGE ;
argc - - ;
argv + + ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -t " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --terse " ) = = 0 ) ) {
2019-09-20 06:56:20 +02:00
if ( mOutImageType = = FW_ZERO_DEBUG_IMAGE ) {
ZeroDebugFlag = TRUE ;
}
2019-09-03 11:58:42 +02:00
mOutImageType = FW_TE_IMAGE ;
argc - - ;
argv + + ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -u " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --dump " ) = = 0 ) ) {
mOutImageType = DUMP_TE_HEADER ;
argc - - ;
argv + + ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -b " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --exe2bin " ) = = 0 ) ) {
mOutImageType = FW_BIN_IMAGE ;
argc - - ;
argv + + ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -z " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --zero " ) = = 0 ) ) {
2019-09-20 06:56:20 +02:00
if ( mOutImageType = = FW_DUMMY_IMAGE ) {
2019-09-25 19:52:02 +02:00
mOutImageType = FW_ZERO_DEBUG_IMAGE ;
2019-09-20 06:56:20 +02:00
}
if ( mOutImageType = = FW_TE_IMAGE | | mOutImageType = = FW_EFI_IMAGE ) {
ZeroDebugFlag = TRUE ;
}
2019-09-03 11:58:42 +02:00
argc - - ;
argv + + ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -s " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --stamp " ) = = 0 ) ) {
mOutImageType = FW_SET_STAMP_IMAGE ;
if ( argv [ 1 ] = = NULL | | argv [ 1 ] [ 0 ] = = ' - ' ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " time stamp is missing for -s option " ) ;
goto Finish ;
}
TimeStamp = argv [ 1 ] ;
argc - = 2 ;
argv + = 2 ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -r " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --replace " ) = = 0 ) ) {
ReplaceFlag = TRUE ;
argc - - ;
argv + + ;
continue ;
}
if ( stricmp ( argv [ 0 ] , " --keepexceptiontable " ) = = 0 ) {
KeepExceptionTableFlag = TRUE ;
argc - - ;
argv + + ;
continue ;
}
if ( stricmp ( argv [ 0 ] , " --keepoptionalheader " ) = = 0 ) {
KeepOptionalHeaderFlag = TRUE ;
argc - - ;
argv + + ;
continue ;
}
if ( stricmp ( argv [ 0 ] , " --keepzeropending " ) = = 0 ) {
KeepZeroPendingFlag = TRUE ;
argc - - ;
argv + + ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -m " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --mcifile " ) = = 0 ) ) {
mOutImageType = FW_MCI_IMAGE ;
argc - - ;
argv + + ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -j " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --join " ) = = 0 ) ) {
mOutImageType = FW_MERGE_IMAGE ;
argc - - ;
argv + + ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -a " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --align " ) = = 0 ) ) {
if ( AsciiStringToUint64 ( argv [ 1 ] , FALSE , & Temp64 ) ! = EFI_SUCCESS ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " %s = %s " , argv [ 0 ] , argv [ 1 ] ) ;
goto Finish ;
}
MciAlignment = ( UINT32 ) Temp64 ;
argc - = 2 ;
argv + = 2 ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " --rebase " ) = = 0 ) ) {
if ( argv [ 1 ] [ 0 ] = = ' - ' ) {
NegativeAddr = TRUE ;
Status = AsciiStringToUint64 ( argv [ 1 ] + 1 , FALSE , & Temp64 ) ;
} else {
NegativeAddr = FALSE ;
Status = AsciiStringToUint64 ( argv [ 1 ] , FALSE , & Temp64 ) ;
}
if ( Status ! = EFI_SUCCESS ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " %s = %s " , argv [ 0 ] , argv [ 1 ] ) ;
goto Finish ;
}
mOutImageType = FW_REBASE_IMAGE ;
NewBaseAddress = ( UINT64 ) Temp64 ;
argc - = 2 ;
argv + = 2 ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " --address " ) = = 0 ) ) {
if ( argv [ 1 ] [ 0 ] = = ' - ' ) {
NegativeAddr = TRUE ;
Status = AsciiStringToUint64 ( argv [ 1 ] + 1 , FALSE , & Temp64 ) ;
} else {
NegativeAddr = FALSE ;
Status = AsciiStringToUint64 ( argv [ 1 ] , FALSE , & Temp64 ) ;
}
if ( Status ! = EFI_SUCCESS ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " %s = %s " , argv [ 0 ] , argv [ 1 ] ) ;
goto Finish ;
}
mOutImageType = FW_SET_ADDRESS_IMAGE ;
NewBaseAddress = ( UINT64 ) Temp64 ;
argc - = 2 ;
argv + = 2 ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -p " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --pad " ) = = 0 ) ) {
if ( AsciiStringToUint64 ( argv [ 1 ] , FALSE , & Temp64 ) ! = EFI_SUCCESS ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " %s = %s " , argv [ 0 ] , argv [ 1 ] ) ;
goto Finish ;
}
MciPadValue = ( UINT8 ) Temp64 ;
argc - = 2 ;
argv + = 2 ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -v " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --verbose " ) = = 0 ) ) {
SetPrintLevel ( VERBOSE_LOG_LEVEL ) ;
VerboseMsg ( " Verbose output Mode Set! " ) ;
argc - - ;
argv + + ;
continue ;
}
2020-11-09 14:19:33 +01:00
if ( ( stricmp ( argv [ 0 ] , " --info " ) = = 0 ) ) {
SetPrintLevel ( INFO_LOG_LEVEL ) ;
NormalMsg ( " Info output Mode Set! " ) ;
argc - - ;
argv + + ;
continue ;
}
2019-09-03 11:58:42 +02:00
if ( ( stricmp ( argv [ 0 ] , " -q " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --quiet " ) = = 0 ) ) {
SetPrintLevel ( KEY_LOG_LEVEL ) ;
KeyMsg ( " Quiet output Mode Set! " ) ;
argc - - ;
argv + + ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -d " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --debug " ) = = 0 ) ) {
Status = AsciiStringToUint64 ( argv [ 1 ] , FALSE , & LogLevel ) ;
if ( EFI_ERROR ( Status ) ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " %s = %s " , argv [ 0 ] , argv [ 1 ] ) ;
goto Finish ;
}
if ( LogLevel > 9 ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " Debug Level range is 0-9, current input level is %d " , ( int ) LogLevel ) ;
goto Finish ;
}
SetPrintLevel ( LogLevel ) ;
DebugMsg ( NULL , 0 , 9 , " Debug Mode Set " , " Debug Output Mode Level %s is set! " , argv [ 1 ] ) ;
argc - = 2 ;
argv + = 2 ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -g " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --hiiguid " ) = = 0 ) ) {
Status = StringToGuid ( argv [ 1 ] , & HiiPackageListGuid ) ;
if ( EFI_ERROR ( Status ) ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " %s = %s " , argv [ 0 ] , argv [ 1 ] ) ;
goto Finish ;
}
argc - = 2 ;
argv + = 2 ;
continue ;
}
if ( stricmp ( argv [ 0 ] , " --hiipackage " ) = = 0 ) {
mOutImageType = FW_HII_PACKAGE_LIST_RCIMAGE ;
argc - - ;
argv + + ;
continue ;
}
if ( stricmp ( argv [ 0 ] , " --hiibinpackage " ) = = 0 ) {
mOutImageType = FW_HII_PACKAGE_LIST_BINIMAGE ;
argc - - ;
argv + + ;
continue ;
}
if ( argv [ 0 ] [ 0 ] = = ' - ' ) {
Error ( NULL , 0 , 1000 , " Unknown option " , argv [ 0 ] ) ;
goto Finish ;
}
//
// Get Input file name
//
if ( ( InputFileNum = = 0 ) & & ( InputFileName = = NULL ) ) {
InputFileName = ( CHAR8 * * ) malloc ( MAXIMUM_INPUT_FILE_NUM * sizeof ( CHAR8 * ) ) ;
if ( InputFileName = = NULL ) {
Error ( NULL , 0 , 4001 , " Resource " , " memory cannot be allocated! " ) ;
goto Finish ;
}
memset ( InputFileName , 0 , ( MAXIMUM_INPUT_FILE_NUM * sizeof ( CHAR8 * ) ) ) ;
} else if ( InputFileNum % MAXIMUM_INPUT_FILE_NUM = = 0 ) {
//
// InputFileName buffer too small, need to realloc
//
InputFileName = ( CHAR8 * * ) realloc (
InputFileName ,
( InputFileNum + MAXIMUM_INPUT_FILE_NUM ) * sizeof ( CHAR8 * )
) ;
if ( InputFileName = = NULL ) {
Error ( NULL , 0 , 4001 , " Resource " , " memory cannot be allocated! " ) ;
goto Finish ;
}
memset ( & ( InputFileName [ InputFileNum ] ) , 0 , ( MAXIMUM_INPUT_FILE_NUM * sizeof ( CHAR8 * ) ) ) ;
}
InputFileName [ InputFileNum + + ] = argv [ 0 ] ;
argc - - ;
argv + + ;
}
VerboseMsg ( " %s tool start. " , UTILITY_NAME ) ;
if ( mOutImageType = = FW_DUMMY_IMAGE ) {
Error ( NULL , 0 , 1001 , " Missing option " , " No create file action specified; pls specify -e, -c or -t option to create efi image, or acpi table or TeImage! " ) ;
if ( ReplaceFlag ) {
Error ( NULL , 0 , 1001 , " Missing option " , " -r option is not supported as the independent option. It can be used together with other create file option specified at the above. " ) ;
}
goto Finish ;
}
//
// check input files
//
if ( InputFileNum = = 0 ) {
Error ( NULL , 0 , 1001 , " Missing option " , " Input files " ) ;
goto Finish ;
}
//
// Combine MciBinary files to one file
//
if ( ( mOutImageType = = FW_MERGE_IMAGE ) & & ReplaceFlag ) {
Error ( NULL , 0 , 1002 , " Conflicting option " , " -r replace option cannot be used with -j merge files option. " ) ;
goto Finish ;
}
//
// Combine HiiBinary packages to a single package list
//
if ( ( mOutImageType = = FW_HII_PACKAGE_LIST_RCIMAGE ) & & ReplaceFlag ) {
Error ( NULL , 0 , 1002 , " Conflicting option " , " -r replace option cannot be used with --hiipackage merge files option. " ) ;
goto Finish ;
}
if ( ( mOutImageType = = FW_HII_PACKAGE_LIST_BINIMAGE ) & & ReplaceFlag ) {
Error ( NULL , 0 , 1002 , " Conflicting option " , " -r replace option cannot be used with --hiibinpackage merge files option. " ) ;
goto Finish ;
}
//
// Input image file
//
mInImageName = InputFileName [ InputFileNum - 1 ] ;
VerboseMsg ( " the input file name is %s " , mInImageName ) ;
//
// Action will be taken for the input file.
//
switch ( mOutImageType ) {
case FW_EFI_IMAGE :
VerboseMsg ( " Create efi image on module type %s based on the input PE image. " , ModuleType ) ;
break ;
case FW_TE_IMAGE :
VerboseMsg ( " Create Te Image based on the input PE image. " ) ;
break ;
case FW_ACPI_IMAGE :
VerboseMsg ( " Get acpi table data from the input PE image. " ) ;
break ;
case FW_RELOC_STRIPEED_IMAGE :
VerboseMsg ( " Remove relocation section from Pe or Te image. " ) ;
break ;
case FW_BIN_IMAGE :
VerboseMsg ( " Convert the input EXE to the output BIN file. " ) ;
break ;
case FW_ZERO_DEBUG_IMAGE :
VerboseMsg ( " Zero the Debug Data Fields and Time Stamp in input PE image. " ) ;
break ;
case FW_SET_STAMP_IMAGE :
VerboseMsg ( " Set new time stamp %s in the input PE image. " , TimeStamp ) ;
break ;
case DUMP_TE_HEADER :
VerboseMsg ( " Dump the TE header information of the input TE image. " ) ;
break ;
case FW_MCI_IMAGE :
VerboseMsg ( " Convert input MicroCode.txt file to MicroCode.bin file. " ) ;
break ;
case FW_MERGE_IMAGE :
VerboseMsg ( " Combine the input multi microcode bin files to one bin file. " ) ;
break ;
case FW_HII_PACKAGE_LIST_RCIMAGE :
VerboseMsg ( " Combine the input multi hii bin packages to one text package list RC file. " ) ;
break ;
case FW_HII_PACKAGE_LIST_BINIMAGE :
VerboseMsg ( " Combine the input multi hii bin packages to one binary package list file. " ) ;
break ;
case FW_REBASE_IMAGE :
VerboseMsg ( " Rebase the input image to new base address. " ) ;
break ;
case FW_SET_ADDRESS_IMAGE :
VerboseMsg ( " Set the preferred address into the section header of the input image " ) ;
break ;
default :
break ;
}
if ( ReplaceFlag ) {
VerboseMsg ( " Overwrite the input file with the output content. " ) ;
}
//
// Open output file and Write image into the output file.
//
if ( OutImageName ! = NULL ) {
fpOut = fopen ( LongFilePath ( OutImageName ) , " rb " ) ;
if ( fpOut ! = NULL ) {
//
// Get Output file time stamp
//
fstat ( fileno ( fpOut ) , & Stat_Buf ) ;
OutputFileTime = Stat_Buf . st_mtime ;
//
// Get Output file data
//
OutputFileLength = _filelength ( fileno ( fpOut ) ) ;
OutputFileBuffer = malloc ( OutputFileLength ) ;
if ( OutputFileBuffer = = NULL ) {
Error ( NULL , 0 , 4001 , " Resource " , " memory cannot be allocated! " ) ;
fclose ( fpOut ) ;
fpOut = NULL ;
goto Finish ;
}
fread ( OutputFileBuffer , 1 , OutputFileLength , fpOut ) ;
fclose ( fpOut ) ;
fpOut = NULL ;
}
VerboseMsg ( " Output file name is %s " , OutImageName ) ;
} else if ( ! ReplaceFlag & & mOutImageType ! = DUMP_TE_HEADER ) {
Error ( NULL , 0 , 1001 , " Missing option " , " output file " ) ;
goto Finish ;
}
//
// Open input file and read file data into file buffer.
//
fpIn = fopen ( LongFilePath ( mInImageName ) , " rb " ) ;
if ( fpIn = = NULL ) {
Error ( NULL , 0 , 0001 , " Error opening file " , mInImageName ) ;
goto Finish ;
}
//
// Get Iutput file time stamp
//
fstat ( fileno ( fpIn ) , & Stat_Buf ) ;
InputFileTime = Stat_Buf . st_mtime ;
//
// Get Input file data
//
InputFileLength = _filelength ( fileno ( fpIn ) ) ;
InputFileBuffer = malloc ( InputFileLength ) ;
if ( InputFileBuffer = = NULL ) {
Error ( NULL , 0 , 4001 , " Resource " , " memory cannot be allocated! " ) ;
fclose ( fpIn ) ;
goto Finish ;
}
fread ( InputFileBuffer , 1 , InputFileLength , fpIn ) ;
fclose ( fpIn ) ;
DebugMsg ( NULL , 0 , 9 , " input file info " , " the input file size is %u bytes " , ( unsigned ) InputFileLength ) ;
//
// Combine multi binary HII package files.
//
if ( mOutImageType = = FW_HII_PACKAGE_LIST_RCIMAGE | | mOutImageType = = FW_HII_PACKAGE_LIST_BINIMAGE ) {
//
// Open output file handle.
//
fpOut = fopen ( LongFilePath ( OutImageName ) , " wb " ) ;
if ( ! fpOut ) {
Error ( NULL , 0 , 0001 , " Error opening output file " , OutImageName ) ;
goto Finish ;
}
//
// Get hii package list length
//
HiiPackageListHeader . PackageLength = sizeof ( EFI_HII_PACKAGE_LIST_HEADER ) ;
for ( Index = 0 ; Index < InputFileNum ; Index + + ) {
fpIn = fopen ( LongFilePath ( InputFileName [ Index ] ) , " rb " ) ;
if ( fpIn = = NULL ) {
Error ( NULL , 0 , 0001 , " Error opening file " , InputFileName [ Index ] ) ;
goto Finish ;
}
FileLength = _filelength ( fileno ( fpIn ) ) ;
fread ( & HiiPackageHeader , 1 , sizeof ( HiiPackageHeader ) , fpIn ) ;
if ( HiiPackageHeader . Type = = EFI_HII_PACKAGE_FORM ) {
if ( HiiPackageHeader . Length ! = FileLength ) {
Error ( NULL , 0 , 3000 , " Invalid " , " The wrong package size is in HII package file %s " , InputFileName [ Index ] ) ;
fclose ( fpIn ) ;
goto Finish ;
}
if ( memcmp ( & HiiPackageListGuid , & mZeroGuid , sizeof ( EFI_GUID ) ) = = 0 ) {
fread ( & IfrFormSet , 1 , sizeof ( IfrFormSet ) , fpIn ) ;
memcpy ( & HiiPackageListGuid , & IfrFormSet . Guid , sizeof ( EFI_GUID ) ) ;
}
NumberOfFormPackage + + ;
}
HiiPackageListHeader . PackageLength + = FileLength ;
fclose ( fpIn ) ;
}
HiiPackageListHeader . PackageLength + = sizeof ( EndPackage ) ;
//
// Check whether hii packages are valid
//
if ( NumberOfFormPackage > 1 ) {
Error ( NULL , 0 , 3000 , " Invalid " , " The input hii packages contains more than one hii form package " ) ;
goto Finish ;
}
if ( memcmp ( & HiiPackageListGuid , & mZeroGuid , sizeof ( EFI_GUID ) ) = = 0 ) {
Error ( NULL , 0 , 3000 , " Invalid " , " HII package list guid is not specified! " ) ;
goto Finish ;
}
memcpy ( & HiiPackageListHeader . PackageListGuid , & HiiPackageListGuid , sizeof ( EFI_GUID ) ) ;
//
// read hii packages
//
HiiPackageListBuffer = malloc ( HiiPackageListHeader . PackageLength ) ;
if ( HiiPackageListBuffer = = NULL ) {
Error ( NULL , 0 , 4001 , " Resource " , " memory cannot be allocated! " ) ;
goto Finish ;
}
memcpy ( HiiPackageListBuffer , & HiiPackageListHeader , sizeof ( HiiPackageListHeader ) ) ;
HiiPackageDataPointer = HiiPackageListBuffer + sizeof ( HiiPackageListHeader ) ;
for ( Index = 0 ; Index < InputFileNum ; Index + + ) {
fpIn = fopen ( LongFilePath ( InputFileName [ Index ] ) , " rb " ) ;
if ( fpIn = = NULL ) {
Error ( NULL , 0 , 0001 , " Error opening file " , InputFileName [ Index ] ) ;
free ( HiiPackageListBuffer ) ;
goto Finish ;
}
FileLength = _filelength ( fileno ( fpIn ) ) ;
fread ( HiiPackageDataPointer , 1 , FileLength , fpIn ) ;
fclose ( fpIn ) ;
HiiPackageDataPointer = HiiPackageDataPointer + FileLength ;
}
memcpy ( HiiPackageDataPointer , & EndPackage , sizeof ( EndPackage ) ) ;
//
// write the hii package into the binary package list file with the resource section header
//
if ( mOutImageType = = FW_HII_PACKAGE_LIST_BINIMAGE ) {
//
// Create the resource section header
//
HiiSectionHeader = CreateHiiResouceSectionHeader ( & HiiSectionHeaderSize , HiiPackageListHeader . PackageLength ) ;
if ( HiiSectionHeader = = NULL ) {
free ( HiiPackageListBuffer ) ;
goto Finish ;
}
//
// Wrtie section header and HiiData into File.
//
fwrite ( HiiSectionHeader , 1 , HiiSectionHeaderSize , fpOut ) ;
fwrite ( HiiPackageListBuffer , 1 , HiiPackageListHeader . PackageLength , fpOut ) ;
//
// Free allocated resources.
//
free ( HiiSectionHeader ) ;
free ( HiiPackageListBuffer ) ;
//
// Done successfully
//
goto Finish ;
}
//
// write the hii package into the text package list rc file.
//
if ( mOutImageType = = FW_HII_PACKAGE_LIST_RCIMAGE ) {
for ( Index = 0 ; gHiiPackageRCFileHeader [ Index ] ! = NULL ; Index + + ) {
fprintf ( fpOut , " %s \n " , gHiiPackageRCFileHeader [ Index ] ) ;
}
fprintf ( fpOut , " \n %d %s \n { " , HII_RESOURCE_SECTION_INDEX , HII_RESOURCE_SECTION_NAME ) ;
HiiPackageDataPointer = HiiPackageListBuffer ;
for ( Index = 0 ; Index + 2 < HiiPackageListHeader . PackageLength ; Index + = 2 ) {
if ( Index % 16 = = 0 ) {
fprintf ( fpOut , " \n " ) ;
}
fprintf ( fpOut , " 0x%04X, " , * ( UINT16 * ) HiiPackageDataPointer ) ;
HiiPackageDataPointer + = 2 ;
}
if ( Index % 16 = = 0 ) {
fprintf ( fpOut , " \n " ) ;
}
if ( ( Index + 2 ) = = HiiPackageListHeader . PackageLength ) {
fprintf ( fpOut , " 0x%04X \n } \n " , * ( UINT16 * ) HiiPackageDataPointer ) ;
}
if ( ( Index + 1 ) = = HiiPackageListHeader . PackageLength ) {
fprintf ( fpOut , " 0x%04X \n } \n " , * ( UINT8 * ) HiiPackageDataPointer ) ;
}
free ( HiiPackageListBuffer ) ;
//
// Done successfully
//
goto Finish ;
}
}
//
// Combine MciBinary files to one file
//
if ( mOutImageType = = FW_MERGE_IMAGE ) {
//
// Open output file handle.
//
fpOut = fopen ( LongFilePath ( OutImageName ) , " wb " ) ;
if ( ! fpOut ) {
Error ( NULL , 0 , 0001 , " Error opening output file " , OutImageName ) ;
goto Finish ;
}
for ( Index = 0 ; Index < InputFileNum ; Index + + ) {
fpIn = fopen ( LongFilePath ( InputFileName [ Index ] ) , " rb " ) ;
if ( ! fpIn ) {
Error ( NULL , 0 , 0001 , " Error opening file " , InputFileName [ Index ] ) ;
goto Finish ;
}
FileLength = _filelength ( fileno ( fpIn ) ) ;
FileBuffer = malloc ( FileLength ) ;
if ( FileBuffer = = NULL ) {
Error ( NULL , 0 , 4001 , " Resource " , " memory cannot be allocated! " ) ;
fclose ( fpIn ) ;
goto Finish ;
}
fread ( FileBuffer , 1 , FileLength , fpIn ) ;
fclose ( fpIn ) ;
//
// write input file to out file
//
fwrite ( FileBuffer , 1 , FileLength , fpOut ) ;
//
// write pad value to out file.
//
while ( FileLength + + % MciAlignment ! = 0 ) {
fwrite ( & MciPadValue , 1 , 1 , fpOut ) ;
}
//
// free allocated memory space
//
free ( FileBuffer ) ;
FileBuffer = NULL ;
}
//
// Done successfully
//
goto Finish ;
}
//
// Convert MicroCode.txt file to MicroCode.bin file
//
if ( mOutImageType = = FW_MCI_IMAGE ) {
fpIn = fopen ( LongFilePath ( mInImageName ) , " r " ) ;
if ( fpIn = = NULL ) {
Error ( NULL , 0 , 0001 , " Error opening file " , mInImageName ) ;
goto Finish ;
}
//
// The first pass is to determine
// how much data is in the file so we can allocate a working buffer.
//
FileLength = 0 ;
do {
Status = MicrocodeReadData ( fpIn , & Data ) ;
if ( Status = = STATUS_SUCCESS ) {
FileLength + = sizeof ( Data ) ;
}
if ( Status = = STATUS_IGNORE ) {
Status = STATUS_SUCCESS ;
}
} while ( Status = = STATUS_SUCCESS ) ;
//
// Error if no data.
//
if ( FileLength = = 0 ) {
Error ( NULL , 0 , 3000 , " Invalid " , " no parseable data found in file %s " , mInImageName ) ;
goto Finish ;
}
if ( FileLength < sizeof ( MICROCODE_IMAGE_HEADER ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " amount of parseable data in %s is insufficient to contain a microcode header " , mInImageName ) ;
goto Finish ;
}
//
// Allocate a buffer for the data
//
FileBuffer = malloc ( FileLength ) ;
if ( FileBuffer = = NULL ) {
Error ( NULL , 0 , 4001 , " Resource " , " memory cannot be allocated! " ) ;
goto Finish ;
}
//
// Re-read the file, storing the data into our buffer
//
fseek ( fpIn , 0 , SEEK_SET ) ;
DataPointer = ( UINT32 * ) FileBuffer ;
OldDataPointer = DataPointer ;
do {
OldDataPointer = DataPointer ;
Status = MicrocodeReadData ( fpIn , DataPointer + + ) ;
if ( Status = = STATUS_IGNORE ) {
DataPointer = OldDataPointer ;
Status = STATUS_SUCCESS ;
}
} while ( Status = = STATUS_SUCCESS ) ;
//
// close input file after read data
//
fclose ( fpIn ) ;
//
// Can't do much checking on the header because, per the spec, the
// DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
// and the TotalSize field is invalid (actually missing). Thus we can't
// even verify the Reserved fields are 0.
//
MciHeader = ( MICROCODE_IMAGE_HEADER * ) FileBuffer ;
if ( MciHeader - > DataSize = = 0 ) {
Index = 2048 ;
} else {
Index = MciHeader - > TotalSize ;
}
if ( Index ! = FileLength ) {
Error ( NULL , 0 , 3000 , " Invalid " , " file length of %s (0x%x) does not equal expected TotalSize: 0x%04X. " , mInImageName , ( unsigned ) FileLength , ( unsigned ) Index ) ;
goto Finish ;
}
//
// Checksum the contents
//
DataPointer = ( UINT32 * ) FileBuffer ;
CheckSum = 0 ;
Index = 0 ;
while ( Index < FileLength ) {
CheckSum + = * DataPointer ;
DataPointer + + ;
Index + = sizeof ( * DataPointer ) ;
}
if ( CheckSum ! = 0 ) {
Error ( NULL , 0 , 3000 , " Invalid " , " checksum (0x%x) failed on file %s. " , ( unsigned ) CheckSum , mInImageName ) ;
goto Finish ;
}
//
// Open the output file and write the buffer contents
//
VerboseMsg ( " the size of output file is %u bytes " , ( unsigned ) FileLength ) ;
goto WriteFile ;
}
//
// Open input file and read file data into file buffer.
//
FileLength = InputFileLength ;
FileBuffer = malloc ( FileLength ) ;
if ( FileBuffer = = NULL ) {
Error ( NULL , 0 , 4001 , " Resource " , " memory cannot be allocated! " ) ;
goto Finish ;
}
memcpy ( FileBuffer , InputFileBuffer , InputFileLength ) ;
//
// Dump TeImage Header into output file.
//
if ( mOutImageType = = DUMP_TE_HEADER ) {
memcpy ( & TEImageHeader , FileBuffer , sizeof ( TEImageHeader ) ) ;
if ( TEImageHeader . Signature ! = EFI_TE_IMAGE_HEADER_SIGNATURE ) {
Error ( NULL , 0 , 3000 , " Invalid " , " TE header signature of file %s is not correct. " , mInImageName ) ;
goto Finish ;
}
//
// Open the output file handle.
//
if ( ReplaceFlag ) {
fpInOut = fopen ( LongFilePath ( mInImageName ) , " wb " ) ;
if ( fpInOut = = NULL ) {
Error ( NULL , 0 , 0001 , " Error opening file " , mInImageName ) ;
goto Finish ;
}
} else {
if ( OutImageName ! = NULL ) {
fpOut = fopen ( LongFilePath ( OutImageName ) , " wb " ) ;
} else {
fpOut = stdout ;
}
if ( fpOut = = NULL ) {
Error ( NULL , 0 , 0001 , " Error opening output file " , OutImageName ) ;
goto Finish ;
}
}
if ( fpInOut ! = NULL ) {
fprintf ( fpInOut , " Dump of file %s \n \n " , mInImageName ) ;
fprintf ( fpInOut , " TE IMAGE HEADER VALUES \n " ) ;
fprintf ( fpInOut , " %17X machine \n " , TEImageHeader . Machine ) ;
fprintf ( fpInOut , " %17X number of sections \n " , TEImageHeader . NumberOfSections ) ;
fprintf ( fpInOut , " %17X subsystems \n " , TEImageHeader . Subsystem ) ;
fprintf ( fpInOut , " %17X stripped size \n " , TEImageHeader . StrippedSize ) ;
fprintf ( fpInOut , " %17X entry point \n " , ( unsigned ) TEImageHeader . AddressOfEntryPoint ) ;
fprintf ( fpInOut , " %17X base of code \n " , ( unsigned ) TEImageHeader . BaseOfCode ) ;
fprintf ( fpInOut , " %17llX image base \n " , ( unsigned long long ) TEImageHeader . ImageBase ) ;
fprintf ( fpInOut , " %17X [%8X] RVA [size] of Base Relocation Directory \n " , ( unsigned ) TEImageHeader . DataDirectory [ 0 ] . VirtualAddress , ( unsigned ) TEImageHeader . DataDirectory [ 0 ] . Size ) ;
fprintf ( fpInOut , " %17X [%8X] RVA [size] of Debug Directory \n " , ( unsigned ) TEImageHeader . DataDirectory [ 1 ] . VirtualAddress , ( unsigned ) TEImageHeader . DataDirectory [ 1 ] . Size ) ;
}
if ( fpOut ! = NULL ) {
fprintf ( fpOut , " Dump of file %s \n \n " , mInImageName ) ;
fprintf ( fpOut , " TE IMAGE HEADER VALUES \n " ) ;
fprintf ( fpOut , " %17X machine \n " , TEImageHeader . Machine ) ;
fprintf ( fpOut , " %17X number of sections \n " , TEImageHeader . NumberOfSections ) ;
fprintf ( fpOut , " %17X subsystems \n " , TEImageHeader . Subsystem ) ;
fprintf ( fpOut , " %17X stripped size \n " , TEImageHeader . StrippedSize ) ;
fprintf ( fpOut , " %17X entry point \n " , ( unsigned ) TEImageHeader . AddressOfEntryPoint ) ;
fprintf ( fpOut , " %17X base of code \n " , ( unsigned ) TEImageHeader . BaseOfCode ) ;
fprintf ( fpOut , " %17llX image base \n " , ( unsigned long long ) TEImageHeader . ImageBase ) ;
fprintf ( fpOut , " %17X [%8X] RVA [size] of Base Relocation Directory \n " , ( unsigned ) TEImageHeader . DataDirectory [ 0 ] . VirtualAddress , ( unsigned ) TEImageHeader . DataDirectory [ 0 ] . Size ) ;
fprintf ( fpOut , " %17X [%8X] RVA [size] of Debug Directory \n " , ( unsigned ) TEImageHeader . DataDirectory [ 1 ] . VirtualAddress , ( unsigned ) TEImageHeader . DataDirectory [ 1 ] . Size ) ;
}
goto Finish ;
}
//
// Following code to convert dll to efi image or te image.
// Get new image type
//
if ( ( mOutImageType = = FW_EFI_IMAGE ) | | ( mOutImageType = = FW_TE_IMAGE ) ) {
if ( ModuleType = = NULL ) {
if ( mOutImageType = = FW_EFI_IMAGE ) {
Error ( NULL , 0 , 1001 , " Missing option " , " EFI_FILETYPE " ) ;
goto Finish ;
} else if ( mOutImageType = = FW_TE_IMAGE ) {
//
// Default TE Image Type is Boot service driver
//
Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER ;
VerboseMsg ( " Efi Image subsystem type is efi boot service driver. " ) ;
}
} else {
if ( stricmp ( ModuleType , " BASE " ) = = 0 | |
stricmp ( ModuleType , " SEC " ) = = 0 | |
stricmp ( ModuleType , " SECURITY_CORE " ) = = 0 | |
stricmp ( ModuleType , " PEI_CORE " ) = = 0 | |
stricmp ( ModuleType , " PEIM " ) = = 0 | |
stricmp ( ModuleType , " COMBINED_PEIM_DRIVER " ) = = 0 | |
stricmp ( ModuleType , " PIC_PEIM " ) = = 0 | |
stricmp ( ModuleType , " RELOCATABLE_PEIM " ) = = 0 | |
stricmp ( ModuleType , " DXE_CORE " ) = = 0 | |
stricmp ( ModuleType , " BS_DRIVER " ) = = 0 | |
stricmp ( ModuleType , " DXE_DRIVER " ) = = 0 | |
stricmp ( ModuleType , " DXE_SMM_DRIVER " ) = = 0 | |
stricmp ( ModuleType , " UEFI_DRIVER " ) = = 0 | |
stricmp ( ModuleType , " SMM_CORE " ) = = 0 | |
stricmp ( ModuleType , " MM_STANDALONE " ) = = 0 | |
stricmp ( ModuleType , " MM_CORE_STANDALONE " ) = = 0 ) {
Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER ;
VerboseMsg ( " Efi Image subsystem type is efi boot service driver. " ) ;
} else if ( stricmp ( ModuleType , " UEFI_APPLICATION " ) = = 0 | |
stricmp ( ModuleType , " APPLICATION " ) = = 0 ) {
Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ;
VerboseMsg ( " Efi Image subsystem type is efi application. " ) ;
} else if ( stricmp ( ModuleType , " DXE_RUNTIME_DRIVER " ) = = 0 | |
stricmp ( ModuleType , " RT_DRIVER " ) = = 0 ) {
Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ;
VerboseMsg ( " Efi Image subsystem type is efi runtime driver. " ) ;
} else if ( stricmp ( ModuleType , " DXE_SAL_DRIVER " ) = = 0 | |
stricmp ( ModuleType , " SAL_RT_DRIVER " ) = = 0 ) {
Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER ;
VerboseMsg ( " Efi Image subsystem type is efi sal runtime driver. " ) ;
} else {
Error ( NULL , 0 , 1003 , " Invalid option value " , " EFI_FILETYPE = %s " , ModuleType ) ;
goto Finish ;
}
}
}
//
// Convert ELF image to PeImage
//
if ( IsElfHeader ( FileBuffer ) ) {
VerboseMsg ( " Convert %s from ELF to PE/COFF. " , mInImageName ) ;
if ( ! ConvertElf ( & FileBuffer , & FileLength ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " Unable to convert %s from ELF to PE/COFF. " , mInImageName ) ;
goto Finish ;
}
}
//
// Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
// XIP == eXecute In Place
//
PeCoffConvertImageToXip ( & FileBuffer , & FileLength ) ;
//
// Remove reloc section from PE or TE image
//
if ( mOutImageType = = FW_RELOC_STRIPEED_IMAGE ) {
//
// Check TeImage
//
TeHdr = ( EFI_TE_IMAGE_HEADER * ) FileBuffer ;
if ( TeHdr - > Signature = = EFI_TE_IMAGE_HEADER_SIGNATURE ) {
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( TeHdr + 1 ) ;
for ( Index = 0 ; Index < TeHdr - > NumberOfSections ; Index + + , SectionHeader + + ) {
if ( strcmp ( ( char * ) SectionHeader - > Name , " .reloc " ) = = 0 ) {
//
// Check the reloc section is in the end of image.
//
if ( ( SectionHeader - > PointerToRawData + SectionHeader - > SizeOfRawData ) = =
( FileLength + TeHdr - > StrippedSize - sizeof ( EFI_TE_IMAGE_HEADER ) ) ) {
//
// Remove .reloc section and update TeImage Header
//
FileLength = FileLength - SectionHeader - > SizeOfRawData ;
SectionHeader - > SizeOfRawData = 0 ;
SectionHeader - > Misc . VirtualSize = 0 ;
TeHdr - > DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress = 0 ;
TeHdr - > DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size = 0 ;
break ;
}
}
}
} else {
//
// Check PE Image
//
DosHdr = ( EFI_IMAGE_DOS_HEADER * ) FileBuffer ;
if ( DosHdr - > e_magic ! = EFI_IMAGE_DOS_SIGNATURE ) {
PeHdr = ( EFI_IMAGE_OPTIONAL_HEADER_UNION * ) ( FileBuffer ) ;
if ( PeHdr - > Pe32 . Signature ! = EFI_IMAGE_NT_SIGNATURE ) {
Error ( NULL , 0 , 3000 , " Invalid " , " TE and DOS header signatures were not found in %s image. " , mInImageName ) ;
goto Finish ;
}
DosHdr = NULL ;
} else {
PeHdr = ( EFI_IMAGE_OPTIONAL_HEADER_UNION * ) ( FileBuffer + DosHdr - > e_lfanew ) ;
if ( PeHdr - > Pe32 . Signature ! = EFI_IMAGE_NT_SIGNATURE ) {
Error ( NULL , 0 , 3000 , " Invalid " , " PE header signature was not found in %s image. " , mInImageName ) ;
goto Finish ;
}
}
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) & ( PeHdr - > Pe32 . OptionalHeader ) + PeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) ;
for ( Index = 0 ; Index < PeHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + , SectionHeader + + ) {
if ( strcmp ( ( char * ) SectionHeader - > Name , " .reloc " ) = = 0 ) {
//
// Check the reloc section is in the end of image.
//
if ( ( SectionHeader - > PointerToRawData + SectionHeader - > SizeOfRawData ) = = FileLength ) {
//
// Remove .reloc section and update PeImage Header
//
FileLength = FileLength - SectionHeader - > SizeOfRawData ;
PeHdr - > Pe32 . FileHeader . Characteristics | = EFI_IMAGE_FILE_RELOCS_STRIPPED ;
if ( PeHdr - > Pe32 . OptionalHeader . Magic = = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC ) {
Optional32 = ( EFI_IMAGE_OPTIONAL_HEADER32 * ) & PeHdr - > Pe32 . OptionalHeader ;
Optional32 - > SizeOfImage - = SectionHeader - > SizeOfRawData ;
Optional32 - > SizeOfInitializedData - = SectionHeader - > SizeOfRawData ;
if ( Optional32 - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ) {
Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress = 0 ;
Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size = 0 ;
}
}
if ( PeHdr - > Pe32 . OptionalHeader . Magic = = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC ) {
Optional64 = ( EFI_IMAGE_OPTIONAL_HEADER64 * ) & PeHdr - > Pe32 . OptionalHeader ;
Optional64 - > SizeOfImage - = SectionHeader - > SizeOfRawData ;
Optional64 - > SizeOfInitializedData - = SectionHeader - > SizeOfRawData ;
if ( Optional64 - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ) {
Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress = 0 ;
Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size = 0 ;
}
}
SectionHeader - > Misc . VirtualSize = 0 ;
SectionHeader - > SizeOfRawData = 0 ;
break ;
}
}
}
}
//
// Write file
//
goto WriteFile ;
}
//
// Read the dos & pe hdrs of the image
//
DosHdr = ( EFI_IMAGE_DOS_HEADER * ) FileBuffer ;
if ( DosHdr - > e_magic ! = EFI_IMAGE_DOS_SIGNATURE ) {
// NO DOS header, check for PE/COFF header
PeHdr = ( EFI_IMAGE_OPTIONAL_HEADER_UNION * ) ( FileBuffer ) ;
if ( PeHdr - > Pe32 . Signature ! = EFI_IMAGE_NT_SIGNATURE ) {
Error ( NULL , 0 , 3000 , " Invalid " , " DOS header signature was not found in %s image. " , mInImageName ) ;
goto Finish ;
}
DosHdr = NULL ;
} else {
PeHdr = ( EFI_IMAGE_OPTIONAL_HEADER_UNION * ) ( FileBuffer + DosHdr - > e_lfanew ) ;
if ( PeHdr - > Pe32 . Signature ! = EFI_IMAGE_NT_SIGNATURE ) {
Error ( NULL , 0 , 3000 , " Invalid " , " PE header signature was not found in %s image. " , mInImageName ) ;
goto Finish ;
}
}
if ( PeHdr - > Pe32 . FileHeader . Machine = = IMAGE_FILE_MACHINE_ARM ) {
// Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
// so patch back to the official UEFI value.
PeHdr - > Pe32 . FileHeader . Machine = IMAGE_FILE_MACHINE_ARMT ;
}
//
// Set new base address into image
//
if ( mOutImageType = = FW_REBASE_IMAGE | | mOutImageType = = FW_SET_ADDRESS_IMAGE ) {
if ( PeHdr - > Pe32 . OptionalHeader . Magic = = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC ) {
if ( NewBaseAddress > = 0x100000000ULL ) {
Error ( NULL , 0 , 3000 , " Invalid " , " New base address is larger than 4G for 32bit PE image " ) ;
goto Finish ;
}
}
if ( NegativeAddr ) {
//
// Set Base Address to a negative value.
//
NewBaseAddress = ( UINT64 ) ( 0 - NewBaseAddress ) ;
}
if ( mOutImageType = = FW_REBASE_IMAGE ) {
Status = RebaseImage ( mInImageName , FileBuffer , NewBaseAddress ) ;
} else {
Status = SetAddressToSectionHeader ( mInImageName , FileBuffer , NewBaseAddress ) ;
}
if ( EFI_ERROR ( Status ) ) {
if ( NegativeAddr ) {
Error ( NULL , 0 , 3000 , " Invalid " , " Rebase/Set Image %s to Base address -0x%llx can't success " , mInImageName , 0 - NewBaseAddress ) ;
} else {
Error ( NULL , 0 , 3000 , " Invalid " , " Rebase/Set Image %s to Base address 0x%llx can't success " , mInImageName , NewBaseAddress ) ;
}
goto Finish ;
}
//
// Write file
//
goto WriteFile ;
}
//
// Extract bin data from Pe image.
//
if ( mOutImageType = = FW_BIN_IMAGE ) {
if ( FileLength < PeHdr - > Pe32 . OptionalHeader . SizeOfHeaders ) {
Error ( NULL , 0 , 3000 , " Invalid " , " FileSize of %s is not a legal size. " , mInImageName ) ;
goto Finish ;
}
//
// Output bin data from exe file
//
FileLength = FileLength - PeHdr - > Pe32 . OptionalHeader . SizeOfHeaders ;
memmove ( FileBuffer , FileBuffer + PeHdr - > Pe32 . OptionalHeader . SizeOfHeaders , FileLength ) ;
VerboseMsg ( " the size of output file is %u bytes " , ( unsigned ) FileLength ) ;
goto WriteFile ;
}
//
// Zero Debug Information of Pe Image
//
if ( mOutImageType = = FW_ZERO_DEBUG_IMAGE ) {
Status = ZeroDebugData ( FileBuffer , TRUE ) ;
if ( EFI_ERROR ( Status ) ) {
Error ( NULL , 0 , 3000 , " Invalid " , " Zero DebugData Error status is 0x%x " , ( int ) Status ) ;
goto Finish ;
}
//
// Write the updated Image
//
VerboseMsg ( " the size of output file is %u bytes " , ( unsigned ) FileLength ) ;
goto WriteFile ;
}
//
// Set Time Stamp of Pe Image
//
if ( mOutImageType = = FW_SET_STAMP_IMAGE ) {
Status = SetStamp ( FileBuffer , TimeStamp ) ;
if ( EFI_ERROR ( Status ) ) {
goto Finish ;
}
//
// Write the updated Image
//
VerboseMsg ( " the size of output file is %u bytes " , ( unsigned ) FileLength ) ;
goto WriteFile ;
}
//
// Extract acpi data from pe image.
//
if ( mOutImageType = = FW_ACPI_IMAGE ) {
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) & ( PeHdr - > Pe32 . OptionalHeader ) + PeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) ;
for ( Index = 0 ; Index < PeHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + , SectionHeader + + ) {
if ( strcmp ( ( char * ) SectionHeader - > Name , " .data " ) = = 0 | | strcmp ( ( char * ) SectionHeader - > Name , " .sdata " ) = = 0 ) {
//
// Check Acpi Table
//
if ( SectionHeader - > Misc . VirtualSize < SectionHeader - > SizeOfRawData ) {
FileLength = SectionHeader - > Misc . VirtualSize ;
} else {
FileLength = SectionHeader - > SizeOfRawData ;
}
if ( CheckAcpiTable ( FileBuffer + SectionHeader - > PointerToRawData , FileLength ) ! = STATUS_SUCCESS ) {
Error ( NULL , 0 , 3000 , " Invalid " , " ACPI table check failed in %s. " , mInImageName ) ;
goto Finish ;
}
//
// Output Apci data to file
//
memmove ( FileBuffer , FileBuffer + SectionHeader - > PointerToRawData , FileLength ) ;
VerboseMsg ( " the size of output file is %u bytes " , ( unsigned ) FileLength ) ;
goto WriteFile ;
}
}
Error ( NULL , 0 , 3000 , " Invalid " , " failed to get ACPI table from %s. " , mInImageName ) ;
goto Finish ;
}
//
// Zero all unused fields of the DOS header
//
if ( DosHdr ! = NULL ) {
memcpy ( & BackupDosHdr , DosHdr , sizeof ( EFI_IMAGE_DOS_HEADER ) ) ;
memset ( DosHdr , 0 , sizeof ( EFI_IMAGE_DOS_HEADER ) ) ;
DosHdr - > e_magic = BackupDosHdr . e_magic ;
DosHdr - > e_lfanew = BackupDosHdr . e_lfanew ;
for ( Index = sizeof ( EFI_IMAGE_DOS_HEADER ) ; Index < ( UINT32 ) DosHdr - > e_lfanew ; Index + + ) {
FileBuffer [ Index ] = ( UINT8 ) DosHdr - > e_cp ;
}
}
//
// Initialize TeImage Header
//
memset ( & TEImageHeader , 0 , sizeof ( EFI_TE_IMAGE_HEADER ) ) ;
TEImageHeader . Signature = EFI_TE_IMAGE_HEADER_SIGNATURE ;
TEImageHeader . Machine = PeHdr - > Pe32 . FileHeader . Machine ;
TEImageHeader . NumberOfSections = ( UINT8 ) PeHdr - > Pe32 . FileHeader . NumberOfSections ;
TEImageHeader . StrippedSize = ( UINT16 ) ( ( UINTN ) ( ( UINT8 * ) & ( PeHdr - > Pe32 . OptionalHeader ) + PeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) - ( UINTN ) FileBuffer ) ;
TEImageHeader . Subsystem = ( UINT8 ) Type ;
//
// Patch the PE header
//
PeHdr - > Pe32 . OptionalHeader . Subsystem = ( UINT16 ) Type ;
if ( PeHdr - > Pe32 . OptionalHeader . Magic = = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC ) {
Optional32 = ( EFI_IMAGE_OPTIONAL_HEADER32 * ) & PeHdr - > Pe32 . OptionalHeader ;
if ( ! KeepOptionalHeaderFlag ) {
Optional32 - > MajorOperatingSystemVersion = 0 ;
Optional32 - > MinorOperatingSystemVersion = 0 ;
Optional32 - > MajorImageVersion = 0 ;
Optional32 - > MinorImageVersion = 0 ;
Optional32 - > MajorSubsystemVersion = 0 ;
Optional32 - > MinorSubsystemVersion = 0 ;
Optional32 - > Win32VersionValue = 0 ;
Optional32 - > CheckSum = 0 ;
Optional32 - > SizeOfStackReserve = 0 ;
Optional32 - > SizeOfStackCommit = 0 ;
Optional32 - > SizeOfHeapReserve = 0 ;
Optional32 - > SizeOfHeapCommit = 0 ;
}
TEImageHeader . AddressOfEntryPoint = Optional32 - > AddressOfEntryPoint ;
TEImageHeader . BaseOfCode = Optional32 - > BaseOfCode ;
TEImageHeader . ImageBase = ( UINT64 ) ( Optional32 - > ImageBase ) ;
if ( Optional32 - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ) {
TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress = Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress ;
TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size = Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size ;
}
if ( Optional32 - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ) {
TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG ] . VirtualAddress = Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . VirtualAddress ;
TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size = Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size ;
}
//
// Zero .pdata section data.
//
if ( ! KeepExceptionTableFlag & & Optional32 - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION & &
Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION ] . VirtualAddress ! = 0 & &
Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION ] . Size ! = 0 ) {
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) & ( PeHdr - > Pe32 . OptionalHeader ) + PeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) ;
for ( Index = 0 ; Index < PeHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + , SectionHeader + + ) {
if ( SectionHeader - > VirtualAddress = = Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION ] . VirtualAddress ) {
//
// Zero .pdata Section data
//
memset ( FileBuffer + SectionHeader - > PointerToRawData , 0 , SectionHeader - > SizeOfRawData ) ;
//
// Zero .pdata Section header name
//
memset ( SectionHeader - > Name , 0 , sizeof ( SectionHeader - > Name ) ) ;
//
// Zero Exception Table
//
Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION ] . VirtualAddress = 0 ;
Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION ] . Size = 0 ;
DebugMsg ( NULL , 0 , 9 , " Zero the .pdata section for PE image " , NULL ) ;
break ;
}
}
}
//
// Strip zero padding at the end of the .reloc section
//
if ( ! KeepZeroPendingFlag & & Optional32 - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ) {
if ( Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size ! = 0 ) {
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) & ( PeHdr - > Pe32 . OptionalHeader ) + PeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) ;
for ( Index = 0 ; Index < PeHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + , SectionHeader + + ) {
//
// Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
//
if ( SectionHeader - > VirtualAddress = = Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress ) {
SectionHeader - > Misc . VirtualSize = Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size ;
AllignedRelocSize = ( Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size + Optional32 - > FileAlignment - 1 ) & ( ~ ( Optional32 - > FileAlignment - 1 ) ) ;
//
// Check to see if there is zero padding at the end of the base relocations
//
if ( AllignedRelocSize < SectionHeader - > SizeOfRawData ) {
//
// Check to see if the base relocations are at the end of the file
//
if ( SectionHeader - > PointerToRawData + SectionHeader - > SizeOfRawData = = Optional32 - > SizeOfImage ) {
//
// All the required conditions are met to strip the zero padding of the end of the base relocations section
//
Optional32 - > SizeOfImage - = ( SectionHeader - > SizeOfRawData - AllignedRelocSize ) ;
Optional32 - > SizeOfInitializedData - = ( SectionHeader - > SizeOfRawData - AllignedRelocSize ) ;
SectionHeader - > SizeOfRawData = AllignedRelocSize ;
FileLength = Optional32 - > SizeOfImage ;
DebugMsg ( NULL , 0 , 9 , " Remove the zero padding bytes at the end of the base relocations " , " The size of padding bytes is %u " , ( unsigned ) ( SectionHeader - > SizeOfRawData - AllignedRelocSize ) ) ;
}
}
}
}
}
}
} else if ( PeHdr - > Pe32 . OptionalHeader . Magic = = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC ) {
Optional64 = ( EFI_IMAGE_OPTIONAL_HEADER64 * ) & PeHdr - > Pe32 . OptionalHeader ;
if ( ! KeepOptionalHeaderFlag ) {
Optional64 - > MajorOperatingSystemVersion = 0 ;
Optional64 - > MinorOperatingSystemVersion = 0 ;
Optional64 - > MajorImageVersion = 0 ;
Optional64 - > MinorImageVersion = 0 ;
Optional64 - > MajorSubsystemVersion = 0 ;
Optional64 - > MinorSubsystemVersion = 0 ;
Optional64 - > Win32VersionValue = 0 ;
Optional64 - > CheckSum = 0 ;
Optional64 - > SizeOfStackReserve = 0 ;
Optional64 - > SizeOfStackCommit = 0 ;
Optional64 - > SizeOfHeapReserve = 0 ;
Optional64 - > SizeOfHeapCommit = 0 ;
}
TEImageHeader . AddressOfEntryPoint = Optional64 - > AddressOfEntryPoint ;
TEImageHeader . BaseOfCode = Optional64 - > BaseOfCode ;
TEImageHeader . ImageBase = ( UINT64 ) ( Optional64 - > ImageBase ) ;
if ( Optional64 - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ) {
TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress = Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress ;
TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size = Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size ;
}
if ( Optional64 - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ) {
TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG ] . VirtualAddress = Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . VirtualAddress ;
TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size = Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size ;
}
//
// Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
// For Itaninum and X64 Image, remove .pdata section.
//
if ( ( ! KeepExceptionTableFlag & & PeHdr - > Pe32 . FileHeader . Machine = = IMAGE_FILE_MACHINE_X64 ) ) {
if ( Optional64 - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION & &
Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION ] . VirtualAddress ! = 0 & &
Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION ] . Size ! = 0 ) {
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) & ( PeHdr - > Pe32 . OptionalHeader ) + PeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) ;
for ( Index = 0 ; Index < PeHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + , SectionHeader + + ) {
if ( SectionHeader - > VirtualAddress = = Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION ] . VirtualAddress ) {
//
// Zero .pdata Section header name
//
memset ( SectionHeader - > Name , 0 , sizeof ( SectionHeader - > Name ) ) ;
RuntimeFunction = ( RUNTIME_FUNCTION * ) ( FileBuffer + SectionHeader - > PointerToRawData ) ;
for ( Index1 = 0 ; Index1 < Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION ] . Size / sizeof ( RUNTIME_FUNCTION ) ; Index1 + + , RuntimeFunction + + ) {
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) & ( PeHdr - > Pe32 . OptionalHeader ) + PeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) ;
for ( Index2 = 0 ; Index2 < PeHdr - > Pe32 . FileHeader . NumberOfSections ; Index2 + + , SectionHeader + + ) {
if ( RuntimeFunction - > UnwindInfoAddress > = SectionHeader - > VirtualAddress & & RuntimeFunction - > UnwindInfoAddress < ( SectionHeader - > VirtualAddress + SectionHeader - > SizeOfRawData ) ) {
UnwindInfo = ( UNWIND_INFO * ) ( FileBuffer + SectionHeader - > PointerToRawData + ( RuntimeFunction - > UnwindInfoAddress - SectionHeader - > VirtualAddress ) ) ;
if ( UnwindInfo - > Version = = 1 ) {
memset ( UnwindInfo + 1 , 0 , UnwindInfo - > CountOfUnwindCodes * sizeof ( UINT16 ) ) ;
memset ( UnwindInfo , 0 , sizeof ( UNWIND_INFO ) ) ;
}
break ;
}
}
memset ( RuntimeFunction , 0 , sizeof ( RUNTIME_FUNCTION ) ) ;
}
//
// Zero Exception Table
//
Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION ] . Size = 0 ;
Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION ] . VirtualAddress = 0 ;
DebugMsg ( NULL , 0 , 9 , " Zero the .pdata section if the machine type is X64 for PE32+ image " , NULL ) ;
break ;
}
}
}
}
//
// Strip zero padding at the end of the .reloc section
//
if ( ! KeepZeroPendingFlag & & Optional64 - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ) {
if ( Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size ! = 0 ) {
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) & ( PeHdr - > Pe32 . OptionalHeader ) + PeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) ;
for ( Index = 0 ; Index < PeHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + , SectionHeader + + ) {
//
// Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
//
if ( SectionHeader - > VirtualAddress = = Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress ) {
SectionHeader - > Misc . VirtualSize = Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size ;
AllignedRelocSize = ( Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size + Optional64 - > FileAlignment - 1 ) & ( ~ ( Optional64 - > FileAlignment - 1 ) ) ;
//
// Check to see if there is zero padding at the end of the base relocations
//
if ( AllignedRelocSize < SectionHeader - > SizeOfRawData ) {
//
// Check to see if the base relocations are at the end of the file
//
if ( SectionHeader - > PointerToRawData + SectionHeader - > SizeOfRawData = = Optional64 - > SizeOfImage ) {
//
// All the required conditions are met to strip the zero padding of the end of the base relocations section
//
Optional64 - > SizeOfImage - = ( SectionHeader - > SizeOfRawData - AllignedRelocSize ) ;
Optional64 - > SizeOfInitializedData - = ( SectionHeader - > SizeOfRawData - AllignedRelocSize ) ;
SectionHeader - > SizeOfRawData = AllignedRelocSize ;
FileLength = Optional64 - > SizeOfImage ;
DebugMsg ( NULL , 0 , 9 , " Remove the zero padding bytes at the end of the base relocations " , " The size of padding bytes is %u " , ( unsigned ) ( SectionHeader - > SizeOfRawData - AllignedRelocSize ) ) ;
}
}
}
}
}
}
} else {
Error ( NULL , 0 , 3000 , " Invalid " , " Magic 0x%x of PeImage %s is unknown. " , PeHdr - > Pe32 . OptionalHeader . Magic , mInImageName ) ;
goto Finish ;
}
if ( ( ( PeHdr - > Pe32 . FileHeader . Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED ) = = 0 ) & & \
( TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress = = 0 ) & & \
( TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . Size = = 0 ) ) {
//
// PeImage can be loaded into memory, but it has no relocation section.
// Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
//
if ( Optional32 ! = NULL ) {
TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress = Optional32 - > SizeOfImage - sizeof ( EFI_IMAGE_BASE_RELOCATION ) ;
} else if ( Optional64 ! = NULL ) {
TEImageHeader . DataDirectory [ EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC ] . VirtualAddress = Optional64 - > SizeOfImage - sizeof ( EFI_IMAGE_BASE_RELOCATION ) ;
}
}
//
// Fill HII section data
//
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) & ( PeHdr - > Pe32 . OptionalHeader ) + PeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) ;
for ( Index = 0 ; Index < PeHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + ) {
if ( stricmp ( ( char * ) SectionHeader [ Index ] . Name , " .hii " ) = = 0 ) {
//
// Update resource section header offset
//
SetHiiResourceHeader ( ( UINT8 * ) FileBuffer + SectionHeader [ Index ] . PointerToRawData , SectionHeader [ Index ] . VirtualAddress ) ;
//
// Update resource section name
//
strcpy ( ( char * ) SectionHeader [ Index ] . Name , " .rsrc " ) ;
//
// Update resource data directory.
//
if ( PeHdr - > Pe32 . OptionalHeader . Magic = = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC ) {
Optional32 = ( EFI_IMAGE_OPTIONAL_HEADER32 * ) & PeHdr - > Pe32 . OptionalHeader ;
Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . VirtualAddress = SectionHeader [ Index ] . VirtualAddress ;
Optional32 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . Size = SectionHeader [ Index ] . Misc . VirtualSize ;
} else if ( PeHdr - > Pe32 . OptionalHeader . Magic = = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC ) {
Optional64 = ( EFI_IMAGE_OPTIONAL_HEADER64 * ) & PeHdr - > Pe32 . OptionalHeader ;
Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . VirtualAddress = SectionHeader [ Index ] . VirtualAddress ;
Optional64 - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . Size = SectionHeader [ Index ] . Misc . VirtualSize ;
}
break ;
}
}
//
// Zero ExceptionTable Xdata
//
if ( ! KeepExceptionTableFlag ) {
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) & ( PeHdr - > Pe32 . OptionalHeader ) + PeHdr - > Pe32 . FileHeader . SizeOfOptionalHeader ) ;
for ( Index = 0 ; Index < PeHdr - > Pe32 . FileHeader . NumberOfSections ; Index + + ) {
if ( stricmp ( ( char * ) SectionHeader [ Index ] . Name , " .xdata " ) = = 0 ) {
//
// zero .xdata section
//
memset ( FileBuffer + SectionHeader [ Index ] . PointerToRawData , 0 , SectionHeader [ Index ] . SizeOfRawData ) ;
DebugMsg ( NULL , 0 , 9 , NULL , " Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x " , ( unsigned ) SectionHeader [ Index ] . PointerToRawData , ( unsigned ) SectionHeader [ Index ] . SizeOfRawData ) ;
break ;
}
}
}
//
// Zero Time/Data field
//
2019-09-20 06:56:20 +02:00
ZeroDebugData ( FileBuffer , ZeroDebugFlag ) ;
2019-09-03 11:58:42 +02:00
if ( mOutImageType = = FW_TE_IMAGE ) {
if ( ( PeHdr - > Pe32 . FileHeader . NumberOfSections & ~ 0xFF ) | | ( Type & ~ 0xFF ) ) {
//
// Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
//
Error ( NULL , 0 , 3000 , " Invalid " , " Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte. " , mInImageName ) ;
goto Finish ;
}
if ( ( PeHdr - > Pe32 . OptionalHeader . SectionAlignment ! = PeHdr - > Pe32 . OptionalHeader . FileAlignment ) ) {
//
// TeImage has the same section alignment and file alignment.
//
Error ( NULL , 0 , 3000 , " Invalid " , " Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage. " , mInImageName ) ;
goto Finish ;
}
DebugMsg ( NULL , 0 , 9 , " TeImage Header Info " , " Machine type is %X, Number of sections is %X, Stripped size is %X, EntryPoint is %X, BaseOfCode is %X, ImageBase is %llX " ,
TEImageHeader . Machine , TEImageHeader . NumberOfSections , TEImageHeader . StrippedSize , ( unsigned ) TEImageHeader . AddressOfEntryPoint , ( unsigned ) TEImageHeader . BaseOfCode , ( unsigned long long ) TEImageHeader . ImageBase ) ;
//
// Update Image to TeImage
//
FileLength = FileLength - TEImageHeader . StrippedSize ;
memmove ( FileBuffer + sizeof ( EFI_TE_IMAGE_HEADER ) , FileBuffer + TEImageHeader . StrippedSize , FileLength ) ;
FileLength = FileLength + sizeof ( EFI_TE_IMAGE_HEADER ) ;
memcpy ( FileBuffer , & TEImageHeader , sizeof ( EFI_TE_IMAGE_HEADER ) ) ;
VerboseMsg ( " the size of output file is %u bytes " , ( unsigned ) ( FileLength ) ) ;
} else {
//
// Following codes are to fix the objcopy's issue:
// objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section
// It cause issue for EFI image which has no ".reloc" sections.
// Following codes will be removed when objcopy in binutil fix this problem for PE image.
//
if ( ( PeHdr - > Pe32 . FileHeader . Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED ) ! = 0 ) {
if ( PeHdr - > Pe32 . OptionalHeader . Magic = = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC ) {
Optional32 = ( EFI_IMAGE_OPTIONAL_HEADER32 * ) & PeHdr - > Pe32 . OptionalHeader ;
if ( Optional32 - > ImageBase = = 0 ) {
PeHdr - > Pe32 . FileHeader . Characteristics & = ~ EFI_IMAGE_FILE_RELOCS_STRIPPED ;
}
} else if ( PeHdr - > Pe32 . OptionalHeader . Magic = = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC ) {
Optional64 = ( EFI_IMAGE_OPTIONAL_HEADER64 * ) & PeHdr - > Pe32 . OptionalHeader ;
if ( Optional64 - > ImageBase = = 0 ) {
PeHdr - > Pe32 . FileHeader . Characteristics & = ~ EFI_IMAGE_FILE_RELOCS_STRIPPED ;
}
}
}
}
WriteFile :
//
// Update Image to EfiImage or TE image
//
if ( ReplaceFlag ) {
if ( ( FileLength ! = InputFileLength ) | | ( memcmp ( FileBuffer , InputFileBuffer , FileLength ) ! = 0 ) ) {
//
// Update File when File is changed.
//
fpInOut = fopen ( LongFilePath ( mInImageName ) , " wb " ) ;
if ( fpInOut = = NULL ) {
Error ( NULL , 0 , 0001 , " Error opening file " , mInImageName ) ;
goto Finish ;
}
fwrite ( FileBuffer , 1 , FileLength , fpInOut ) ;
VerboseMsg ( " the size of output file is %u bytes " , ( unsigned ) FileLength ) ;
}
} else {
if ( ( OutputFileTime < InputFileTime ) | | ( FileLength ! = OutputFileLength ) | | ( memcmp ( FileBuffer , OutputFileBuffer , FileLength ) ! = 0 ) ) {
//
// Update File when File is changed or File is old.
//
fpOut = fopen ( LongFilePath ( OutImageName ) , " wb " ) ;
if ( fpOut = = NULL ) {
Error ( NULL , 0 , 0001 , " Error opening output file " , OutImageName ) ;
goto Finish ;
}
fwrite ( FileBuffer , 1 , FileLength , fpOut ) ;
VerboseMsg ( " the size of output file is %u bytes " , ( unsigned ) FileLength ) ;
}
}
mImageSize = FileLength ;
Finish :
if ( fpInOut ! = NULL ) {
if ( GetUtilityStatus ( ) ! = STATUS_SUCCESS ) {
//
// when file updates failed, original file is still recovered.
//
fwrite ( InputFileBuffer , 1 , InputFileLength , fpInOut ) ;
}
//
// Write converted data into fpInOut file and close input file.
//
fclose ( fpInOut ) ;
}
if ( FileBuffer ! = NULL ) {
free ( FileBuffer ) ;
}
if ( InputFileName ! = NULL ) {
free ( InputFileName ) ;
}
if ( fpOut ! = NULL ) {
//
// Write converted data into fpOut file and close output file.
//
fclose ( fpOut ) ;
if ( GetUtilityStatus ( ) ! = STATUS_SUCCESS ) {
if ( OutputFileBuffer = = NULL ) {
remove ( OutImageName ) ;
} else {
fpOut = fopen ( LongFilePath ( OutImageName ) , " wb " ) ;
fwrite ( OutputFileBuffer , 1 , OutputFileLength , fpOut ) ;
fclose ( fpOut ) ;
}
}
}
if ( InputFileBuffer ! = NULL ) {
free ( InputFileBuffer ) ;
}
if ( OutputFileBuffer ! = NULL ) {
free ( OutputFileBuffer ) ;
}
//
// Write module size and time stamp to report file.
//
if ( OutImageName ! = NULL ) {
FileLen = strlen ( OutImageName ) ;
}
if ( FileLen > = 4 & & strcmp ( OutImageName + ( FileLen - 4 ) , " .efi " ) = = 0 ) {
ReportFileName = ( CHAR8 * ) malloc ( FileLen + 1 ) ;
if ( ReportFileName ! = NULL ) {
strcpy ( ReportFileName , OutImageName ) ;
strcpy ( ReportFileName + ( FileLen - 4 ) , " .txt " ) ;
ReportFile = fopen ( LongFilePath ( ReportFileName ) , " w+ " ) ;
if ( ReportFile ! = NULL ) {
fprintf ( ReportFile , " MODULE_SIZE = %u \n " , ( unsigned ) mImageSize ) ;
fprintf ( ReportFile , " TIME_STAMP = %u \n " , ( unsigned ) mImageTimeStamp ) ;
fclose ( ReportFile ) ;
}
free ( ReportFileName ) ;
}
}
VerboseMsg ( " %s tool done with return code is 0x%x. " , UTILITY_NAME , GetUtilityStatus ( ) ) ;
return GetUtilityStatus ( ) ;
}
STATIC
EFI_STATUS
ZeroDebugData (
IN OUT UINT8 * FileBuffer ,
BOOLEAN ZeroDebugFlag
)
/*++
Routine Description :
Zero debug information in PeImage .
Arguments :
FileBuffer - Pointer to PeImage .
ZeroDebugFlag - TRUE to zero Debug information , FALSE to only zero time / stamp
Returns :
EFI_ABORTED - PeImage is invalid .
EFI_SUCCESS - Zero debug data successfully .
- - */
{
UINT32 Index ;
UINT32 DebugDirectoryEntryRva ;
UINT32 DebugDirectoryEntrySize ;
UINT32 DebugDirectoryEntryFileOffset ;
UINT32 ExportDirectoryEntryRva ;
UINT32 ExportDirectoryEntryFileOffset ;
UINT32 ResourceDirectoryEntryRva ;
UINT32 ResourceDirectoryEntryFileOffset ;
EFI_IMAGE_DOS_HEADER * DosHdr ;
EFI_IMAGE_FILE_HEADER * FileHdr ;
EFI_IMAGE_OPTIONAL_HEADER32 * Optional32Hdr ;
EFI_IMAGE_OPTIONAL_HEADER64 * Optional64Hdr ;
EFI_IMAGE_SECTION_HEADER * SectionHeader ;
EFI_IMAGE_DEBUG_DIRECTORY_ENTRY * DebugEntry ;
EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY * RsdsEntry ;
UINT32 * NewTimeStamp ;
//
// Init variable.
//
DebugDirectoryEntryRva = 0 ;
DebugDirectoryEntrySize = 0 ;
ExportDirectoryEntryRva = 0 ;
ResourceDirectoryEntryRva = 0 ;
DebugDirectoryEntryFileOffset = 0 ;
ExportDirectoryEntryFileOffset = 0 ;
ResourceDirectoryEntryFileOffset = 0 ;
DosHdr = ( EFI_IMAGE_DOS_HEADER * ) FileBuffer ;
FileHdr = ( EFI_IMAGE_FILE_HEADER * ) ( FileBuffer + DosHdr - > e_lfanew + sizeof ( UINT32 ) ) ;
DosHdr = ( EFI_IMAGE_DOS_HEADER * ) FileBuffer ;
if ( DosHdr - > e_magic ! = EFI_IMAGE_DOS_SIGNATURE ) {
// NO DOS header, must start with PE/COFF header
FileHdr = ( EFI_IMAGE_FILE_HEADER * ) ( FileBuffer + sizeof ( UINT32 ) ) ;
} else {
FileHdr = ( EFI_IMAGE_FILE_HEADER * ) ( FileBuffer + DosHdr - > e_lfanew + sizeof ( UINT32 ) ) ;
}
//
// Get Debug, Export and Resource EntryTable RVA address.
// Resource Directory entry need to review.
//
Optional32Hdr = ( EFI_IMAGE_OPTIONAL_HEADER32 * ) ( ( UINT8 * ) FileHdr + sizeof ( EFI_IMAGE_FILE_HEADER ) ) ;
Optional64Hdr = ( EFI_IMAGE_OPTIONAL_HEADER64 * ) ( ( UINT8 * ) FileHdr + sizeof ( EFI_IMAGE_FILE_HEADER ) ) ;
if ( Optional32Hdr - > Magic = = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC ) {
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) Optional32Hdr + FileHdr - > SizeOfOptionalHeader ) ;
if ( Optional32Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT & & \
Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXPORT ] . Size ! = 0 ) {
ExportDirectoryEntryRva = Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXPORT ] . VirtualAddress ;
}
if ( Optional32Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE & & \
Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . Size ! = 0 ) {
ResourceDirectoryEntryRva = Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . VirtualAddress ;
}
if ( Optional32Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG & & \
Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size ! = 0 ) {
DebugDirectoryEntryRva = Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . VirtualAddress ;
DebugDirectoryEntrySize = Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size ;
if ( ZeroDebugFlag ) {
Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size = 0 ;
Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . VirtualAddress = 0 ;
}
}
} else {
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) Optional64Hdr + FileHdr - > SizeOfOptionalHeader ) ;
if ( Optional64Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT & & \
Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXPORT ] . Size ! = 0 ) {
ExportDirectoryEntryRva = Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXPORT ] . VirtualAddress ;
}
if ( Optional64Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE & & \
Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . Size ! = 0 ) {
ResourceDirectoryEntryRva = Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . VirtualAddress ;
}
if ( Optional64Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG & & \
Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size ! = 0 ) {
DebugDirectoryEntryRva = Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . VirtualAddress ;
DebugDirectoryEntrySize = Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size ;
if ( ZeroDebugFlag ) {
Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size = 0 ;
Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . VirtualAddress = 0 ;
}
}
}
//
// Get DirectoryEntryTable file offset.
//
for ( Index = 0 ; Index < FileHdr - > NumberOfSections ; Index + + , SectionHeader + + ) {
if ( DebugDirectoryEntryRva > = SectionHeader - > VirtualAddress & &
DebugDirectoryEntryRva < SectionHeader - > VirtualAddress + SectionHeader - > Misc . VirtualSize ) {
DebugDirectoryEntryFileOffset =
DebugDirectoryEntryRva - SectionHeader - > VirtualAddress + SectionHeader - > PointerToRawData ;
}
if ( ExportDirectoryEntryRva > = SectionHeader - > VirtualAddress & &
ExportDirectoryEntryRva < SectionHeader - > VirtualAddress + SectionHeader - > Misc . VirtualSize ) {
ExportDirectoryEntryFileOffset =
ExportDirectoryEntryRva - SectionHeader - > VirtualAddress + SectionHeader - > PointerToRawData ;
}
if ( ResourceDirectoryEntryRva > = SectionHeader - > VirtualAddress & &
ResourceDirectoryEntryRva < SectionHeader - > VirtualAddress + SectionHeader - > Misc . VirtualSize ) {
ResourceDirectoryEntryFileOffset =
ResourceDirectoryEntryRva - SectionHeader - > VirtualAddress + SectionHeader - > PointerToRawData ;
}
}
//
//Zero Debug Data and TimeStamp
//
FileHdr - > TimeDateStamp = 0 ;
mImageTimeStamp = 0 ;
if ( ExportDirectoryEntryFileOffset ! = 0 ) {
NewTimeStamp = ( UINT32 * ) ( FileBuffer + ExportDirectoryEntryFileOffset + sizeof ( UINT32 ) ) ;
* NewTimeStamp = 0 ;
}
if ( ResourceDirectoryEntryFileOffset ! = 0 ) {
NewTimeStamp = ( UINT32 * ) ( FileBuffer + ResourceDirectoryEntryFileOffset + sizeof ( UINT32 ) ) ;
* NewTimeStamp = 0 ;
}
if ( DebugDirectoryEntryFileOffset ! = 0 ) {
DebugEntry = ( EFI_IMAGE_DEBUG_DIRECTORY_ENTRY * ) ( FileBuffer + DebugDirectoryEntryFileOffset ) ;
Index = 0 ;
for ( Index = 0 ; Index < DebugDirectoryEntrySize / sizeof ( EFI_IMAGE_DEBUG_DIRECTORY_ENTRY ) ; Index + + , DebugEntry + + ) {
DebugEntry - > TimeDateStamp = 0 ;
if ( mIsConvertXip ) {
DebugEntry - > FileOffset = DebugEntry - > RVA ;
}
if ( ZeroDebugFlag | | DebugEntry - > Type ! = EFI_IMAGE_DEBUG_TYPE_CODEVIEW ) {
memset ( FileBuffer + DebugEntry - > FileOffset , 0 , DebugEntry - > SizeOfData ) ;
memset ( DebugEntry , 0 , sizeof ( EFI_IMAGE_DEBUG_DIRECTORY_ENTRY ) ) ;
}
if ( DebugEntry - > Type = = EFI_IMAGE_DEBUG_TYPE_CODEVIEW ) {
RsdsEntry = ( EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY * ) ( FileBuffer + DebugEntry - > FileOffset ) ;
if ( RsdsEntry - > Signature = = CODEVIEW_SIGNATURE_MTOC ) {
// MTOC sets DebugDirectoryEntrySize to size of the .debug section, so fix it.
if ( ! ZeroDebugFlag ) {
if ( Optional32Hdr - > Magic = = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC ) {
Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size = sizeof ( EFI_IMAGE_DEBUG_DIRECTORY_ENTRY ) ;
} else {
Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size = sizeof ( EFI_IMAGE_DEBUG_DIRECTORY_ENTRY ) ;
}
}
break ;
}
}
}
}
return EFI_SUCCESS ;
}
STATIC
EFI_STATUS
SetStamp (
IN OUT UINT8 * FileBuffer ,
IN CHAR8 * TimeStamp
)
/*++
Routine Description :
Set new time stamp into PeImage FileHdr and Directory table :
Debug , Export and Resource .
Arguments :
FileBuffer - Pointer to PeImage .
TimeStamp - Time stamp string .
Returns :
EFI_INVALID_PARAMETER - TimeStamp format is not recognized .
EFI_SUCCESS - Set new time stamp in this image successfully .
- - */
{
struct tm stime ;
struct tm * ptime ;
time_t newtime ;
UINT32 Index ;
UINT32 DebugDirectoryEntryRva ;
UINT32 DebugDirectoryEntryFileOffset ;
UINT32 ExportDirectoryEntryRva ;
UINT32 ExportDirectoryEntryFileOffset ;
UINT32 ResourceDirectoryEntryRva ;
UINT32 ResourceDirectoryEntryFileOffset ;
EFI_IMAGE_DOS_HEADER * DosHdr ;
EFI_IMAGE_FILE_HEADER * FileHdr ;
EFI_IMAGE_OPTIONAL_HEADER32 * Optional32Hdr ;
EFI_IMAGE_OPTIONAL_HEADER64 * Optional64Hdr ;
EFI_IMAGE_SECTION_HEADER * SectionHeader ;
UINT32 * NewTimeStamp ;
//
// Init variable.
//
DebugDirectoryEntryRva = 0 ;
DebugDirectoryEntryFileOffset = 0 ;
ExportDirectoryEntryRva = 0 ;
ExportDirectoryEntryFileOffset = 0 ;
ResourceDirectoryEntryRva = 0 ;
ResourceDirectoryEntryFileOffset = 0 ;
//
// Get time and date that will be set.
//
if ( TimeStamp = = NULL ) {
Error ( NULL , 0 , 3000 , " Invalid " , " TimeStamp cannot be NULL. " ) ;
return EFI_INVALID_PARAMETER ;
}
//
// compare the value with "NOW", if yes, current system time is set.
//
if ( stricmp ( TimeStamp , " NOW " ) = = 0 ) {
//
// get system current time and date
//
time ( & newtime ) ;
} else {
//
// Check Time Format strictly yyyy-mm-dd 00:00:00
//
for ( Index = 0 ; TimeStamp [ Index ] ! = ' \0 ' & & Index < 20 ; Index + + ) {
if ( Index = = 4 | | Index = = 7 ) {
if ( TimeStamp [ Index ] = = ' - ' ) {
continue ;
}
} else if ( Index = = 13 | | Index = = 16 ) {
if ( TimeStamp [ Index ] = = ' : ' ) {
continue ;
}
} else if ( Index = = 10 & & TimeStamp [ Index ] = = ' ' ) {
continue ;
} else if ( ( TimeStamp [ Index ] < ' 0 ' ) | | ( TimeStamp [ Index ] > ' 9 ' ) ) {
break ;
}
}
if ( Index < 19 | | TimeStamp [ 19 ] ! = ' \0 ' ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " Incorrect Time \" %s \" \n Correct Format \" yyyy-mm-dd 00:00:00 \" " , TimeStamp ) ;
return EFI_INVALID_PARAMETER ;
}
//
// get the date and time from TimeStamp
//
if ( sscanf ( TimeStamp , " %d-%d-%d %d:%d:%d " ,
& stime . tm_year ,
& stime . tm_mon ,
& stime . tm_mday ,
& stime . tm_hour ,
& stime . tm_min ,
& stime . tm_sec
) ! = 6 ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " Incorrect Tiem \" %s \" \n Correct Format \" yyyy-mm-dd 00:00:00 \" " , TimeStamp ) ;
return EFI_INVALID_PARAMETER ;
}
//
// in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
//
if ( stime . tm_mon < = 0 | | stime . tm_mday < = 0 ) {
Error ( NULL , 0 , 3000 , " Invalid " , " %s Invalid date! " , TimeStamp ) ;
return EFI_INVALID_PARAMETER ;
}
stime . tm_mon - = 1 ;
//
// in struct, Year (current year minus 1900)
// and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
//
//
// convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
//
if ( stime . tm_year > = 1970 & & stime . tm_year < = 2038 ) {
//
// convert 1970 -> 70, 2000 -> 100, ...
//
stime . tm_year - = 1900 ;
} else {
Error ( NULL , 0 , 3000 , " Invalid " , " %s Invalid or unsupported datetime! " , TimeStamp ) ;
return EFI_INVALID_PARAMETER ;
}
//
// convert the date and time to time_t format
//
newtime = mktime ( & stime ) ;
if ( newtime = = ( time_t ) - 1 ) {
Error ( NULL , 0 , 3000 , " Invalid " , " %s Invalid or unsupported datetime! " , TimeStamp ) ;
return EFI_INVALID_PARAMETER ;
}
}
ptime = localtime ( & newtime ) ;
if ( ptime ! = NULL ) {
DebugMsg ( NULL , 0 , 9 , " New Image Time Stamp " , " %04d-%02d-%02d %02d:%02d:%02d " ,
ptime - > tm_year + 1900 , ptime - > tm_mon + 1 , ptime - > tm_mday , ptime - > tm_hour , ptime - > tm_min , ptime - > tm_sec ) ;
}
//
// Set new time and data into PeImage.
//
DosHdr = ( EFI_IMAGE_DOS_HEADER * ) FileBuffer ;
if ( DosHdr - > e_magic ! = EFI_IMAGE_DOS_SIGNATURE ) {
// NO DOS header, must start with PE/COFF header
FileHdr = ( EFI_IMAGE_FILE_HEADER * ) ( FileBuffer + sizeof ( UINT32 ) ) ;
} else {
FileHdr = ( EFI_IMAGE_FILE_HEADER * ) ( FileBuffer + DosHdr - > e_lfanew + sizeof ( UINT32 ) ) ;
}
//
// Get Debug, Export and Resource EntryTable RVA address.
// Resource Directory entry need to review.
//
if ( FileHdr - > Machine = = EFI_IMAGE_MACHINE_IA32 ) {
Optional32Hdr = ( EFI_IMAGE_OPTIONAL_HEADER32 * ) ( ( UINT8 * ) FileHdr + sizeof ( EFI_IMAGE_FILE_HEADER ) ) ;
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) Optional32Hdr + FileHdr - > SizeOfOptionalHeader ) ;
if ( Optional32Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT & & \
Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXPORT ] . Size ! = 0 ) {
ExportDirectoryEntryRva = Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXPORT ] . VirtualAddress ;
}
if ( Optional32Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE & & \
Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . Size ! = 0 ) {
ResourceDirectoryEntryRva = Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . VirtualAddress ;
}
if ( Optional32Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG & & \
Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size ! = 0 ) {
DebugDirectoryEntryRva = Optional32Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . VirtualAddress ;
}
} else {
Optional64Hdr = ( EFI_IMAGE_OPTIONAL_HEADER64 * ) ( ( UINT8 * ) FileHdr + sizeof ( EFI_IMAGE_FILE_HEADER ) ) ;
SectionHeader = ( EFI_IMAGE_SECTION_HEADER * ) ( ( UINT8 * ) Optional64Hdr + FileHdr - > SizeOfOptionalHeader ) ;
if ( Optional64Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT & & \
Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXPORT ] . Size ! = 0 ) {
ExportDirectoryEntryRva = Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_EXPORT ] . VirtualAddress ;
}
if ( Optional64Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE & & \
Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . Size ! = 0 ) {
ResourceDirectoryEntryRva = Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE ] . VirtualAddress ;
}
if ( Optional64Hdr - > NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG & & \
Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . Size ! = 0 ) {
DebugDirectoryEntryRva = Optional64Hdr - > DataDirectory [ EFI_IMAGE_DIRECTORY_ENTRY_DEBUG ] . VirtualAddress ;
}
}
//
// Get DirectoryEntryTable file offset.
//
for ( Index = 0 ; Index < FileHdr - > NumberOfSections ; Index + + , SectionHeader + + ) {
if ( DebugDirectoryEntryRva > = SectionHeader - > VirtualAddress & &
DebugDirectoryEntryRva < SectionHeader - > VirtualAddress + SectionHeader - > Misc . VirtualSize ) {
DebugDirectoryEntryFileOffset =
DebugDirectoryEntryRva - SectionHeader - > VirtualAddress + SectionHeader - > PointerToRawData ;
}
if ( ExportDirectoryEntryRva > = SectionHeader - > VirtualAddress & &
ExportDirectoryEntryRva < SectionHeader - > VirtualAddress + SectionHeader - > Misc . VirtualSize ) {
ExportDirectoryEntryFileOffset =
ExportDirectoryEntryRva - SectionHeader - > VirtualAddress + SectionHeader - > PointerToRawData ;
}
if ( ResourceDirectoryEntryRva > = SectionHeader - > VirtualAddress & &
ResourceDirectoryEntryRva < SectionHeader - > VirtualAddress + SectionHeader - > Misc . VirtualSize ) {
ResourceDirectoryEntryFileOffset =
ResourceDirectoryEntryRva - SectionHeader - > VirtualAddress + SectionHeader - > PointerToRawData ;
}
}
//
// Set new stamp
//
FileHdr - > TimeDateStamp = ( UINT32 ) newtime ;
mImageTimeStamp = ( UINT32 ) newtime ;
if ( ExportDirectoryEntryRva ! = 0 ) {
NewTimeStamp = ( UINT32 * ) ( FileBuffer + ExportDirectoryEntryFileOffset + sizeof ( UINT32 ) ) ;
* NewTimeStamp = ( UINT32 ) newtime ;
}
if ( ResourceDirectoryEntryRva ! = 0 ) {
NewTimeStamp = ( UINT32 * ) ( FileBuffer + ResourceDirectoryEntryFileOffset + sizeof ( UINT32 ) ) ;
* NewTimeStamp = ( UINT32 ) newtime ;
}
if ( DebugDirectoryEntryRva ! = 0 ) {
NewTimeStamp = ( UINT32 * ) ( FileBuffer + DebugDirectoryEntryFileOffset + sizeof ( UINT32 ) ) ;
* NewTimeStamp = ( UINT32 ) newtime ;
}
return EFI_SUCCESS ;
}
STATIC
STATUS
MicrocodeReadData (
FILE * InFptr ,
UINT32 * Data
)
/*++
Routine Description :
Read a 32 - bit microcode data value from a text file and convert to raw binary form .
Arguments :
InFptr - file pointer to input text file
Data - pointer to where to return the data parsed
Returns :
STATUS_SUCCESS - no errors or warnings , Data contains valid information
STATUS_ERROR - errors were encountered
- - */
{
CHAR8 Line [ MAX_LINE_LEN ] ;
CHAR8 * cptr ;
int ScannedData = 0 ;
Line [ MAX_LINE_LEN - 1 ] = 0 ;
while ( 1 ) {
if ( fgets ( Line , MAX_LINE_LEN , InFptr ) = = NULL ) {
return STATUS_ERROR ;
}
//
// If it was a binary file, then it may have overwritten our null terminator
//
if ( Line [ MAX_LINE_LEN - 1 ] ! = 0 ) {
return STATUS_ERROR ;
}
//
// strip space
//
for ( cptr = Line ; * cptr & & isspace ( ( int ) * cptr ) ; cptr + + ) {
}
// Skip Blank Lines and Comment Lines
if ( ( strlen ( cptr ) ! = 0 ) & & ( * cptr ! = ' ; ' ) ) {
break ;
}
}
// Look for
// dd 000000001h ; comment
// dd XXXXXXXX
// DD XXXXXXXXX
// DD XXXXXXXXX
//
if ( ( tolower ( ( int ) cptr [ 0 ] ) = = ' d ' ) & & ( tolower ( ( int ) cptr [ 1 ] ) = = ' d ' ) & & isspace ( ( int ) cptr [ 2 ] ) ) {
//
// Skip blanks and look for a hex digit
//
cptr + = 3 ;
for ( ; * cptr & & isspace ( ( int ) * cptr ) ; cptr + + ) {
}
if ( isxdigit ( ( int ) * cptr ) ) {
if ( sscanf ( cptr , " %X " , & ScannedData ) ! = 1 ) {
return STATUS_ERROR ;
}
}
* Data = ( UINT32 ) ScannedData ;
return STATUS_SUCCESS ;
}
return STATUS_ERROR ;
}