13eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++ 23eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 33e99020dbf0a159e34b84e7ae9125f2e368d5390lgaoCopyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR> 44b1e11214a01fa6994e3f77c2481f2723a32221bhhtianThis program and the accompanying materials 53eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangare licensed and made available under the terms and conditions of the BSD License 63eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangwhich accompanies this distribution. The full text of the license may be found at 73eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwanghttp://opensource.org/licenses/bsd-license.php 83eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 93eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangModule Name: 133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fwimage.c 153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangAbstract: 173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Converts a pe32/pe32+ image to an FW image type 193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/ 213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include <windows.h> 233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include <stdio.h> 243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include <stdlib.h> 253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include <string.h> 263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include <time.h> 273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include "TianoCommon.h" 293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include "EfiImage.h" 303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include "EfiUtilityMsgs.c" 313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 323e99020dbf0a159e34b84e7ae9125f2e368d5390lgao#define UTILITY_NAME "FwImage" 333e99020dbf0a159e34b84e7ae9125f2e368d5390lgao#define UTILITY_VERSION "v1.0" 343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangtypedef union { 363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang IMAGE_NT_HEADERS32 PeHeader32; 373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang IMAGE_NT_HEADERS64 PeHeader64; 383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang} PE_HEADER; 393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangVOID 413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangUsage ( 423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang VOID 433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang ) 443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{ 453e99020dbf0a159e34b84e7ae9125f2e368d5390lgao int Index; 463e99020dbf0a159e34b84e7ae9125f2e368d5390lgao const char *Str[] = { 473e99020dbf0a159e34b84e7ae9125f2e368d5390lgao UTILITY_NAME" "UTILITY_VERSION" - Intel Firmware Image Utility", 483e99020dbf0a159e34b84e7ae9125f2e368d5390lgao " Copyright (C), 2004 - 2008 Intel Corporation", 493e99020dbf0a159e34b84e7ae9125f2e368d5390lgao 503e99020dbf0a159e34b84e7ae9125f2e368d5390lgao#if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) ) 513e99020dbf0a159e34b84e7ae9125f2e368d5390lgao " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR, 523e99020dbf0a159e34b84e7ae9125f2e368d5390lgao#endif 533e99020dbf0a159e34b84e7ae9125f2e368d5390lgao 543e99020dbf0a159e34b84e7ae9125f2e368d5390lgao "", 553e99020dbf0a159e34b84e7ae9125f2e368d5390lgao "Usage:", 563e99020dbf0a159e34b84e7ae9125f2e368d5390lgao " "UTILITY_NAME" [OPTION]... FWTYPE SOURCE [DEST]", 573e99020dbf0a159e34b84e7ae9125f2e368d5390lgao "Description:", 583e99020dbf0a159e34b84e7ae9125f2e368d5390lgao " Converts a pe32/pe32+ SOURCE to DEST with FWTYPE image type.", 593e99020dbf0a159e34b84e7ae9125f2e368d5390lgao "Options:", 603e99020dbf0a159e34b84e7ae9125f2e368d5390lgao " FWTYPE Can be one of APPLICATION, BS_DRIVER, RT_DRIVER, SAL_RT_DRIVER,", 613e99020dbf0a159e34b84e7ae9125f2e368d5390lgao " COMBINED_PEIM_DRIVER, SECURITY_CORE, PEI_CORE, PE32_PEIM and", 623e99020dbf0a159e34b84e7ae9125f2e368d5390lgao " RELOCATABLE_PEIM", 633e99020dbf0a159e34b84e7ae9125f2e368d5390lgao " -t time-date Add Time Stamp for output image", 643e99020dbf0a159e34b84e7ae9125f2e368d5390lgao " -e Not clear ExceptionTable for output image", 653e99020dbf0a159e34b84e7ae9125f2e368d5390lgao " -r Not strip zero pending of .reloc for output image", 663e99020dbf0a159e34b84e7ae9125f2e368d5390lgao NULL 673e99020dbf0a159e34b84e7ae9125f2e368d5390lgao }; 683e99020dbf0a159e34b84e7ae9125f2e368d5390lgao 693e99020dbf0a159e34b84e7ae9125f2e368d5390lgao for (Index = 0; Str[Index] != NULL; Index++) { 703e99020dbf0a159e34b84e7ae9125f2e368d5390lgao fprintf (stdout, "%s\n", Str[Index]); 713e99020dbf0a159e34b84e7ae9125f2e368d5390lgao } 723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang} 733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangstatic 753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangSTATUS 763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangFReadFile ( 773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang FILE *in, 783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang VOID **Buffer, 793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINTN *Length 803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang ) 813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{ 823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fseek (in, 0, SEEK_END); 833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang *Length = ftell (in); 843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang *Buffer = malloc (*Length); 853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fseek (in, 0, SEEK_SET); 863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fread (*Buffer, *Length, 1, in); 873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_SUCCESS; 883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang} 893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangstatic 913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangSTATUS 923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangFWriteFile ( 933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang FILE *out, 943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang VOID *Buffer, 953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINTN Length 963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang ) 973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{ 983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fseek (out, 0, SEEK_SET); 993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fwrite (Buffer, Length, 1, out); 1003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if ((ULONG) ftell (out) != Length) { 1013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Error (NULL, 0, 0, "write error", NULL); 1023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_ERROR; 1033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 1043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang free (Buffer); 1053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_SUCCESS; 1063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang} 1073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangVOID 1093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangZeroExceptionTable ( 1103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang IN UINT8 *FileBuffer, 1113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang IN EFI_IMAGE_DOS_HEADER *DosHdr, 1123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang IN PE_HEADER *PeHdr 1133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang ) 1143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{ 1153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINT32 PdataSize; 1163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINT32 PdataOffset; 1173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINT32 PdataRVASize; 1183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINT32 PdataRVA; 1193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINT32 SectionOffset; 1203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINT16 SectionNumber; 1213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINT32 SectionNameSize; 1223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang EFI_IMAGE_SECTION_HEADER *Section; 1233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PdataSize = 0; 1253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PdataOffset = 0; 1263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PdataRVASize = 0; 1273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PdataRVA = 0; 1283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionOffset = 0; 1293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 1313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Search .pdata section 1323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 1333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { 1343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if ((PeHdr->PeHeader32.OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXCEPTION) && 1353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang (PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0) && 1363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang (PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0)) { 1373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PdataRVA = PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress; 1393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PdataRVASize = PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size; 1403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0; 1423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0; 1433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionOffset = sizeof(PeHdr->PeHeader32); 1453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 1463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } else { 1473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if ((PeHdr->PeHeader64.OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXCEPTION) && 1483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang (PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0) && 1493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang (PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0)) { 1503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PdataRVA = PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress; 1523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PdataRVASize = PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size; 1533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0; 1553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0; 1563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionOffset = sizeof(PeHdr->PeHeader64); 1583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 1593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 1603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if ((PdataRVASize != 0) && (PdataRVA != 0)) { 1623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionNumber = PeHdr->PeHeader32.FileHeader.NumberOfSections; 1643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionNameSize = sizeof(Section->Name); 1653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang while (SectionNumber > 0) { 1663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Section = (EFI_IMAGE_SECTION_HEADER *) &FileBuffer[DosHdr->e_lfanew + SectionOffset]; 1673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (strcmp (Section->Name, ".pdata") == 0) { 1683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 1693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Zero .pdata Section Header Name 1703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 1713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang memset ( 1723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang FileBuffer + DosHdr->e_lfanew + SectionOffset, 1733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 0, 1743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionNameSize); 1753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 1773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Zero .pdata Secton raw data 1783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 1793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PdataOffset = Section->PointerToRawData; 1803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PdataSize = Section->SizeOfRawData; 1813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang memset (FileBuffer + PdataOffset, 0, PdataSize); 1823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang break; 1833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 1843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionNumber--; 1853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionOffset += sizeof(EFI_IMAGE_SECTION_HEADER); 1863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 1873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 1883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return ; 1903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang} 1913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 1923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangVOID 1933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangStripZeroPendingReloc ( 1943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang IN UINT8 *FileBuffer, 1953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang IN OUT UINTN *FileLength, 1963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang IN EFI_IMAGE_DOS_HEADER *DosHdr, 1973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang IN PE_HEADER *PeHdr 1983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang ) 1993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{ 2003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang EFI_IMAGE_OPTIONAL_HEADER32 *Optional32; 2013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang EFI_IMAGE_OPTIONAL_HEADER64 *Optional64; 2023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang EFI_IMAGE_SECTION_HEADER *SectionHeader; 2033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINTN AllignedRelocSize; 2043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINTN Index; 2053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 2063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { 2073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->PeHeader32.OptionalHeader; 2083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if ((Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) && 2093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)) { 2103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->PeHeader32.FileHeader.SizeOfOptionalHeader); 2113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang for (Index = 0; Index < PeHdr->PeHeader32.FileHeader.NumberOfSections; Index++, SectionHeader++) { 2123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory 2143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (strcmp (SectionHeader->Name, ".reloc") == 0) { 2163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; 2173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 2183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + 2193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1)); 2203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Check to see if there is zero padding at the end of the base relocations 2223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (AllignedRelocSize < SectionHeader->SizeOfRawData) { 2243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Check to see if the base relocations are at the end of the file 2263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) { 2283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // All the required conditions are met to strip the zero padding of the end of the base relocations section 2303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize); 2323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize); 2333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionHeader->SizeOfRawData = AllignedRelocSize; 2343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang *FileLength = Optional32->SizeOfImage; 2353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 2363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 2373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 2383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 2393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 2403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } else { 2413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->PeHeader64.OptionalHeader; 2423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if ((Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) && 2433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)) { 2443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->PeHeader64.FileHeader.SizeOfOptionalHeader); 2453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang for (Index = 0; Index < PeHdr->PeHeader64.FileHeader.NumberOfSections; Index++, SectionHeader++) { 2463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory 2483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (strcmp (SectionHeader->Name, ".reloc") == 0) { 2503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; 2513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 2523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + 2533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1)); 2543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Check to see if there is zero padding at the end of the base relocations 2563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (AllignedRelocSize < SectionHeader->SizeOfRawData) { 2583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Check to see if the base relocations are at the end of the file 2603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) { 2623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // All the required conditions are met to strip the zero padding of the end of the base relocations section 2643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 2653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize); 2663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize); 2673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SectionHeader->SizeOfRawData = AllignedRelocSize; 2683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang *FileLength = Optional64->SizeOfImage; 2693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 2703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 2713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 2723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 2733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 2743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 2753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang} 2763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 2773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangint 2783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangmain ( 2793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang int argc, 2803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang char *argv[] 2813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang ) 2823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++ 2833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 2843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description: 2853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 2863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Main function. 2873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 2883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments: 2893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 2903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang argc - Number of command line parameters. 2913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang argv - Array of pointers to command line parameter strings. 2923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 2933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns: 2943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 2953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang STATUS_SUCCESS - Utility exits successfully. 2963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang STATUS_ERROR - Some error occurred during execution. 2973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 2983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/ 2993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{ 3003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang ULONG Type; 3013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PUCHAR Ext; 3023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PUCHAR p; 3033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PUCHAR pe; 3043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PUCHAR OutImageName; 3053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UCHAR outname[500]; 3063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang FILE *fpIn; 3073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang FILE *fpOut; 3083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang EFI_IMAGE_DOS_HEADER *DosHdr; 3093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PE_HEADER *PeHdr; 3103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang time_t TimeStamp; 3113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang struct tm TimeStruct; 3123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang EFI_IMAGE_DOS_HEADER BackupDosHdr; 3133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang ULONG Index; 3143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang BOOLEAN TimeStampPresent; 3153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang BOOLEAN NeedClearExceptionTable; 3163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang BOOLEAN NeedStripZeroPendingReloc; 3173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINT8 *FileBuffer; 3183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang UINTN FileLength; 3193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang EFI_IMAGE_OPTIONAL_HEADER32 *Optional32; 3203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang EFI_IMAGE_OPTIONAL_HEADER64 *Optional64; 3213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 3223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang SetUtilityName (UTILITY_NAME); 3233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Assign to fix compile warning 3253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang OutImageName = NULL; 3273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Type = 0; 3283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Ext = 0; 3293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang TimeStamp = 0; 3303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang TimeStampPresent = FALSE; 3313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 3323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang NeedClearExceptionTable = TRUE; 3333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang NeedStripZeroPendingReloc = TRUE; 3343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 3353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Look for -t time-date option first. If the time is "0", then 3373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // skip it. 3383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if ((argc > 2) && !strcmp (argv[1], "-t")) { 3403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang TimeStampPresent = TRUE; 3413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (strcmp (argv[2], "0") != 0) { 3423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Convert the string to a value 3443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang memset ((char *) &TimeStruct, 0, sizeof (TimeStruct)); 3463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (sscanf( 3473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang argv[2], "%d/%d/%d,%d:%d:%d", 3483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang &TimeStruct.tm_mon, /* months since January - [0,11] */ 3493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang &TimeStruct.tm_mday, /* day of the month - [1,31] */ 3503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang &TimeStruct.tm_year, /* years since 1900 */ 3513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang &TimeStruct.tm_hour, /* hours since midnight - [0,23] */ 3523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang &TimeStruct.tm_min, /* minutes after the hour - [0,59] */ 3533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang &TimeStruct.tm_sec /* seconds after the minute - [0,59] */ 3543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang ) != 6) { 3553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format"); 3563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_ERROR; 3573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 3583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Now fixup some of the fields 3603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang TimeStruct.tm_mon--; 3623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang TimeStruct.tm_year -= 1900; 3633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Sanity-check values? 3653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Convert 3663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang TimeStamp = mktime (&TimeStruct); 3683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (TimeStamp == (time_t) - 1) { 3693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Error (NULL, 0, 0, argv[2], "failed to convert time"); 3703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_ERROR; 3713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 3723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 3733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Skip over the args 3753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang argc -= 2; 3773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang argv += 2; 3783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 3793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 3803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Look for -e option. 3823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if ((argc > 1) && !strcmp (argv[1], "-e")) { 3843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang NeedClearExceptionTable = FALSE; 3853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Skip over the args 3873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang argc -= 1; 3893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang argv += 1; 3903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 3913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 3923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Look for -r option 3943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if ((argc > 1) && !strcmp (argv[1], "-r")) { 3963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang NeedStripZeroPendingReloc = FALSE; 3973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 3983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Skip over the args 3993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 4003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang argc -= 1; 4013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang argv += 1; 4023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 4043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 4053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Check for enough args 4063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 4073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (argc < 3) { 4083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Usage (); 4093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_ERROR; 4103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 4123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (argc == 4) { 4133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang OutImageName = argv[3]; 4143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 4163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Get new image type 4173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 4183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang p = argv[1]; 4193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (*p == '/' || *p == '\\') { 4203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang p += 1; 4213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 4233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (_stricmp (p, "app") == 0 || _stricmp (p, "APPLICATION") == 0) { 4243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION; 4253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Ext = ".efi"; 4263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 4273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } else if (_stricmp (p, "bsdrv") == 0 || _stricmp (p, "BS_DRIVER") == 0) { 4283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; 4293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Ext = ".efi"; 4303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 4313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } else if (_stricmp (p, "rtdrv") == 0 || _stricmp (p, "RT_DRIVER") == 0) { 4323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER; 4333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Ext = ".efi"; 4343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 4353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } else if (_stricmp (p, "rtdrv") == 0 || _stricmp (p, "SAL_RT_DRIVER") == 0) { 4363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; 4373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Ext = ".efi"; 4383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } else if (_stricmp (p, "SECURITY_CORE") == 0) { 4393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; 4403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Ext = ".sec"; 4413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } else if (_stricmp (p, "peim") == 0 || 4423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang _stricmp (p, "PEI_CORE") == 0 || 4433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang _stricmp (p, "PE32_PEIM") == 0 || 4443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang _stricmp (p, "RELOCATABLE_PEIM") == 0 || 4453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang _stricmp (p, "combined_peim_driver") == 0 4463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang ) { 4473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; 4483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Ext = ".pei"; 4493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } else { 4503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Usage (); 4513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_ERROR; 4523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 4543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // open source file 4553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 4563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fpIn = fopen (argv[2], "rb"); 4573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (!fpIn) { 4583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Error (NULL, 0, 0, argv[2], "failed to open input file for reading"); 4593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_ERROR; 4603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength); 4623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 4633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Read the dos & pe hdrs of the image 4643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 4653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer; 4663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (DosHdr->e_magic != IMAGE_DOS_SIGNATURE) { 4673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image"); 4683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fclose (fpIn); 4693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_ERROR; 4703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 4723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PeHdr = (PE_HEADER *)(FileBuffer + DosHdr->e_lfanew); 4733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (PeHdr->PeHeader32.Signature != IMAGE_NT_SIGNATURE) { 4743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Error (NULL, 0, 0, argv[2], "PE header signature not found in source image"); 4753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fclose (fpIn); 4763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_ERROR; 4773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 4793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // open output file 4803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 4813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang strcpy (outname, argv[2]); 4823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang pe = NULL; 4833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang for (p = outname; *p; p++) { 4843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (*p == '.') { 4853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang pe = p; 4863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 4893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (!pe) { 4903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang pe = p; 4913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 4933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang strcpy (pe, Ext); 4943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 4953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (!OutImageName) { 4963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang OutImageName = outname; 4973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 4983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 4993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fpOut = fopen (OutImageName, "w+b"); 5003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (!fpOut) { 5013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Error (NULL, 0, 0, OutImageName, "could not open output file for writing"); 5023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fclose (fpIn); 5033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_ERROR; 5043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 5053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Zero all unused fields of the DOS header 5073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER)); 5093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER)); 5103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang DosHdr->e_magic = BackupDosHdr.e_magic; 5113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang DosHdr->e_lfanew = BackupDosHdr.e_lfanew; 5123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 5133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) { 5143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang FileBuffer[Index] = (UINT8) DosHdr->e_cp; 5153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 5163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 5173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Modify some fields in the PE header 5193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 5213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // TimeDateStamp's offset is fixed for PE32/32+ 5233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (TimeStampPresent) { 5253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang PeHdr->PeHeader32.FileHeader.TimeDateStamp = (UINT32) TimeStamp; 5263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 5273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 5283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // PE32/32+ has different optional header layout 5303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Determine format is PE32 or PE32+ before modification 5313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { 5333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // PE32 image 5353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->PeHeader32.OptionalHeader; 5373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 5383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->MajorLinkerVersion = 0; 5393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->MinorLinkerVersion = 0; 5403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->MajorOperatingSystemVersion = 0; 5413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->MinorOperatingSystemVersion = 0; 5423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->MajorImageVersion = 0; 5433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->MinorImageVersion = 0; 5443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->MajorSubsystemVersion = 0; 5453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->MinorSubsystemVersion = 0; 5463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->Win32VersionValue = 0; 5473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->CheckSum = 0; 5483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->SizeOfStackReserve = 0; 5493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->SizeOfStackCommit = 0; 5503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->SizeOfHeapReserve = 0; 5513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->SizeOfHeapCommit = 0; 5523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional32->Subsystem = (USHORT) Type; 5533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 5543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Strip zero padding at the end of the .reloc section 5563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (NeedStripZeroPendingReloc) { 5583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang StripZeroPendingReloc (FileBuffer, &FileLength, DosHdr, PeHdr); 5593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 5603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } else if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { 5613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // PE32+ image 5633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->PeHeader64.OptionalHeader; 5653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 5663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->MajorLinkerVersion = 0; 5673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->MinorLinkerVersion = 0; 5683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->MajorOperatingSystemVersion = 0; 5693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->MinorOperatingSystemVersion = 0; 5703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->MajorImageVersion = 0; 5713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->MinorImageVersion = 0; 5723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->MajorSubsystemVersion = 0; 5733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->MinorSubsystemVersion = 0; 5743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->Win32VersionValue = 0; 5753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->CheckSum = 0; 5763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->SizeOfStackReserve = 0; 5773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->SizeOfStackCommit = 0; 5783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->SizeOfHeapReserve = 0; 5793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->SizeOfHeapCommit = 0; 5803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Optional64->Subsystem = (USHORT) Type; 5813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 5823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Strip zero padding at the end of the .reloc section 5843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (NeedStripZeroPendingReloc) { 5863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang StripZeroPendingReloc (FileBuffer, &FileLength, DosHdr, PeHdr); 5873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 5883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } else { 5893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang Error (NULL, 0, 0, argv[2], "Unsupported PE image"); 5903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fclose (fpIn); 5913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fclose (fpOut); 5923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_ERROR; 5933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 5943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 5953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Zero PDATA section for smaller binary size after compression 5973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 5983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang if (NeedClearExceptionTable) { 5993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang ZeroExceptionTable (FileBuffer, DosHdr, PeHdr); 6003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang } 6013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 6023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang FWriteFile (fpOut, FileBuffer, FileLength); 6033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 6043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 6053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // Done 6063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang // 6073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fclose (fpIn); 6083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang fclose (fpOut); 6093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang 6103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang return STATUS_SUCCESS; 6113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang} 612