]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/TianoTools/SecFixup/SecFixup.c
96faaf089a7a34d65d9d4af71e869b5ca5a35ccf
[mirror_edk2.git] / Tools / Source / TianoTools / SecFixup / SecFixup.c
1 /*++
2
3 Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
10 Intel Corporation.
11
12
13 Module Name:
14
15 SecFixup.c
16
17 Abstract:
18
19 This utility is part of build process for IA32 SEC FFS file.
20
21 It fixup the reset vector data. The reset vector data binary file
22 will be wrapped as a RAW section and be located immediately after
23 the PE/TE section.
24
25 The SEC EXE file can be either PE or TE file.
26
27 --*/
28
29 #include <stdio.h>
30
31 #include <UefiBaseTypes.h>
32 #include <Base.h>
33 #include "EfiImage.h"
34 #include "FirmwareVolumeImageFormat.h"
35 #include "EfiUtilityMsgs.c"
36
37 #include "SecFixup.h"
38
39 VOID
40 PrintUtilityInfo (
41 VOID
42 )
43 /*++
44
45 Routine Description:
46
47 Displays the standard utility information to SDTOUT
48
49 Arguments:
50
51 None
52
53 Returns:
54
55 None
56
57 --*/
58 {
59 printf (
60 "%s - Tiano IA32 SEC Fixup Utility."" Version %i.%i\n\n",
61 UTILITY_NAME,
62 UTILITY_MAJOR_VERSION,
63 UTILITY_MINOR_VERSION
64 );
65 }
66
67 VOID
68 PrintUsage (
69 VOID
70 )
71 /*++
72
73 Routine Description:
74
75 Displays the utility usage syntax to STDOUT
76
77 Arguments:
78
79 None
80
81 Returns:
82
83 None
84
85 --*/
86 {
87 printf ("Usage: %s SecExeFile ResetVectorDataFile OutputFile\n", UTILITY_NAME);
88 printf (" Where:\n");
89 printf ("\tSecExeFile - Name of the IA32 SEC EXE file.\n");
90 printf ("\tResetVectorDataFile - Name of the reset vector data binary file.\n");
91 printf ("\tOutputFileName - Name of the output file.\n\n");
92 }
93
94 STATUS
95 main (
96 IN INTN argc,
97 IN CHAR8 **argv
98 )
99 /*++
100
101 Routine Description:
102
103 Main function.
104
105 Arguments:
106
107 argc - Number of command line parameters.
108 argv - Array of pointers to parameter strings.
109
110 Returns:
111 STATUS_SUCCESS - Utility exits successfully.
112 STATUS_ERROR - Some error occurred during execution.
113
114 --*/
115 {
116 FILE *FpIn;
117
118 FILE *FpOut;
119 UINT32 AddressOfEntryPoint;
120 INT32 DestRel;
121 STATUS Status;
122 UINT32 SecFileSize;
123
124 SetUtilityName (UTILITY_NAME);
125
126 //
127 // Display utility information
128 //
129 PrintUtilityInfo ();
130
131 //
132 // Verify the correct number of arguments
133 //
134 if (argc != MAX_ARGS) {
135 Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);
136 PrintUsage ();
137 return STATUS_ERROR;
138 }
139 //
140 // Open the SEC exe file
141 //
142 if ((FpIn = fopen (argv[1], "rb")) == NULL) {
143 Error (NULL, 0, 0, "Unable to open file", argv[1]);
144 return STATUS_ERROR;
145 }
146 //
147 // Get the entry point of the EXE file
148 //
149 Status = GetEntryPoint (FpIn, &AddressOfEntryPoint);
150 if (Status != STATUS_SUCCESS) {
151 fclose (FpIn);
152 return STATUS_ERROR;
153 }
154 //
155 // Get the SEC file size
156 //
157 fseek (FpIn, 0, SEEK_END);
158 SecFileSize = ftell (FpIn);
159
160 //
161 // Close the SEC file
162 //
163 fclose (FpIn);
164
165 //
166 // Open the reset vector data file
167 //
168 if ((FpIn = fopen (argv[2], "rb")) == NULL) {
169 Error (NULL, 0, 0, "Unable to open file", argv[2]);
170 return STATUS_ERROR;
171 }
172 //
173 // Open the output file
174 //
175 if ((FpOut = fopen (argv[3], "w+b")) == NULL) {
176 Error (NULL, 0, 0, "Unable to open file", argv[3]);
177 fclose (FpIn);
178 return STATUS_ERROR;
179 }
180 //
181 // Copy the input file to the output file
182 //
183 if (CopyFile (FpIn, FpOut) != STATUS_SUCCESS) {
184 fclose (FpIn);
185 fclose (FpOut);
186 return STATUS_ERROR;
187 }
188 //
189 // Close the reset vector data file
190 //
191 fclose (FpIn);
192
193 //
194 // Fix the destination relative in the jmp instruction
195 // in the reset vector data structure
196 //
197 fseek (FpOut, -DEST_REL_OFFSET, SEEK_END);
198 DestRel = AddressOfEntryPoint - (SecFileSize + sizeof (EFI_COMMON_SECTION_HEADER) + (UINT32) (ftell (FpOut)) + 2);
199 if (DestRel <= -65536) {
200 Error (NULL, 0, 0, "The SEC EXE file size is too big", NULL);
201 fclose (FpOut);
202 return STATUS_ERROR;
203 }
204
205 if (fwrite (&DestRel, sizeof (UINT16), 1, FpOut) != 1) {
206 Error (NULL, 0, 0, "Failed to write to the output file", NULL);
207 fclose (FpOut);
208 return STATUS_ERROR;
209 }
210 //
211 // Close the output file
212 //
213 fclose (FpOut);
214
215 return STATUS_SUCCESS;
216 }
217
218 STATUS
219 GetEntryPoint (
220 IN FILE *ExeFile,
221 OUT UINT32 *EntryPoint
222 )
223 /*++
224
225 Routine Description:
226
227 Get the address of the entry point of a PE/TE file.
228
229 Arguments:
230
231 PeFile - File pointer to the specified PE/TE file.
232 EntryPoint - Buffer for the address of the entry point to be returned.
233
234 Returns:
235 STATUS_SUCCESS - Function completed successfully.
236 STATUS_ERROR - Error occured.
237
238 --*/
239 // GC_TODO: ExeFile - add argument and description to function comment
240 {
241 EFI_IMAGE_DOS_HEADER DosHeader;
242 EFI_IMAGE_NT_HEADERS32 NtHeader;
243 EFI_TE_IMAGE_HEADER TeHeader;
244
245 //
246 // Check if it is a TE file
247 //
248 fseek (ExeFile, 0, SEEK_SET);
249 //
250 // Attempt to read the TE header
251 //
252 if (fread (&TeHeader, sizeof (TeHeader), 1, ExeFile) == 1) {
253 if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
254 if (TeHeader.Machine != EFI_IMAGE_MACHINE_IA32) {
255 Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);
256 return STATUS_ERROR;
257 }
258
259 *EntryPoint = TeHeader.AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader.StrippedSize;
260 return STATUS_SUCCESS;
261 }
262 }
263 //
264 // Check if it is a PE file
265 //
266 fseek (ExeFile, 0, SEEK_SET);
267 //
268 // Attempt to read the DOS header
269 //
270 if (fread (&DosHeader, sizeof (DosHeader), 1, ExeFile) != 1) {
271 goto InvalidFile;
272 }
273 //
274 // Check the magic number
275 //
276 if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
277 goto InvalidFile;
278 }
279 //
280 // Position into the file and read the NT PE header
281 //
282 fseek (ExeFile, (long) DosHeader.e_lfanew, SEEK_SET);
283 if (fread (&NtHeader, sizeof (NtHeader), 1, ExeFile) != 1) {
284 goto InvalidFile;
285 }
286 //
287 // Check the PE signature in the header
288 //
289 if (NtHeader.Signature != EFI_IMAGE_NT_SIGNATURE) {
290 goto InvalidFile;
291 }
292 //
293 // Make sure the PE file is PE32 for IA32
294 //
295 if (NtHeader.FileHeader.Machine != EFI_IMAGE_MACHINE_IA32 ||
296 NtHeader.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
297 ) {
298 Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);
299 return STATUS_ERROR;
300 }
301 //
302 // Get the entry point from the optional header
303 //
304 *EntryPoint = NtHeader.OptionalHeader.AddressOfEntryPoint;
305 return STATUS_SUCCESS;
306
307 InvalidFile:
308 Error (NULL, 0, 0, "The SEC file is neither PE nor TE file", NULL);
309 return STATUS_ERROR;
310 }
311
312 STATUS
313 CopyFile (
314 FILE *FpIn,
315 FILE *FpOut
316 )
317 /*++
318
319 Routine Description:
320
321 Copy file.
322
323 Arguments:
324
325 FpIn - File pointer to the source file.
326 FpOut - File pointer to the destination file.
327
328 Returns:
329 STATUS_SUCCESS - Function completed successfully.
330 STATUS_ERROR - Error occured.
331
332 --*/
333 {
334 INTN FileSize;
335
336 INTN Offset;
337
338 INTN Length;
339 UINT8 Buffer[BUF_SIZE];
340
341 fseek (FpIn, 0, SEEK_END);
342 FileSize = ftell (FpIn);
343
344 fseek (FpIn, 0, SEEK_SET);
345 fseek (FpOut, 0, SEEK_SET);
346
347 Offset = 0;
348 while (Offset < FileSize) {
349 Length = sizeof (Buffer);
350 if (FileSize - Offset < Length) {
351 Length = FileSize - Offset;
352 }
353
354 if (fread (Buffer, Length, 1, FpIn) != 1 || fwrite (Buffer, Length, 1, FpOut) != 1) {
355 Error (NULL, 0, 0, "Copy file error", NULL);
356 return STATUS_ERROR;
357 }
358
359 Offset += Length;
360 }
361
362 return STATUS_SUCCESS;
363 }