Fix buffer overflow when the raw size of a section and the virtual size of a section...
[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
ce53a8c3 22#include "WinNtInclude.h"\r
23\r
878ddf1f 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
ce53a8c3 32#include <Common/UefiBaseTypes.h>\r
33#include <Common/EfiImage.h>\r
34\r
35#include "CommonLib.h"\r
36#include "EfiUtilityMsgs.c"\r
878ddf1f 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
8a286638 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
878ddf1f 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
93int\r
94main (\r
95 int argc,\r
96 char *argv[]\r
97 )\r
98/*++\r
99\r
100Routine Description:\r
101\r
102 Main function.\r
103\r
104Arguments:\r
105\r
106 argc - Number of command line parameters.\r
107 argv - Array of pointers to command line parameter strings.\r
108\r
109Returns:\r
110 STATUS_SUCCESS - Utility exits successfully.\r
111 STATUS_ERROR - Some error occurred during execution.\r
112\r
113--*/\r
114{\r
115 ULONG Type;\r
116 PUCHAR Ext;\r
117 PUCHAR p;\r
118 PUCHAR pe;\r
119 PUCHAR OutImageName;\r
120 UCHAR outname[500];\r
121 FILE *fpIn;\r
122 FILE *fpOut;\r
123 EFI_IMAGE_DOS_HEADER DosHdr;\r
124 EFI_IMAGE_NT_HEADERS PeHdr;\r
125 time_t TimeStamp;\r
126 struct tm TimeStruct;\r
127 EFI_IMAGE_DOS_HEADER BackupDosHdr;\r
128 ULONG Index;\r
129 BOOLEAN TimeStampPresent;\r
130\r
131 SetUtilityName (UTILITY_NAME);\r
132 //\r
133 // Assign to fix compile warning\r
134 //\r
135 OutImageName = NULL;\r
136 Type = 0;\r
137 Ext = 0;\r
138 TimeStamp = 0;\r
139 TimeStampPresent = FALSE;\r
140\r
141 //\r
142 // Look for -t time-date option first. If the time is "0", then\r
143 // skip it.\r
144 //\r
145 if ((argc > 2) && !strcmp (argv[1], "-t")) {\r
146 TimeStampPresent = TRUE;\r
147 if (strcmp (argv[2], "0") != 0) {\r
148 //\r
149 // Convert the string to a value\r
150 //\r
151 memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));\r
152 if (sscanf(\r
153 argv[2], "%d/%d/%d,%d:%d:%d",\r
154 &TimeStruct.tm_mon, /* months since January - [0,11] */\r
155 &TimeStruct.tm_mday, /* day of the month - [1,31] */\r
156 &TimeStruct.tm_year, /* years since 1900 */\r
157 &TimeStruct.tm_hour, /* hours since midnight - [0,23] */\r
158 &TimeStruct.tm_min, /* minutes after the hour - [0,59] */\r
159 &TimeStruct.tm_sec /* seconds after the minute - [0,59] */\r
160 ) != 6) {\r
161 Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");\r
162 return STATUS_ERROR;\r
163 }\r
164 //\r
165 // Now fixup some of the fields\r
166 //\r
167 TimeStruct.tm_mon--;\r
168 TimeStruct.tm_year -= 1900;\r
169 //\r
170 // Sanity-check values?\r
171 // Convert\r
172 //\r
173 TimeStamp = mktime (&TimeStruct);\r
174 if (TimeStamp == (time_t) - 1) {\r
175 Error (NULL, 0, 0, argv[2], "failed to convert time");\r
176 return STATUS_ERROR;\r
177 }\r
178 }\r
179 //\r
180 // Skip over the args\r
181 //\r
182 argc -= 2;\r
183 argv += 2;\r
184 }\r
185 //\r
186 // Check for enough args\r
187 //\r
188 if (argc < 3) {\r
189 Usage ();\r
190 return STATUS_ERROR;\r
191 }\r
192\r
193 if (argc == 4) {\r
194 OutImageName = argv[3];\r
195 }\r
196 //\r
197 // Get new image type\r
198 //\r
199 p = argv[1];\r
200 if (*p == '/' || *p == '\\') {\r
201 p += 1;\r
202 }\r
203\r
8a286638 204 if (stricmp (p, "app") == 0 || stricmp (p, "UEFI_APPLICATION") == 0) {\r
878ddf1f 205 Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
206 Ext = ".efi";\r
207\r
8a286638 208 } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "DXE_DRIVER") == 0) {\r
878ddf1f 209 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
210 Ext = ".efi";\r
211\r
8a286638 212 } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_RUNTIME_DRIVER") == 0) {\r
878ddf1f 213 Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
214 Ext = ".efi";\r
215\r
8a286638 216 } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_SAL_DRIVER") == 0) {\r
878ddf1f 217 Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
218 Ext = ".efi";\r
8a286638 219 } else if (stricmp (p, "SEC") == 0) {\r
878ddf1f 220 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
221 Ext = ".sec";\r
222 } else if (stricmp (p, "peim") == 0 ||\r
8a286638 223 stricmp (p, "BASE") == 0 ||\r
878ddf1f 224 stricmp (p, "PEI_CORE") == 0 ||\r
8a286638 225 stricmp (p, "PEIM") == 0 ||\r
226 stricmp (p, "DXE_SMM_DRIVER") == 0 ||\r
227 stricmp (p, "TOOL") == 0 ||\r
228 stricmp (p, "UEFI_APPLICATION") == 0 ||\r
229 stricmp (p, "USER_DEFINED") == 0 ||\r
230 stricmp (p, "UEFI_DRIVER") == 0 ||\r
231 stricmp (p, "DXE_CORE") == 0\r
878ddf1f 232 ) {\r
233 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
234 Ext = ".pei";\r
235 } else {\r
8a286638 236 printf ("%s", p);\r
878ddf1f 237 Usage ();\r
238 return STATUS_ERROR;\r
239 }\r
240 //\r
241 // open source file\r
242 //\r
243 fpIn = fopen (argv[2], "rb");\r
244 if (!fpIn) {\r
245 Error (NULL, 0, 0, argv[2], "failed to open input file for reading");\r
246 return STATUS_ERROR;\r
247 }\r
248 //\r
249 // Read the dos & pe hdrs of the image\r
250 //\r
251 fseek (fpIn, 0, SEEK_SET);\r
252 fread (&DosHdr, sizeof (DosHdr), 1, fpIn);\r
253 if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
254 Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image");\r
255 fclose (fpIn);\r
256 return STATUS_ERROR;\r
257 }\r
258\r
259 fseek (fpIn, DosHdr.e_lfanew, SEEK_SET);\r
260 fread (&PeHdr, sizeof (PeHdr), 1, fpIn);\r
261 if (PeHdr.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
262 Error (NULL, 0, 0, argv[2], "PE header signature not found in source image");\r
263 fclose (fpIn);\r
264 return STATUS_ERROR;\r
265 }\r
266 //\r
267 // open output file\r
268 //\r
269 strcpy (outname, argv[2]);\r
270 pe = NULL;\r
271 for (p = outname; *p; p++) {\r
272 if (*p == '.') {\r
273 pe = p;\r
274 }\r
275 }\r
276\r
277 if (!pe) {\r
278 pe = p;\r
279 }\r
280\r
281 strcpy (pe, Ext);\r
282\r
283 if (!OutImageName) {\r
284 OutImageName = outname;\r
285 }\r
286\r
287 fpOut = fopen (OutImageName, "w+b");\r
288 if (!fpOut) {\r
289 Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r
290 fclose (fpIn);\r
291 return STATUS_ERROR;\r
292 }\r
293 //\r
294 // Copy the file\r
295 //\r
296 if (FCopyFile (fpIn, fpOut) != STATUS_SUCCESS) {\r
297 fclose (fpIn);\r
298 fclose (fpOut);\r
299 return STATUS_ERROR;\r
300 }\r
301 //\r
302 // Zero all unused fields of the DOS header\r
303 //\r
304 memcpy (&BackupDosHdr, &DosHdr, sizeof (DosHdr));\r
305 memset (&DosHdr, 0, sizeof (DosHdr));\r
306 DosHdr.e_magic = BackupDosHdr.e_magic;\r
307 DosHdr.e_lfanew = BackupDosHdr.e_lfanew;\r
308 fseek (fpOut, 0, SEEK_SET);\r
309 fwrite (&DosHdr, sizeof (DosHdr), 1, fpOut);\r
310\r
311 fseek (fpOut, sizeof (DosHdr), SEEK_SET);\r
312 for (Index = sizeof (DosHdr); Index < (ULONG) DosHdr.e_lfanew; Index++) {\r
313 fwrite (&DosHdr.e_cp, 1, 1, fpOut);\r
314 }\r
315 //\r
316 // Path the PE header\r
317 //\r
318 PeHdr.OptionalHeader.Subsystem = (USHORT) Type;\r
319 if (TimeStampPresent) {\r
320 PeHdr.FileHeader.TimeDateStamp = (UINT32) TimeStamp;\r
321 }\r
322\r
323 PeHdr.OptionalHeader.SizeOfStackReserve = 0;\r
324 PeHdr.OptionalHeader.SizeOfStackCommit = 0;\r
325 PeHdr.OptionalHeader.SizeOfHeapReserve = 0;\r
326 PeHdr.OptionalHeader.SizeOfHeapCommit = 0;\r
327 fseek (fpOut, DosHdr.e_lfanew, SEEK_SET);\r
328 fwrite (&PeHdr, sizeof (PeHdr), 1, fpOut);\r
329\r
330 //\r
331 // Done\r
332 //\r
333 fclose (fpIn);\r
334 fclose (fpOut);\r
335 //\r
336 // printf ("Created %s\n", OutImageName);\r
337 //\r
338 return STATUS_SUCCESS;\r
339}\r