3 Copyright (c) 2004, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Converts a pe32+ image to an FW image type
22 #include "WinNtInclude.h"
32 #include <Common/UefiBaseTypes.h>
33 #include <Common/EfiImage.h>
35 #include "CommonLib.h"
36 #include "EfiUtilityMsgs.c"
38 #define UTILITY_NAME "FwImage"
41 typedef unsigned long ULONG
;
42 typedef unsigned char UCHAR
;
43 typedef unsigned char *PUCHAR
;
44 typedef unsigned short USHORT
;
52 printf ("Usage: " UTILITY_NAME
" {-t time-date} [BASE|SEC|PEI_CORE|PEIM|DXE_CORE|DXE_DRIVER|DXE_RUNTIME_DRIVER|DXE_SAL_DRIVER|DXE_SMM_DRIVER|TOOL|UEFI_DRIVER|UEFI_APPLICATION|USER_DEFINED] peimage [outimage]");
65 UCHAR Buffer
[8 * 1024];
67 fseek (in
, 0, SEEK_END
);
68 filesize
= ftell (in
);
70 fseek (in
, 0, SEEK_SET
);
71 fseek (out
, 0, SEEK_SET
);
74 while (offset
< filesize
) {
75 length
= sizeof (Buffer
);
76 if (filesize
- offset
< length
) {
77 length
= filesize
- offset
;
80 fread (Buffer
, length
, 1, in
);
81 fwrite (Buffer
, length
, 1, out
);
85 if ((ULONG
) ftell (out
) != filesize
) {
86 Error (NULL
, 0, 0, "write error", NULL
);
90 return STATUS_SUCCESS
;
101 fseek (in
, 0, SEEK_END
);
102 *Length
= ftell (in
);
103 *Buffer
= malloc (*Length
);
104 fseek (in
, 0, SEEK_SET
);
105 fread (*Buffer
, *Length
, 1, in
);
106 return STATUS_SUCCESS
;
117 fseek (out
, 0, SEEK_SET
);
118 fwrite (Buffer
, Length
, 1, out
);
119 if ((ULONG
) ftell (out
) != Length
) {
120 Error (NULL
, 0, 0, "write error", NULL
);
124 return STATUS_SUCCESS
;
140 argc - Number of command line parameters.
141 argv - Array of pointers to command line parameter strings.
144 STATUS_SUCCESS - Utility exits successfully.
145 STATUS_ERROR - Some error occurred during execution.
158 EFI_IMAGE_DOS_HEADER
*DosHdr
;
159 EFI_IMAGE_NT_HEADERS
*PeHdr
;
160 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
161 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
163 struct tm TimeStruct
;
164 EFI_IMAGE_DOS_HEADER BackupDosHdr
;
167 BOOLEAN TimeStampPresent
;
170 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
174 SetUtilityName (UTILITY_NAME
);
176 // Assign to fix compile warning
182 TimeStampPresent
= FALSE
;
185 // Look for -t time-date option first. If the time is "0", then
188 if ((argc
> 2) && !strcmp (argv
[1], "-t")) {
189 TimeStampPresent
= TRUE
;
190 if (strcmp (argv
[2], "0") != 0) {
192 // Convert the string to a value
194 memset ((char *) &TimeStruct
, 0, sizeof (TimeStruct
));
196 argv
[2], "%d/%d/%d,%d:%d:%d",
197 &TimeStruct
.tm_mon
, /* months since January - [0,11] */
198 &TimeStruct
.tm_mday
, /* day of the month - [1,31] */
199 &TimeStruct
.tm_year
, /* years since 1900 */
200 &TimeStruct
.tm_hour
, /* hours since midnight - [0,23] */
201 &TimeStruct
.tm_min
, /* minutes after the hour - [0,59] */
202 &TimeStruct
.tm_sec
/* seconds after the minute - [0,59] */
204 Error (NULL
, 0, 0, argv
[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");
208 // Now fixup some of the fields
211 TimeStruct
.tm_year
-= 1900;
213 // Sanity-check values?
216 TimeStamp
= mktime (&TimeStruct
);
217 if (TimeStamp
== (time_t) - 1) {
218 Error (NULL
, 0, 0, argv
[2], "failed to convert time");
223 // Skip over the args
229 // Check for enough args
237 OutImageName
= argv
[3];
240 // Get new image type
243 if (*p
== '/' || *p
== '\\') {
247 if (stricmp (p
, "app") == 0 || stricmp (p
, "UEFI_APPLICATION") == 0) {
248 Type
= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
251 } else if (stricmp (p
, "bsdrv") == 0 || stricmp (p
, "DXE_DRIVER") == 0) {
252 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
255 } else if (stricmp (p
, "rtdrv") == 0 || stricmp (p
, "DXE_RUNTIME_DRIVER") == 0) {
256 Type
= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
;
259 } else if (stricmp (p
, "rtdrv") == 0 || stricmp (p
, "DXE_SAL_DRIVER") == 0) {
260 Type
= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
;
262 } else if (stricmp (p
, "SEC") == 0) {
263 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
265 } else if (stricmp (p
, "peim") == 0 ||
266 stricmp (p
, "BASE") == 0 ||
267 stricmp (p
, "PEI_CORE") == 0 ||
268 stricmp (p
, "PEIM") == 0 ||
269 stricmp (p
, "DXE_SMM_DRIVER") == 0 ||
270 stricmp (p
, "TOOL") == 0 ||
271 stricmp (p
, "UEFI_APPLICATION") == 0 ||
272 stricmp (p
, "USER_DEFINED") == 0 ||
273 stricmp (p
, "UEFI_DRIVER") == 0 ||
274 stricmp (p
, "DXE_CORE") == 0
276 Type
= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
;
286 fpIn
= fopen (argv
[2], "rb");
288 Error (NULL
, 0, 0, argv
[2], "failed to open input file for reading");
292 FReadFile (fpIn
, (VOID
**)&FileBuffer
, &FileLength
);
295 // Read the dos & pe hdrs of the image
297 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)FileBuffer
;
298 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
299 Error (NULL
, 0, 0, argv
[2], "DOS header signature not found in source image");
304 PeHdr
= (EFI_IMAGE_NT_HEADERS
*)(FileBuffer
+ DosHdr
->e_lfanew
);
305 if (PeHdr
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
306 Error (NULL
, 0, 0, argv
[2], "PE header signature not found in source image");
314 strcpy (outname
, argv
[2]);
316 for (p
= outname
; *p
; p
++) {
329 OutImageName
= outname
;
332 fpOut
= fopen (OutImageName
, "w+b");
334 Error (NULL
, 0, 0, OutImageName
, "could not open output file for writing");
340 // Zero all unused fields of the DOS header
342 memcpy (&BackupDosHdr
, DosHdr
, sizeof (EFI_IMAGE_DOS_HEADER
));
343 memset (DosHdr
, 0, sizeof (EFI_IMAGE_DOS_HEADER
));
344 DosHdr
->e_magic
= BackupDosHdr
.e_magic
;
345 DosHdr
->e_lfanew
= BackupDosHdr
.e_lfanew
;
347 for (Index
= sizeof (EFI_IMAGE_DOS_HEADER
); Index
< (ULONG
) DosHdr
->e_lfanew
; Index
++) {
348 FileBuffer
[Index
] = DosHdr
->e_cp
;
352 // Path the PE header
354 PeHdr
->OptionalHeader
.Subsystem
= (USHORT
) Type
;
355 if (TimeStampPresent
) {
356 PeHdr
->FileHeader
.TimeDateStamp
= (UINT32
) TimeStamp
;
360 if (PeHdr
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
361 Optional32
= (EFI_IMAGE_OPTIONAL_HEADER32
*)&PeHdr
->OptionalHeader
;
362 Optional32
->MajorLinkerVersion
= 0;
363 Optional32
->MinorLinkerVersion
= 0;
364 Optional32
->MajorOperatingSystemVersion
= 0;
365 Optional32
->MinorOperatingSystemVersion
= 0;
366 Optional32
->MajorImageVersion
= 0;
367 Optional32
->MinorImageVersion
= 0;
368 Optional32
->MajorSubsystemVersion
= 0;
369 Optional32
->MinorSubsystemVersion
= 0;
370 Optional32
->Win32VersionValue
= 0;
371 Optional32
->CheckSum
= 0;
372 Optional32
->SizeOfStackReserve
= 0;
373 Optional32
->SizeOfStackCommit
= 0;
374 Optional32
->SizeOfHeapReserve
= 0;
375 Optional32
->SizeOfHeapCommit
= 0;
378 // Zero the .pdata section if the machine type is X64 and the Debug Directoty entry is empty
380 if (PeHdr
->FileHeader
.Machine
== 0x8664) { // X64
381 if (Optional32
->NumberOfRvaAndSizes
>= 4) {
382 if (Optional32
->NumberOfRvaAndSizes
< 7 || (Optional32
->NumberOfRvaAndSizes
>= 7 && Optional32
->DataDirectory
[6].Size
== 0)) {
383 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof(UINT32
) + sizeof (EFI_IMAGE_FILE_HEADER
) + PeHdr
->FileHeader
.SizeOfOptionalHeader
);
384 for (Index
= 0; Index
< PeHdr
->FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
385 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[3].VirtualAddress
) {
386 for (Index1
= 0; Index1
< Optional32
->DataDirectory
[3].Size
; Index1
++) {
387 FileBuffer
[SectionHeader
->PointerToRawData
+ Index1
] = 0;
391 Optional32
->DataDirectory
[3].Size
= 0;
392 Optional32
->DataDirectory
[3].VirtualAddress
= 0;
398 // Strip zero padding at the end of the .reloc section
400 if (Optional32
->NumberOfRvaAndSizes
>= 6) {
401 if (Optional32
->DataDirectory
[5].Size
!= 0) {
402 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof(UINT32
) + sizeof (EFI_IMAGE_FILE_HEADER
) + PeHdr
->FileHeader
.SizeOfOptionalHeader
);
403 for (Index
= 0; Index
< PeHdr
->FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
404 if (SectionHeader
->VirtualAddress
== Optional32
->DataDirectory
[5].VirtualAddress
) {
405 FileLength
= SectionHeader
->PointerToRawData
+ Optional32
->DataDirectory
[5].Size
;
406 FileLength
= (FileLength
+ 7) & 0xfffffff8;
407 RelocSize
= FileLength
- SectionHeader
->PointerToRawData
;
413 if (PeHdr
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
414 Optional64
= (EFI_IMAGE_OPTIONAL_HEADER64
*)&PeHdr
->OptionalHeader
;
415 Optional64
->MajorLinkerVersion
= 0;
416 Optional64
->MinorLinkerVersion
= 0;
417 Optional64
->MajorOperatingSystemVersion
= 0;
418 Optional64
->MinorOperatingSystemVersion
= 0;
419 Optional64
->MajorImageVersion
= 0;
420 Optional64
->MinorImageVersion
= 0;
421 Optional64
->MajorSubsystemVersion
= 0;
422 Optional64
->MinorSubsystemVersion
= 0;
423 Optional64
->Win32VersionValue
= 0;
424 Optional64
->CheckSum
= 0;
425 Optional64
->SizeOfStackReserve
= 0;
426 Optional64
->SizeOfStackCommit
= 0;
427 Optional64
->SizeOfHeapReserve
= 0;
428 Optional64
->SizeOfHeapCommit
= 0;
431 // Zero the .pdata section if the machine type is X64 and the Debug Directory is empty
433 if (PeHdr
->FileHeader
.Machine
== 0x8664) { // X64
434 if (Optional64
->NumberOfRvaAndSizes
>= 4) {
435 if (Optional64
->NumberOfRvaAndSizes
< 7 || (Optional64
->NumberOfRvaAndSizes
>= 7 && Optional64
->DataDirectory
[6].Size
== 0)) {
436 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof(UINT32
) + sizeof (EFI_IMAGE_FILE_HEADER
) + PeHdr
->FileHeader
.SizeOfOptionalHeader
);
437 for (Index
= 0; Index
< PeHdr
->FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
438 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[3].VirtualAddress
) {
439 for (Index1
= 0; Index1
< Optional64
->DataDirectory
[3].Size
; Index1
++) {
440 FileBuffer
[SectionHeader
->PointerToRawData
+ Index1
] = 0;
444 Optional64
->DataDirectory
[3].Size
= 0;
445 Optional64
->DataDirectory
[3].VirtualAddress
= 0;
451 // Strip zero padding at the end of the .reloc section
453 if (Optional64
->NumberOfRvaAndSizes
>= 6) {
454 if (Optional64
->DataDirectory
[5].Size
!= 0) {
455 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof(UINT32
) + sizeof (EFI_IMAGE_FILE_HEADER
) + PeHdr
->FileHeader
.SizeOfOptionalHeader
);
456 for (Index
= 0; Index
< PeHdr
->FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
457 if (SectionHeader
->VirtualAddress
== Optional64
->DataDirectory
[5].VirtualAddress
) {
458 FileLength
= SectionHeader
->PointerToRawData
+ Optional64
->DataDirectory
[5].Size
;
459 FileLength
= (FileLength
+ 7) & 0xfffffff8;
460 RelocSize
= FileLength
- SectionHeader
->PointerToRawData
;
467 if (RelocSize
!= 0) {
468 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*)(FileBuffer
+ DosHdr
->e_lfanew
+ sizeof(UINT32
) + sizeof (EFI_IMAGE_FILE_HEADER
) + PeHdr
->FileHeader
.SizeOfOptionalHeader
);
469 for (Index
= 0; Index
< PeHdr
->FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
470 if (strcmp(SectionHeader
->Name
, ".reloc") == 0) {
471 SectionHeader
->Misc
.VirtualSize
= (RelocSize
+ 0x1f) & 0xffffffe0;
472 SectionHeader
->SizeOfRawData
= RelocSize
;
477 FWriteFile (fpOut
, FileBuffer
, FileLength
);
485 // printf ("Created %s\n", OutImageName);
487 return STATUS_SUCCESS
;