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