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