Initial import.
[mirror_edk2.git] / Tools / Source / TianoTools / FwImage / fwimage.c
CommitLineData
878ddf1f 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#ifndef __GNUC__\r
24#include <windows.h>\r
25#endif\r
26#include <stdio.h>\r
27#include <stdlib.h>\r
28#include <string.h>\r
29#include <time.h>\r
30\r
31#include <Base.h>\r
32#include <UefiBaseTypes.h>\r
33#include <CommonLib.h>\r
34#include <EfiImage.h>\r
35#include <EfiUtilityMsgs.c>\r
36\r
37#define UTILITY_NAME "FwImage"\r
38\r
39#ifdef __GNUC__\r
40typedef unsigned long ULONG;\r
41typedef unsigned char UCHAR;\r
42typedef unsigned char *PUCHAR;\r
43typedef unsigned short USHORT;\r
44#endif\r
45\r
46VOID\r
47Usage (\r
48 VOID\r
49 )\r
50{\r
51 printf ("Usage: " UTILITY_NAME " {-t time-date} [APPLICATION|BS_DRIVER|RT_DRIVER|SAL_RT_DRIVER|COMBINED_PEIM_DRIVER|SECURITY_CORE|PEI_CORE|PE32_PEIM|RELOCATABLE_PEIM] peimage [outimage]");\r
52}\r
53\r
54static\r
55STATUS\r
56FCopyFile (\r
57 FILE *in,\r
58 FILE *out\r
59 )\r
60{\r
61 ULONG filesize;\r
62 ULONG offset;\r
63 ULONG length;\r
64 UCHAR Buffer[8 * 1024];\r
65\r
66 fseek (in, 0, SEEK_END);\r
67 filesize = ftell (in);\r
68\r
69 fseek (in, 0, SEEK_SET);\r
70 fseek (out, 0, SEEK_SET);\r
71\r
72 offset = 0;\r
73 while (offset < filesize) {\r
74 length = sizeof (Buffer);\r
75 if (filesize - offset < length) {\r
76 length = filesize - offset;\r
77 }\r
78\r
79 fread (Buffer, length, 1, in);\r
80 fwrite (Buffer, length, 1, out);\r
81 offset += length;\r
82 }\r
83\r
84 if ((ULONG) ftell (out) != filesize) {\r
85 Error (NULL, 0, 0, "write error", NULL);\r
86 return STATUS_ERROR;\r
87 }\r
88\r
89 return STATUS_SUCCESS;\r
90}\r
91\r
92int\r
93main (\r
94 int argc,\r
95 char *argv[]\r
96 )\r
97/*++\r
98\r
99Routine Description:\r
100\r
101 Main function.\r
102\r
103Arguments:\r
104\r
105 argc - Number of command line parameters.\r
106 argv - Array of pointers to command line parameter strings.\r
107\r
108Returns:\r
109 STATUS_SUCCESS - Utility exits successfully.\r
110 STATUS_ERROR - Some error occurred during execution.\r
111\r
112--*/\r
113{\r
114 ULONG Type;\r
115 PUCHAR Ext;\r
116 PUCHAR p;\r
117 PUCHAR pe;\r
118 PUCHAR OutImageName;\r
119 UCHAR outname[500];\r
120 FILE *fpIn;\r
121 FILE *fpOut;\r
122 EFI_IMAGE_DOS_HEADER DosHdr;\r
123 EFI_IMAGE_NT_HEADERS PeHdr;\r
124 time_t TimeStamp;\r
125 struct tm TimeStruct;\r
126 EFI_IMAGE_DOS_HEADER BackupDosHdr;\r
127 ULONG Index;\r
128 BOOLEAN TimeStampPresent;\r
129\r
130 SetUtilityName (UTILITY_NAME);\r
131 //\r
132 // Assign to fix compile warning\r
133 //\r
134 OutImageName = NULL;\r
135 Type = 0;\r
136 Ext = 0;\r
137 TimeStamp = 0;\r
138 TimeStampPresent = FALSE;\r
139\r
140 //\r
141 // Look for -t time-date option first. If the time is "0", then\r
142 // skip it.\r
143 //\r
144 if ((argc > 2) && !strcmp (argv[1], "-t")) {\r
145 TimeStampPresent = TRUE;\r
146 if (strcmp (argv[2], "0") != 0) {\r
147 //\r
148 // Convert the string to a value\r
149 //\r
150 memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));\r
151 if (sscanf(\r
152 argv[2], "%d/%d/%d,%d:%d:%d",\r
153 &TimeStruct.tm_mon, /* months since January - [0,11] */\r
154 &TimeStruct.tm_mday, /* day of the month - [1,31] */\r
155 &TimeStruct.tm_year, /* years since 1900 */\r
156 &TimeStruct.tm_hour, /* hours since midnight - [0,23] */\r
157 &TimeStruct.tm_min, /* minutes after the hour - [0,59] */\r
158 &TimeStruct.tm_sec /* seconds after the minute - [0,59] */\r
159 ) != 6) {\r
160 Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");\r
161 return STATUS_ERROR;\r
162 }\r
163 //\r
164 // Now fixup some of the fields\r
165 //\r
166 TimeStruct.tm_mon--;\r
167 TimeStruct.tm_year -= 1900;\r
168 //\r
169 // Sanity-check values?\r
170 // Convert\r
171 //\r
172 TimeStamp = mktime (&TimeStruct);\r
173 if (TimeStamp == (time_t) - 1) {\r
174 Error (NULL, 0, 0, argv[2], "failed to convert time");\r
175 return STATUS_ERROR;\r
176 }\r
177 }\r
178 //\r
179 // Skip over the args\r
180 //\r
181 argc -= 2;\r
182 argv += 2;\r
183 }\r
184 //\r
185 // Check for enough args\r
186 //\r
187 if (argc < 3) {\r
188 Usage ();\r
189 return STATUS_ERROR;\r
190 }\r
191\r
192 if (argc == 4) {\r
193 OutImageName = argv[3];\r
194 }\r
195 //\r
196 // Get new image type\r
197 //\r
198 p = argv[1];\r
199 if (*p == '/' || *p == '\\') {\r
200 p += 1;\r
201 }\r
202\r
203 if (stricmp (p, "app") == 0 || stricmp (p, "APPLICATION") == 0) {\r
204 Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
205 Ext = ".efi";\r
206\r
207 } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "BS_DRIVER") == 0) {\r
208 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
209 Ext = ".efi";\r
210\r
211 } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "RT_DRIVER") == 0) {\r
212 Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
213 Ext = ".efi";\r
214\r
215 } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "SAL_RT_DRIVER") == 0) {\r
216 Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
217 Ext = ".efi";\r
218 } else if (stricmp (p, "SECURITY_CORE") == 0) {\r
219 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
220 Ext = ".sec";\r
221 } else if (stricmp (p, "peim") == 0 ||\r
222 stricmp (p, "PEI_CORE") == 0 ||\r
223 stricmp (p, "PE32_PEIM") == 0 ||\r
224 stricmp (p, "RELOCATABLE_PEIM") == 0 ||\r
225 stricmp (p, "combined_peim_driver") == 0\r
226 ) {\r
227 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
228 Ext = ".pei";\r
229 } else {\r
230 Usage ();\r
231 return STATUS_ERROR;\r
232 }\r
233 //\r
234 // open source file\r
235 //\r
236 fpIn = fopen (argv[2], "rb");\r
237 if (!fpIn) {\r
238 Error (NULL, 0, 0, argv[2], "failed to open input file for reading");\r
239 return STATUS_ERROR;\r
240 }\r
241 //\r
242 // Read the dos & pe hdrs of the image\r
243 //\r
244 fseek (fpIn, 0, SEEK_SET);\r
245 fread (&DosHdr, sizeof (DosHdr), 1, fpIn);\r
246 if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
247 Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image");\r
248 fclose (fpIn);\r
249 return STATUS_ERROR;\r
250 }\r
251\r
252 fseek (fpIn, DosHdr.e_lfanew, SEEK_SET);\r
253 fread (&PeHdr, sizeof (PeHdr), 1, fpIn);\r
254 if (PeHdr.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
255 Error (NULL, 0, 0, argv[2], "PE header signature not found in source image");\r
256 fclose (fpIn);\r
257 return STATUS_ERROR;\r
258 }\r
259 //\r
260 // open output file\r
261 //\r
262 strcpy (outname, argv[2]);\r
263 pe = NULL;\r
264 for (p = outname; *p; p++) {\r
265 if (*p == '.') {\r
266 pe = p;\r
267 }\r
268 }\r
269\r
270 if (!pe) {\r
271 pe = p;\r
272 }\r
273\r
274 strcpy (pe, Ext);\r
275\r
276 if (!OutImageName) {\r
277 OutImageName = outname;\r
278 }\r
279\r
280 fpOut = fopen (OutImageName, "w+b");\r
281 if (!fpOut) {\r
282 Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r
283 fclose (fpIn);\r
284 return STATUS_ERROR;\r
285 }\r
286 //\r
287 // Copy the file\r
288 //\r
289 if (FCopyFile (fpIn, fpOut) != STATUS_SUCCESS) {\r
290 fclose (fpIn);\r
291 fclose (fpOut);\r
292 return STATUS_ERROR;\r
293 }\r
294 //\r
295 // Zero all unused fields of the DOS header\r
296 //\r
297 memcpy (&BackupDosHdr, &DosHdr, sizeof (DosHdr));\r
298 memset (&DosHdr, 0, sizeof (DosHdr));\r
299 DosHdr.e_magic = BackupDosHdr.e_magic;\r
300 DosHdr.e_lfanew = BackupDosHdr.e_lfanew;\r
301 fseek (fpOut, 0, SEEK_SET);\r
302 fwrite (&DosHdr, sizeof (DosHdr), 1, fpOut);\r
303\r
304 fseek (fpOut, sizeof (DosHdr), SEEK_SET);\r
305 for (Index = sizeof (DosHdr); Index < (ULONG) DosHdr.e_lfanew; Index++) {\r
306 fwrite (&DosHdr.e_cp, 1, 1, fpOut);\r
307 }\r
308 //\r
309 // Path the PE header\r
310 //\r
311 PeHdr.OptionalHeader.Subsystem = (USHORT) Type;\r
312 if (TimeStampPresent) {\r
313 PeHdr.FileHeader.TimeDateStamp = (UINT32) TimeStamp;\r
314 }\r
315\r
316 PeHdr.OptionalHeader.SizeOfStackReserve = 0;\r
317 PeHdr.OptionalHeader.SizeOfStackCommit = 0;\r
318 PeHdr.OptionalHeader.SizeOfHeapReserve = 0;\r
319 PeHdr.OptionalHeader.SizeOfHeapCommit = 0;\r
320 fseek (fpOut, DosHdr.e_lfanew, SEEK_SET);\r
321 fwrite (&PeHdr, sizeof (PeHdr), 1, fpOut);\r
322\r
323 //\r
324 // Done\r
325 //\r
326 fclose (fpIn);\r
327 fclose (fpOut);\r
328 //\r
329 // printf ("Created %s\n", OutImageName);\r
330 //\r
331 return STATUS_SUCCESS;\r
332}\r