3 Copyright (c) 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
18 A utility that extracts the .DATA section from a PE/COFF image.
27 #include "TianoCommon.h"
28 #include "EfiImage.h" // for PE32 structure definitions
29 #include "EfiUtilityMsgs.h"
32 // Version of this utility
34 #define UTILITY_NAME "GenAcpiTable"
35 #define UTILITY_VERSION "v0.11"
38 // Define the max length of a filename
41 #define DEFAULT_OUTPUT_EXTENSION ".acpi"
44 // Use this to track our command-line options and globals
47 INT8 OutFileName
[MAX_PATH
];
48 INT8 InFileName
[MAX_PATH
];
52 // Use these to convert from machine type value to a named type
59 static STRING_LOOKUP mMachineTypes
[] = {
60 EFI_IMAGE_MACHINE_IA32
,
62 EFI_IMAGE_MACHINE_IA64
,
64 EFI_IMAGE_MACHINE_EBC
,
70 static STRING_LOOKUP mSubsystemTypes
[] = {
71 EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
,
73 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
,
74 "EFI boot service driver",
75 EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
,
81 // Function prototypes
129 Argc - standard C main() argument count
131 Argv - standard C main() argument list
139 // GC_TODO: ] - add argument and description to function comment
143 SetUtilityName (UTILITY_NAME
);
145 // Parse the command line arguments
147 if (ParseCommandLine (Argc
, Argv
)) {
151 // Make sure we don't have the same filename for input and output files
153 if (stricmp (mOptions
.OutFileName
, mOptions
.InFileName
) == 0) {
154 Error (NULL
, 0, 0, mOptions
.OutFileName
, "input and output file names must be different");
160 ProcessFile (mOptions
.InFileName
, mOptions
.OutFileName
);
162 Status
= GetUtilityStatus ();
176 Process a PE32 EFI file.
180 InFileName - Name of the PE32 EFI file to process.
181 OutFileName - Name of the output file for the processed data.
196 EFI_IMAGE_FILE_HEADER FileHeader
;
197 EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32
;
198 EFI_IMAGE_SECTION_HEADER SectionHeader
;
200 long SaveFilePosition
;
205 Status
= STATUS_ERROR
;
207 // Try to open the input file
209 if ((InFptr
= fopen (InFileName
, "rb")) == NULL
) {
210 Error (NULL
, 0, 0, InFileName
, "failed to open input file for reading");
214 // Double-check the file to make sure it's what we expect it to be
216 if (CheckPE32File (InFileName
, InFptr
, &MachineType
, &SubSystem
) != STATUS_SUCCESS
) {
220 // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit
221 // offset (from the start of the file) to the PE signature, which always
222 // follows the MSDOS stub. The PE signature is immediately followed by the
226 if (fseek (InFptr
, 0x3C, SEEK_SET
) != 0) {
227 Error (NULL
, 0, 0, InFileName
, "failed to seek to PE signature in file", NULL
);
231 if (fread (&PESigOffset
, sizeof (PESigOffset
), 1, InFptr
) != 1) {
232 Error (NULL
, 0, 0, InFileName
, "failed to read PE signature offset from file");
236 if (fseek (InFptr
, PESigOffset
+ 4, SEEK_SET
) != 0) {
237 Error (NULL
, 0, 0, InFileName
, "failed to seek to PE signature");
241 // We should now be at the COFF file header. Read it in and verify it's
242 // of an image type we support.
244 if (fread (&FileHeader
, sizeof (EFI_IMAGE_FILE_HEADER
), 1, InFptr
) != 1) {
245 Error (NULL
, 0, 0, InFileName
, "failed to read file header from image");
249 if ((FileHeader
.Machine
!= EFI_IMAGE_MACHINE_IA32
) && (FileHeader
.Machine
!= EFI_IMAGE_MACHINE_IA64
) && (FileHeader
.Machine
!= EFI_IMAGE_MACHINE_X64
)) {
250 Error (NULL
, 0, 0, InFileName
, "image is of an unsupported machine type 0x%X", (UINT32
) FileHeader
.Machine
);
254 // Read in the optional header. Assume PE32, and if not, then re-read as PE32+
256 SaveFilePosition
= ftell (InFptr
);
257 if (fread (&OptionalHeader32
, sizeof (EFI_IMAGE_OPTIONAL_HEADER32
), 1, InFptr
) != 1) {
258 Error (NULL
, 0, 0, InFileName
, "failed to read optional header from input file");
262 if (OptionalHeader32
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
263 if (fseek (InFptr
, SaveFilePosition
, SEEK_SET
) != 0) {
264 Error (NULL
, 0, 0, InFileName
, "failed to seek to .data section");
268 if (fread (&OptionalHeader32
, sizeof (EFI_IMAGE_OPTIONAL_HEADER64
), 1, InFptr
) != 1) {
269 Error (NULL
, 0, 0, InFileName
, "failed to read optional header from input file");
274 // Search for the ".data" section
276 for (Index
= 0; Index
< FileHeader
.NumberOfSections
; Index
++) {
277 if (fread (&SectionHeader
, sizeof (EFI_IMAGE_SECTION_HEADER
), 1, InFptr
) != 1) {
278 Error (NULL
, 0, 0, InFileName
, "failed to read optional header from input file");
282 if (strcmp (SectionHeader
.Name
, ".data") == 0) {
283 if (fseek (InFptr
, SectionHeader
.PointerToRawData
, SEEK_SET
) != 0) {
284 Error (NULL
, 0, 0, InFileName
, "failed to seek to .data section");
288 Buffer
= (UINT8
*) malloc (SectionHeader
.Misc
.VirtualSize
);
289 if (Buffer
== NULL
) {
290 Status
= EFI_OUT_OF_RESOURCES
;
293 if (fread (Buffer
, SectionHeader
.Misc
.VirtualSize
, 1, InFptr
) != 1) {
294 Error (NULL
, 0, 0, InFileName
, "failed to .data section");
298 // Now open our output file
300 if ((OutFptr
= fopen (OutFileName
, "wb")) == NULL
) {
301 Error (NULL
, 0, 0, OutFileName
, "failed to open output file for writing");
305 if (fwrite (Buffer
, SectionHeader
.Misc
.VirtualSize
, 1, OutFptr
) != 1) {
306 Error (NULL
, 0, 0, OutFileName
, "failed to write .data section");
310 Status
= STATUS_SUCCESS
;
315 Status
= STATUS_ERROR
;
318 if (InFptr
!= NULL
) {
322 // Close the output file. If there was an error, delete the output file so
323 // that a subsequent build will rebuild it.
325 if (OutFptr
!= NULL
) {
327 if (GetUtilityStatus () == STATUS_ERROR
) {
328 remove (OutFileName
);
333 // Free up our buffer
335 if (Buffer
!= NULL
) {
354 GC_TODO: Add function description
358 FileName - GC_TODO: add argument description
359 Fptr - GC_TODO: add argument description
360 MachineType - GC_TODO: add argument description
361 SubSystem - GC_TODO: add argument description
365 GC_TODO: add return values
373 Given a file pointer to a supposed PE32 image file, verify that it is indeed a
374 PE32 image file, and then return the machine type in the supplied pointer.
378 Fptr File pointer to the already-opened PE32 file
379 MachineType Location to stuff the machine type of the PE32 file. This is needed
380 because the image may be Itanium-based, IA32, or EBC.
388 EFI_IMAGE_DOS_HEADER DosHeader
;
389 EFI_IMAGE_FILE_HEADER FileHdr
;
390 EFI_IMAGE_OPTIONAL_HEADER OptionalHdr
;
394 Status
= STATUS_ERROR
;
396 // Position to the start of the file
398 fseek (Fptr
, 0, SEEK_SET
);
400 // Read the DOS header
402 if (fread (&DosHeader
, sizeof (DosHeader
), 1, Fptr
) != 1) {
403 Error (NULL
, 0, 0, FileName
, "failed to read the DOS stub from the input file");
407 // Check the magic number (0x5A4D)
409 if (DosHeader
.e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
410 Error (NULL
, 0, 0, FileName
, "input file does not appear to be a PE32 image (magic number)");
414 // Position into the file and check the PE signature
416 fseek (Fptr
, (long) DosHeader
.e_lfanew
, SEEK_SET
);
417 if (fread (&PESig
, sizeof (PESig
), 1, Fptr
) != 1) {
418 Error (NULL
, 0, 0, FileName
, "failed to read PE signature bytes");
422 // Check the PE signature in the header "PE\0\0"
424 if (PESig
!= EFI_IMAGE_NT_SIGNATURE
) {
425 Error (NULL
, 0, 0, FileName
, "file does not appear to be a PE32 image (signature)");
429 // Read the file header
431 if (fread (&FileHdr
, sizeof (FileHdr
), 1, Fptr
) != 1) {
432 Error (NULL
, 0, 0, FileName
, "failed to read PE file header from input file");
436 // Read the optional header so we can get the subsystem
438 if (fread (&OptionalHdr
, sizeof (OptionalHdr
), 1, Fptr
) != 1) {
439 Error (NULL
, 0, 0, FileName
, "failed to read COFF optional header from input file");
443 *SubSystem
= OptionalHdr
.Subsystem
;
447 Status
= STATUS_SUCCESS
;
449 fseek (Fptr
, 0, SEEK_SET
);
463 Given the Argc/Argv program arguments, and a pointer to an options structure,
464 parse the command-line options and check their validity.
469 Argc - standard C main() argument count
470 Argv - standard C main() argument list
474 STATUS_SUCCESS success
478 // GC_TODO: ] - add argument and description to function comment
481 // Clear out the options
483 memset ((char *) &mOptions
, 0, sizeof (mOptions
));
485 // Skip over the program name
495 strcpy (mOptions
.InFileName
, Argv
[0]);
502 strcpy (mOptions
.OutFileName
, Argv
[0]);
504 return STATUS_SUCCESS
;
516 Print usage information for this utility.
529 static const char *Msg
[] = {
530 UTILITY_NAME
" version "UTILITY_VERSION
" - Generate ACPI Table image utility",
531 " Generate an ACPI Table image from an EFI PE32 image",
532 " Usage: "UTILITY_NAME
" InFileName OutFileName",
534 " InFileName - name of the input PE32 file",
535 " OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION
,
539 for (Index
= 0; Msg
[Index
] != NULL
; Index
++) {
540 fprintf (stdout
, "%s\n", Msg
[Index
]);