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
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.
19 This utility is part of build process for IA32 SEC FFS file.
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
25 The SEC EXE file can be either PE or TE file.
31 #include <Common/UefiBaseTypes.h>
32 #include <Common/EfiImage.h>
33 #include <Common/FirmwareVolumeImageFormat.h>
35 #include "EfiUtilityMsgs.c"
46 Displays the standard utility information to SDTOUT
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");
70 Displays the utility usage syntax to STDOUT
84 printf ("\nUsage: %s SecExeFile ResetVectorDataFile OutputFile\n", UTILITY_NAME
);
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");
104 argc - Number of command line parameters.
105 argv - Array of pointers to parameter strings.
108 STATUS_SUCCESS - Utility exits successfully.
109 STATUS_ERROR - Some error occurred during execution.
116 UINT32 AddressOfEntryPoint
;
121 SetUtilityName (UTILITY_NAME
);
128 if ((strcmp(argv
[1], "-h") == 0) || (strcmp(argv
[1], "--help") == 0) ||
129 (strcmp(argv
[1], "-?") == 0) || (strcmp(argv
[1], "/?") == 0)) {
134 if ((strcmp(argv
[1], "-V") == 0) || (strcmp(argv
[1], "--version") == 0)) {
140 // Verify the correct number of arguments
142 if (argc
!= MAX_ARGS
) {
143 Error (NULL
, 0, 0, "invalid number of input parameters specified", NULL
);
148 // Open the SEC exe file
150 if ((FpIn
= fopen (argv
[1], "rb")) == NULL
) {
151 Error (NULL
, 0, 0, "Unable to open file", argv
[1]);
155 // Get the entry point of the EXE file
157 Status
= GetEntryPoint (FpIn
, &AddressOfEntryPoint
);
158 if (Status
!= STATUS_SUCCESS
) {
163 // Get the SEC file size
165 fseek (FpIn
, 0, SEEK_END
);
166 SecFileSize
= ftell (FpIn
);
169 // Close the SEC file
174 // Open the reset vector data file
176 if ((FpIn
= fopen (argv
[2], "rb")) == NULL
) {
177 Error (NULL
, 0, 0, "Unable to open file", argv
[2]);
181 // Open the output file
183 if ((FpOut
= fopen (argv
[3], "w+b")) == NULL
) {
184 Error (NULL
, 0, 0, "Unable to open file", argv
[3]);
189 // Copy the input file to the output file
191 if (CopyFile (FpIn
, FpOut
) != STATUS_SUCCESS
) {
197 // Close the reset vector data file
202 // Fix the destination relative in the jmp instruction
203 // in the reset vector data structure
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
);
213 if (fwrite (&DestRel
, sizeof (UINT16
), 1, FpOut
) != 1) {
214 Error (NULL
, 0, 0, "Failed to write to the output file", NULL
);
219 // Close the output file
223 return STATUS_SUCCESS
;
229 OUT UINT32
*EntryPoint
235 Get the address of the entry point of a PE/TE file.
239 PeFile - File pointer to the specified PE/TE file.
240 EntryPoint - Buffer for the address of the entry point to be returned.
243 STATUS_SUCCESS - Function completed successfully.
244 STATUS_ERROR - Error occured.
247 // GC_TODO: ExeFile - add argument and description to function comment
249 EFI_IMAGE_DOS_HEADER DosHeader
;
250 EFI_IMAGE_NT_HEADERS32 NtHeader
;
251 EFI_TE_IMAGE_HEADER TeHeader
;
254 // Check if it is a TE file
256 fseek (ExeFile
, 0, SEEK_SET
);
258 // Attempt to read the TE header
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
);
267 *EntryPoint
= TeHeader
.AddressOfEntryPoint
+ sizeof (EFI_TE_IMAGE_HEADER
) - TeHeader
.StrippedSize
;
268 return STATUS_SUCCESS
;
272 // Check if it is a PE file
274 fseek (ExeFile
, 0, SEEK_SET
);
276 // Attempt to read the DOS header
278 if (fread (&DosHeader
, sizeof (DosHeader
), 1, ExeFile
) != 1) {
282 // Check the magic number
284 if (DosHeader
.e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
288 // Position into the file and read the NT PE header
290 fseek (ExeFile
, (long) DosHeader
.e_lfanew
, SEEK_SET
);
291 if (fread (&NtHeader
, sizeof (NtHeader
), 1, ExeFile
) != 1) {
295 // Check the PE signature in the header
297 if (NtHeader
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
301 // Make sure the PE file is PE32 for IA32
303 if (NtHeader
.FileHeader
.Machine
!= EFI_IMAGE_MACHINE_IA32
||
304 NtHeader
.OptionalHeader
.Magic
!= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
306 Error (NULL
, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL
);
310 // Get the entry point from the optional header
312 *EntryPoint
= NtHeader
.OptionalHeader
.AddressOfEntryPoint
;
313 return STATUS_SUCCESS
;
316 Error (NULL
, 0, 0, "The SEC file is neither PE nor TE file", NULL
);
333 FpIn - File pointer to the source file.
334 FpOut - File pointer to the destination file.
337 STATUS_SUCCESS - Function completed successfully.
338 STATUS_ERROR - Error occured.
347 UINT8 Buffer
[BUF_SIZE
];
349 fseek (FpIn
, 0, SEEK_END
);
350 FileSize
= ftell (FpIn
);
352 fseek (FpIn
, 0, SEEK_SET
);
353 fseek (FpOut
, 0, SEEK_SET
);
356 while (Offset
< FileSize
) {
357 Length
= sizeof (Buffer
);
358 if (FileSize
- Offset
< Length
) {
359 Length
= FileSize
- Offset
;
362 if (fread (Buffer
, Length
, 1, FpIn
) != 1 || fwrite (Buffer
, Length
, 1, FpOut
) != 1) {
363 Error (NULL
, 0, 0, "Copy file error", NULL
);
370 return STATUS_SUCCESS
;