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