]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - Tools/Source/TianoTools/FwImage/fwimage.c
Add EntryPointLib class once ImageEntryPoint is found in inf file.
[mirror_edk2.git] / Tools / Source / TianoTools / FwImage / fwimage.c
... / ...
CommitLineData
1/*++\r
2\r
3Copyright (c) 2004, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 fwimage.c\r
15\r
16Abstract:\r
17\r
18 Converts a pe32+ image to an FW image type\r
19\r
20--*/\r
21\r
22#include "WinNtInclude.h"\r
23\r
24#ifndef __GNUC__\r
25#include <windows.h>\r
26#endif\r
27#include <stdio.h>\r
28#include <stdlib.h>\r
29#include <string.h>\r
30#include <time.h>\r
31\r
32#include <Common/UefiBaseTypes.h>\r
33#include <Common/EfiImage.h>\r
34\r
35#include "CommonLib.h"\r
36#include "EfiUtilityMsgs.c"\r
37\r
38#define UTILITY_NAME "FwImage"\r
39\r
40#ifdef __GNUC__\r
41typedef unsigned long ULONG;\r
42typedef unsigned char UCHAR;\r
43typedef unsigned char *PUCHAR;\r
44typedef unsigned short USHORT;\r
45#endif\r
46\r
47VOID\r
48Usage (\r
49 VOID\r
50 )\r
51{\r
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]");\r
53}\r
54\r
55static\r
56STATUS\r
57FCopyFile (\r
58 FILE *in,\r
59 FILE *out\r
60 )\r
61{\r
62 ULONG filesize;\r
63 ULONG offset;\r
64 ULONG length;\r
65 UCHAR Buffer[8 * 1024];\r
66\r
67 fseek (in, 0, SEEK_END);\r
68 filesize = ftell (in);\r
69\r
70 fseek (in, 0, SEEK_SET);\r
71 fseek (out, 0, SEEK_SET);\r
72\r
73 offset = 0;\r
74 while (offset < filesize) {\r
75 length = sizeof (Buffer);\r
76 if (filesize - offset < length) {\r
77 length = filesize - offset;\r
78 }\r
79\r
80 fread (Buffer, length, 1, in);\r
81 fwrite (Buffer, length, 1, out);\r
82 offset += length;\r
83 }\r
84\r
85 if ((ULONG) ftell (out) != filesize) {\r
86 Error (NULL, 0, 0, "write error", NULL);\r
87 return STATUS_ERROR;\r
88 }\r
89\r
90 return STATUS_SUCCESS;\r
91}\r
92\r
93static\r
94STATUS\r
95FReadFile (\r
96 FILE *in,\r
97 VOID **Buffer,\r
98 UINTN *Length\r
99 )\r
100{\r
101 fseek (in, 0, SEEK_END);\r
102 *Length = ftell (in);\r
103 *Buffer = malloc (*Length);\r
104 fseek (in, 0, SEEK_SET);\r
105 fread (*Buffer, *Length, 1, in);\r
106 return STATUS_SUCCESS;\r
107}\r
108\r
109static\r
110STATUS\r
111FWriteFile (\r
112 FILE *out,\r
113 VOID *Buffer,\r
114 UINTN Length\r
115 )\r
116{\r
117 fseek (out, 0, SEEK_SET);\r
118 fwrite (Buffer, Length, 1, out);\r
119 if ((ULONG) ftell (out) != Length) {\r
120 Error (NULL, 0, 0, "write error", NULL);\r
121 return STATUS_ERROR;\r
122 }\r
123 free (Buffer);\r
124 return STATUS_SUCCESS;\r
125}\r
126\r
127int\r
128main (\r
129 int argc,\r
130 char *argv[]\r
131 )\r
132/*++\r
133\r
134Routine Description:\r
135\r
136 Main function.\r
137\r
138Arguments:\r
139\r
140 argc - Number of command line parameters.\r
141 argv - Array of pointers to command line parameter strings.\r
142\r
143Returns:\r
144 STATUS_SUCCESS - Utility exits successfully.\r
145 STATUS_ERROR - Some error occurred during execution.\r
146\r
147--*/\r
148{\r
149 ULONG Type;\r
150 PUCHAR Ext;\r
151 PUCHAR p;\r
152 PUCHAR pe;\r
153 PUCHAR OutImageName;\r
154 UCHAR outname[500];\r
155 FILE *fpIn;\r
156 FILE *fpOut;\r
157 VOID *ZeroBuffer;\r
158 EFI_IMAGE_DOS_HEADER *DosHdr;\r
159 EFI_IMAGE_NT_HEADERS *PeHdr;\r
160 EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;\r
161 EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;\r
162 time_t TimeStamp;\r
163 struct tm TimeStruct;\r
164 EFI_IMAGE_DOS_HEADER BackupDosHdr;\r
165 ULONG Index;\r
166 ULONG Index1;\r
167 BOOLEAN TimeStampPresent;\r
168 UINTN RelocSize;\r
169 UINTN Delta;\r
170 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
171 UINT8 *FileBuffer;\r
172 UINTN FileLength;\r
173\r
174 SetUtilityName (UTILITY_NAME);\r
175 //\r
176 // Assign to fix compile warning\r
177 //\r
178 OutImageName = NULL;\r
179 Type = 0;\r
180 Ext = 0;\r
181 TimeStamp = 0;\r
182 TimeStampPresent = FALSE;\r
183\r
184 //\r
185 // Look for -t time-date option first. If the time is "0", then\r
186 // skip it.\r
187 //\r
188 if ((argc > 2) && !strcmp (argv[1], "-t")) {\r
189 TimeStampPresent = TRUE;\r
190 if (strcmp (argv[2], "0") != 0) {\r
191 //\r
192 // Convert the string to a value\r
193 //\r
194 memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));\r
195 if (sscanf(\r
196 argv[2], "%d/%d/%d,%d:%d:%d",\r
197 &TimeStruct.tm_mon, /* months since January - [0,11] */\r
198 &TimeStruct.tm_mday, /* day of the month - [1,31] */\r
199 &TimeStruct.tm_year, /* years since 1900 */\r
200 &TimeStruct.tm_hour, /* hours since midnight - [0,23] */\r
201 &TimeStruct.tm_min, /* minutes after the hour - [0,59] */\r
202 &TimeStruct.tm_sec /* seconds after the minute - [0,59] */\r
203 ) != 6) {\r
204 Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");\r
205 return STATUS_ERROR;\r
206 }\r
207 //\r
208 // Now fixup some of the fields\r
209 //\r
210 TimeStruct.tm_mon--;\r
211 TimeStruct.tm_year -= 1900;\r
212 //\r
213 // Sanity-check values?\r
214 // Convert\r
215 //\r
216 TimeStamp = mktime (&TimeStruct);\r
217 if (TimeStamp == (time_t) - 1) {\r
218 Error (NULL, 0, 0, argv[2], "failed to convert time");\r
219 return STATUS_ERROR;\r
220 }\r
221 }\r
222 //\r
223 // Skip over the args\r
224 //\r
225 argc -= 2;\r
226 argv += 2;\r
227 }\r
228 //\r
229 // Check for enough args\r
230 //\r
231 if (argc < 3) {\r
232 Usage ();\r
233 return STATUS_ERROR;\r
234 }\r
235\r
236 if (argc == 4) {\r
237 OutImageName = argv[3];\r
238 }\r
239 //\r
240 // Get new image type\r
241 //\r
242 p = argv[1];\r
243 if (*p == '/' || *p == '\\') {\r
244 p += 1;\r
245 }\r
246\r
247 if (stricmp (p, "app") == 0 || stricmp (p, "UEFI_APPLICATION") == 0) {\r
248 Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
249 Ext = ".efi";\r
250\r
251 } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "DXE_DRIVER") == 0) {\r
252 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
253 Ext = ".efi";\r
254\r
255 } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_RUNTIME_DRIVER") == 0) {\r
256 Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
257 Ext = ".efi";\r
258\r
259 } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_SAL_DRIVER") == 0) {\r
260 Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
261 Ext = ".efi";\r
262 } else if (stricmp (p, "SEC") == 0) {\r
263 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
264 Ext = ".sec";\r
265 } else if (stricmp (p, "peim") == 0 ||\r
266 stricmp (p, "BASE") == 0 ||\r
267 stricmp (p, "PEI_CORE") == 0 ||\r
268 stricmp (p, "PEIM") == 0 ||\r
269 stricmp (p, "DXE_SMM_DRIVER") == 0 ||\r
270 stricmp (p, "TOOL") == 0 ||\r
271 stricmp (p, "UEFI_APPLICATION") == 0 ||\r
272 stricmp (p, "USER_DEFINED") == 0 ||\r
273 stricmp (p, "UEFI_DRIVER") == 0 ||\r
274 stricmp (p, "DXE_CORE") == 0\r
275 ) {\r
276 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
277 Ext = ".pei";\r
278 } else {\r
279 printf ("%s", p);\r
280 Usage ();\r
281 return STATUS_ERROR;\r
282 }\r
283 //\r
284 // open source file\r
285 //\r
286 fpIn = fopen (argv[2], "rb");\r
287 if (!fpIn) {\r
288 Error (NULL, 0, 0, argv[2], "failed to open input file for reading");\r
289 return STATUS_ERROR;\r
290 }\r
291\r
292 FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);\r
293\r
294 //\r
295 // Read the dos & pe hdrs of the image\r
296 //\r
297 DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
298 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
299 Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image");\r
300 fclose (fpIn);\r
301 return STATUS_ERROR;\r
302 }\r
303\r
304 PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r
305 if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
306 Error (NULL, 0, 0, argv[2], "PE header signature not found in source image");\r
307 fclose (fpIn);\r
308 return STATUS_ERROR;\r
309 }\r
310\r
311 //\r
312 // open output file\r
313 //\r
314 strcpy (outname, argv[2]);\r
315 pe = NULL;\r
316 for (p = outname; *p; p++) {\r
317 if (*p == '.') {\r
318 pe = p;\r
319 }\r
320 }\r
321\r
322 if (!pe) {\r
323 pe = p;\r
324 }\r
325\r
326 strcpy (pe, Ext);\r
327\r
328 if (!OutImageName) {\r
329 OutImageName = outname;\r
330 }\r
331\r
332 fpOut = fopen (OutImageName, "w+b");\r
333 if (!fpOut) {\r
334 Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r
335 fclose (fpIn);\r
336 return STATUS_ERROR;\r
337 }\r
338\r
339 //\r
340 // Zero all unused fields of the DOS header\r
341 //\r
342 memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r
343 memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
344 DosHdr->e_magic = BackupDosHdr.e_magic;\r
345 DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
346\r
347 for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) {\r
348 FileBuffer[Index] = DosHdr->e_cp;\r
349 }\r
350\r
351 //\r
352 // Path the PE header\r
353 //\r
354 PeHdr->OptionalHeader.Subsystem = (USHORT) Type;\r
355 if (TimeStampPresent) {\r
356 PeHdr->FileHeader.TimeDateStamp = (UINT32) TimeStamp;\r
357 }\r
358\r
359 RelocSize = 0;\r
360 if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
361 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r
362 Optional32->MajorLinkerVersion = 0;\r
363 Optional32->MinorLinkerVersion = 0;\r
364 Optional32->MajorOperatingSystemVersion = 0;\r
365 Optional32->MinorOperatingSystemVersion = 0;\r
366 Optional32->MajorImageVersion = 0;\r
367 Optional32->MinorImageVersion = 0;\r
368 Optional32->MajorSubsystemVersion = 0;\r
369 Optional32->MinorSubsystemVersion = 0;\r
370 Optional32->Win32VersionValue = 0;\r
371 Optional32->CheckSum = 0;\r
372 Optional32->SizeOfStackReserve = 0;\r
373 Optional32->SizeOfStackCommit = 0;\r
374 Optional32->SizeOfHeapReserve = 0;\r
375 Optional32->SizeOfHeapCommit = 0;\r
376\r
377 //\r
378 // Zero the .pdata section if the machine type is X64 and the Debug Directoty entry is empty\r
379 //\r
380 if (PeHdr->FileHeader.Machine == 0x8664) { // X64\r
381 if (Optional32->NumberOfRvaAndSizes >= 4) {\r
382 if (Optional32->NumberOfRvaAndSizes < 7 || (Optional32->NumberOfRvaAndSizes >= 7 && Optional32->DataDirectory[6].Size == 0)) {\r
383 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
384 for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
385 if (SectionHeader->VirtualAddress == Optional32->DataDirectory[3].VirtualAddress) {\r
386 for (Index1 = 0; Index1 < Optional32->DataDirectory[3].Size; Index1++) {\r
387 FileBuffer[SectionHeader->PointerToRawData + Index1] = 0;\r
388 }\r
389 }\r
390 }\r
391 Optional32->DataDirectory[3].Size = 0;\r
392 Optional32->DataDirectory[3].VirtualAddress = 0;\r
393 }\r
394 }\r
395 }\r
396\r
397 //\r
398 // Strip zero padding at the end of the .reloc section \r
399 //\r
400 if (Optional32->NumberOfRvaAndSizes >= 6) {\r
401 if (Optional32->DataDirectory[5].Size != 0) {\r
402 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
403 for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
404 if (SectionHeader->VirtualAddress == Optional32->DataDirectory[5].VirtualAddress) {\r
405 FileLength = SectionHeader->PointerToRawData + Optional32->DataDirectory[5].Size;\r
406 FileLength = (FileLength + 7) & 0xfffffff8;\r
407 RelocSize = FileLength - SectionHeader->PointerToRawData;\r
408 }\r
409 }\r
410 }\r
411 }\r
412 } \r
413 if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
414 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r
415 Optional64->MajorLinkerVersion = 0;\r
416 Optional64->MinorLinkerVersion = 0;\r
417 Optional64->MajorOperatingSystemVersion = 0;\r
418 Optional64->MinorOperatingSystemVersion = 0;\r
419 Optional64->MajorImageVersion = 0;\r
420 Optional64->MinorImageVersion = 0;\r
421 Optional64->MajorSubsystemVersion = 0;\r
422 Optional64->MinorSubsystemVersion = 0;\r
423 Optional64->Win32VersionValue = 0;\r
424 Optional64->CheckSum = 0;\r
425 Optional64->SizeOfStackReserve = 0;\r
426 Optional64->SizeOfStackCommit = 0;\r
427 Optional64->SizeOfHeapReserve = 0;\r
428 Optional64->SizeOfHeapCommit = 0;\r
429\r
430 //\r
431 // Zero the .pdata section if the machine type is X64 and the Debug Directory is empty\r
432 //\r
433 if (PeHdr->FileHeader.Machine == 0x8664) { // X64\r
434 if (Optional64->NumberOfRvaAndSizes >= 4) {\r
435 if (Optional64->NumberOfRvaAndSizes < 7 || (Optional64->NumberOfRvaAndSizes >= 7 && Optional64->DataDirectory[6].Size == 0)) {\r
436 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
437 for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
438 if (SectionHeader->VirtualAddress == Optional64->DataDirectory[3].VirtualAddress) {\r
439 for (Index1 = 0; Index1 < Optional64->DataDirectory[3].Size; Index1++) {\r
440 FileBuffer[SectionHeader->PointerToRawData + Index1] = 0;\r
441 }\r
442 }\r
443 }\r
444 Optional64->DataDirectory[3].Size = 0;\r
445 Optional64->DataDirectory[3].VirtualAddress = 0;\r
446 }\r
447 }\r
448 }\r
449\r
450 //\r
451 // Strip zero padding at the end of the .reloc section \r
452 //\r
453 if (Optional64->NumberOfRvaAndSizes >= 6) {\r
454 if (Optional64->DataDirectory[5].Size != 0) {\r
455 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
456 for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
457 if (SectionHeader->VirtualAddress == Optional64->DataDirectory[5].VirtualAddress) {\r
458 FileLength = SectionHeader->PointerToRawData + Optional64->DataDirectory[5].Size;\r
459 FileLength = (FileLength + 7) & 0xfffffff8;\r
460 RelocSize = FileLength - SectionHeader->PointerToRawData;\r
461 }\r
462 }\r
463 }\r
464 }\r
465 }\r
466\r
467 if (RelocSize != 0) {\r
468 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
469 for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
470 if (strcmp(SectionHeader->Name, ".reloc") == 0) {\r
471 SectionHeader->Misc.VirtualSize = (RelocSize + 0x1f) & 0xffffffe0;\r
472 SectionHeader->SizeOfRawData = RelocSize;\r
473 }\r
474 }\r
475 }\r
476\r
477 FWriteFile (fpOut, FileBuffer, FileLength);\r
478\r
479 //\r
480 // Done\r
481 //\r
482 fclose (fpIn);\r
483 fclose (fpOut);\r
484 //\r
485 // printf ("Created %s\n", OutImageName);\r
486 //\r
487 return STATUS_SUCCESS;\r
488}\r