]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - Tools/CodeTools/TianoTools/FwImage/fwimage.c
Restructuring for better separation of Tool packages.
[mirror_edk2.git] / Tools / CodeTools / 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 ULONG Index2;\r
168 ULONG Index3;\r
169 BOOLEAN TimeStampPresent;\r
170 UINTN AllignedRelocSize;\r
171 UINTN Delta;\r
172 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
173 UINT8 *FileBuffer;\r
174 UINTN FileLength;\r
175 RUNTIME_FUNCTION *RuntimeFunction;\r
176 UNWIND_INFO *UnwindInfo;\r
177\r
178 SetUtilityName (UTILITY_NAME);\r
179 //\r
180 // Assign to fix compile warning\r
181 //\r
182 OutImageName = NULL;\r
183 Type = 0;\r
184 Ext = 0;\r
185 TimeStamp = 0;\r
186 TimeStampPresent = FALSE;\r
187\r
188 //\r
189 // Look for -t time-date option first. If the time is "0", then\r
190 // skip it.\r
191 //\r
192 if ((argc > 2) && !strcmp (argv[1], "-t")) {\r
193 TimeStampPresent = TRUE;\r
194 if (strcmp (argv[2], "0") != 0) {\r
195 //\r
196 // Convert the string to a value\r
197 //\r
198 memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));\r
199 if (sscanf(\r
200 argv[2], "%d/%d/%d,%d:%d:%d",\r
201 &TimeStruct.tm_mon, /* months since January - [0,11] */\r
202 &TimeStruct.tm_mday, /* day of the month - [1,31] */\r
203 &TimeStruct.tm_year, /* years since 1900 */\r
204 &TimeStruct.tm_hour, /* hours since midnight - [0,23] */\r
205 &TimeStruct.tm_min, /* minutes after the hour - [0,59] */\r
206 &TimeStruct.tm_sec /* seconds after the minute - [0,59] */\r
207 ) != 6) {\r
208 Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");\r
209 return STATUS_ERROR;\r
210 }\r
211 //\r
212 // Now fixup some of the fields\r
213 //\r
214 TimeStruct.tm_mon--;\r
215 TimeStruct.tm_year -= 1900;\r
216 //\r
217 // Sanity-check values?\r
218 // Convert\r
219 //\r
220 TimeStamp = mktime (&TimeStruct);\r
221 if (TimeStamp == (time_t) - 1) {\r
222 Error (NULL, 0, 0, argv[2], "failed to convert time");\r
223 return STATUS_ERROR;\r
224 }\r
225 }\r
226 //\r
227 // Skip over the args\r
228 //\r
229 argc -= 2;\r
230 argv += 2;\r
231 }\r
232 //\r
233 // Check for enough args\r
234 //\r
235 if (argc < 3) {\r
236 Usage ();\r
237 return STATUS_ERROR;\r
238 }\r
239\r
240 if (argc == 4) {\r
241 OutImageName = argv[3];\r
242 }\r
243 //\r
244 // Get new image type\r
245 //\r
246 p = argv[1];\r
247 if (*p == '/' || *p == '\\') {\r
248 p += 1;\r
249 }\r
250\r
251 if (stricmp (p, "app") == 0 || stricmp (p, "UEFI_APPLICATION") == 0) {\r
252 Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
253 Ext = ".efi";\r
254\r
255 } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "DXE_DRIVER") == 0) {\r
256 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
257 Ext = ".efi";\r
258\r
259 } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_RUNTIME_DRIVER") == 0) {\r
260 Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
261 Ext = ".efi";\r
262\r
263 } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_SAL_DRIVER") == 0) {\r
264 Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
265 Ext = ".efi";\r
266 } else if (stricmp (p, "SEC") == 0) {\r
267 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
268 Ext = ".sec";\r
269 } else if (stricmp (p, "peim") == 0 ||\r
270 stricmp (p, "BASE") == 0 ||\r
271 stricmp (p, "PEI_CORE") == 0 ||\r
272 stricmp (p, "PEIM") == 0 ||\r
273 stricmp (p, "DXE_SMM_DRIVER") == 0 ||\r
274 stricmp (p, "TOOL") == 0 ||\r
275 stricmp (p, "UEFI_APPLICATION") == 0 ||\r
276 stricmp (p, "USER_DEFINED") == 0 ||\r
277 stricmp (p, "UEFI_DRIVER") == 0 ||\r
278 stricmp (p, "DXE_CORE") == 0\r
279 ) {\r
280 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
281 Ext = ".pei";\r
282 } else {\r
283 printf ("%s", p);\r
284 Usage ();\r
285 return STATUS_ERROR;\r
286 }\r
287 //\r
288 // open source file\r
289 //\r
290 fpIn = fopen (argv[2], "rb");\r
291 if (!fpIn) {\r
292 Error (NULL, 0, 0, argv[2], "failed to open input file for reading");\r
293 return STATUS_ERROR;\r
294 }\r
295\r
296 FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);\r
297\r
298 //\r
299 // Read the dos & pe hdrs of the image\r
300 //\r
301 DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
302 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
303 Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image");\r
304 fclose (fpIn);\r
305 return STATUS_ERROR;\r
306 }\r
307\r
308 PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r
309 if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
310 Error (NULL, 0, 0, argv[2], "PE header signature not found in source image");\r
311 fclose (fpIn);\r
312 return STATUS_ERROR;\r
313 }\r
314\r
315 //\r
316 // open output file\r
317 //\r
318 strcpy (outname, argv[2]);\r
319 pe = NULL;\r
320 for (p = outname; *p; p++) {\r
321 if (*p == '.') {\r
322 pe = p;\r
323 }\r
324 }\r
325\r
326 if (!pe) {\r
327 pe = p;\r
328 }\r
329\r
330 strcpy (pe, Ext);\r
331\r
332 if (!OutImageName) {\r
333 OutImageName = outname;\r
334 }\r
335\r
336 fpOut = fopen (OutImageName, "w+b");\r
337 if (!fpOut) {\r
338 Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r
339 fclose (fpIn);\r
340 return STATUS_ERROR;\r
341 }\r
342\r
343 //\r
344 // Zero all unused fields of the DOS header\r
345 //\r
346 memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r
347 memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
348 DosHdr->e_magic = BackupDosHdr.e_magic;\r
349 DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
350\r
351 for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) {\r
352 FileBuffer[Index] = DosHdr->e_cp;\r
353 }\r
354\r
355 //\r
356 // Path the PE header\r
357 //\r
358 PeHdr->OptionalHeader.Subsystem = (USHORT) Type;\r
359 if (TimeStampPresent) {\r
360 PeHdr->FileHeader.TimeDateStamp = (UINT32) TimeStamp;\r
361 }\r
362\r
363 if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
364 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r
365 Optional32->MajorLinkerVersion = 0;\r
366 Optional32->MinorLinkerVersion = 0;\r
367 Optional32->MajorOperatingSystemVersion = 0;\r
368 Optional32->MinorOperatingSystemVersion = 0;\r
369 Optional32->MajorImageVersion = 0;\r
370 Optional32->MinorImageVersion = 0;\r
371 Optional32->MajorSubsystemVersion = 0;\r
372 Optional32->MinorSubsystemVersion = 0;\r
373 Optional32->Win32VersionValue = 0;\r
374 Optional32->CheckSum = 0;\r
375 Optional32->SizeOfStackReserve = 0;\r
376 Optional32->SizeOfStackCommit = 0;\r
377 Optional32->SizeOfHeapReserve = 0;\r
378 Optional32->SizeOfHeapCommit = 0;\r
379\r
380 //\r
381 // Strip zero padding at the end of the .reloc section \r
382 //\r
383 if (Optional32->NumberOfRvaAndSizes >= 6) {\r
384 if (Optional32->DataDirectory[5].Size != 0) {\r
385 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
386 for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
387 //\r
388 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
389 //\r
390 if (SectionHeader->VirtualAddress == Optional32->DataDirectory[5].VirtualAddress) {\r
391 SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[5].Size;\r
392 AllignedRelocSize = (Optional32->DataDirectory[5].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r
393 //\r
394 // Check to see if there is zero padding at the end of the base relocations\r
395 //\r
396 if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
397 //\r
398 // Check to see if the base relocations are at the end of the file\r
399 //\r
400 if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r
401 //\r
402 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
403 //\r
404 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
405 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
406 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
407 FileLength = Optional32->SizeOfImage;\r
408 }\r
409 }\r
410 }\r
411 }\r
412 }\r
413 }\r
414 } \r
415 if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
416 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r
417 Optional64->MajorLinkerVersion = 0;\r
418 Optional64->MinorLinkerVersion = 0;\r
419 Optional64->MajorOperatingSystemVersion = 0;\r
420 Optional64->MinorOperatingSystemVersion = 0;\r
421 Optional64->MajorImageVersion = 0;\r
422 Optional64->MinorImageVersion = 0;\r
423 Optional64->MajorSubsystemVersion = 0;\r
424 Optional64->MinorSubsystemVersion = 0;\r
425 Optional64->Win32VersionValue = 0;\r
426 Optional64->CheckSum = 0;\r
427 Optional64->SizeOfStackReserve = 0;\r
428 Optional64->SizeOfStackCommit = 0;\r
429 Optional64->SizeOfHeapReserve = 0;\r
430 Optional64->SizeOfHeapCommit = 0;\r
431\r
432 //\r
433 // Zero the .pdata section if the machine type is X64 and the Debug Directory is empty\r
434 //\r
435 if (PeHdr->FileHeader.Machine == 0x8664) { // X64\r
436 if (Optional64->NumberOfRvaAndSizes >= 4) {\r
437 if (Optional64->NumberOfRvaAndSizes < 7 || (Optional64->NumberOfRvaAndSizes >= 7 && Optional64->DataDirectory[6].Size == 0)) {\r
438 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
439 for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
440 if (SectionHeader->VirtualAddress == Optional64->DataDirectory[3].VirtualAddress) {\r
441 RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r
442 for (Index1 = 0; Index1 < Optional64->DataDirectory[3].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r
443 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
444 for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r
445 if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r
446 UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r
447 if (UnwindInfo->Version == 1) {\r
448 memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r
449 memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r
450 }\r
451 }\r
452 }\r
453 memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r
454 }\r
455 }\r
456 }\r
457 Optional64->DataDirectory[3].Size = 0;\r
458 Optional64->DataDirectory[3].VirtualAddress = 0;\r
459 }\r
460 }\r
461 }\r
462\r
463 //\r
464 // Strip zero padding at the end of the .reloc section \r
465 //\r
466 if (Optional64->NumberOfRvaAndSizes >= 6) {\r
467 if (Optional64->DataDirectory[5].Size != 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 //\r
471 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
472 //\r
473 if (SectionHeader->VirtualAddress == Optional64->DataDirectory[5].VirtualAddress) {\r
474 SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[5].Size;\r
475 AllignedRelocSize = (Optional64->DataDirectory[5].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r
476 //\r
477 // Check to see if there is zero padding at the end of the base relocations\r
478 //\r
479 if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
480 //\r
481 // Check to see if the base relocations are at the end of the file\r
482 //\r
483 if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r
484 //\r
485 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
486 //\r
487 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
488 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
489 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
490 FileLength = Optional64->SizeOfImage;\r
491 }\r
492 }\r
493 }\r
494 }\r
495 }\r
496 }\r
497 }\r
498\r
499 FWriteFile (fpOut, FileBuffer, FileLength);\r
500\r
501 //\r
502 // Done\r
503 //\r
504 fclose (fpIn);\r
505 fclose (fpOut);\r
506 //\r
507 // printf ("Created %s\n", OutImageName);\r
508 //\r
509 return STATUS_SUCCESS;\r
510}\r