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