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