mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-25 17:23:53 +02:00 
			
		
		
		
	Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Yingke Liu <yingke.d.liu@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15971 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			3190 lines
		
	
	
		
			119 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3190 lines
		
	
	
		
			119 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| Converts a pe32+ image to an FW, Te image type, or other specific image.
 | |
| 
 | |
| Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #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;
 | |
| 
 | |
| 
 | |
| 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, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME);
 | |
| 
 | |
|   //
 | |
|   // Copyright declaration
 | |
|   //
 | |
|   fprintf (stdout, "Copyright (c) 2007 - 2014, 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 ouput 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\
 | |
|                         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, -r, -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, "  -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, -r, -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, "  -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, "  --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 pacakges 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 pacakges 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 FileAlginment 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);
 | |
|   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;
 | |
| }
 | |
| 
 | |
| 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);
 | |
|   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;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // No available section header is found.
 | |
|   //
 | |
|   if (Index == ImgHdr->Pe32.FileHeader.NumberOfSections) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // 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.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {
 | |
|     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                          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                            NumberOfFormPacakge;
 | |
|   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;
 | |
| 
 | |
|   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;
 | |
|   KeepZeroPendingFlag    = FALSE;
 | |
|   NumberOfFormPacakge    = 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;
 | |
| 
 | |
|   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];
 | |
|       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)) {
 | |
|       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)) {
 | |
|       mOutImageType = FW_ZERO_DEBUG_IMAGE;
 | |
|       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], "--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;
 | |
|     }
 | |
| 
 | |
|     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, currnt 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 ("Conver 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 pacakge list RC file.");
 | |
|     break;
 | |
|   case FW_HII_PACKAGE_LIST_BINIMAGE:
 | |
|     VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge 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 lenght
 | |
|     //
 | |
|     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));
 | |
|         }
 | |
|         NumberOfFormPacakge ++;
 | |
|       }
 | |
|       HiiPackageListHeader.PackageLength += FileLength;
 | |
|       fclose (fpIn);
 | |
|     }
 | |
|     HiiPackageListHeader.PackageLength += sizeof (EndPackage);
 | |
|     //
 | |
|     // Check whether hii packages are valid
 | |
|     //
 | |
|     if (NumberOfFormPacakge > 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 pacakge 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);
 | |
|       //
 | |
|       // 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) {
 | |
|           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 offical 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) && (PeHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {
 | |
|       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;
 | |
|     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 Execption 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;
 | |
|     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) || PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {
 | |
|       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 Execption 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
 | |
|   //
 | |
|   ZeroDebugData (FileBuffer, FALSE);
 | |
| 
 | |
|   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                           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;
 | |
|   UINT32                          *NewTimeStamp;  
 | |
| 
 | |
|   //
 | |
|   // Init variable.
 | |
|   //
 | |
|   DebugDirectoryEntryRva           = 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.
 | |
|   //
 | |
|   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;
 | |
|       if (ZeroDebugFlag) {
 | |
|         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
 | |
|         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
 | |
|       }
 | |
|     }
 | |
|   } 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;
 | |
|       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);
 | |
|     DebugEntry->TimeDateStamp = 0;
 | |
|     mImageTimeStamp = 0;
 | |
|     if (ZeroDebugFlag) {
 | |
|       memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);
 | |
|       memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   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);
 | |
|   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;
 | |
|   unsigned 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;
 | |
| }
 |