]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/GenTEImage/GenTEImage.c
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / GenTEImage / GenTEImage.c
1 /*++
2
3 Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this 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 Module Name:
13
14 GenTEImage.c
15
16 Abstract:
17
18 Utility program to shrink a PE32 image down by replacing
19 the DOS, PE, and optional headers with a minimal header.
20
21 --*/
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26
27 #include "Tiano.h"
28 #include "TianoCommon.h"
29 #include "EfiImage.h" // for PE32 structure definitions
30 #include "EfiUtilityMsgs.h"
31
32 //
33 // Version of this utility
34 //
35 #define UTILITY_NAME "GenTEImage"
36 #define UTILITY_VERSION "v1.0"
37
38 //
39 // Define the max length of a filename
40 //
41 #define MAX_PATH 256
42 #define DEFAULT_OUTPUT_EXTENSION ".te"
43
44 //
45 // Use this to track our command-line options and globals
46 //
47 struct {
48 INT8 OutFileName[MAX_PATH];
49 INT8 InFileName[MAX_PATH];
50 INT8 Verbose;
51 INT8 Dump;
52 } mOptions;
53
54 //
55 // Use these to convert from machine type value to a named type
56 //
57 typedef struct {
58 UINT16 Value;
59 INT8 *Name;
60 } STRING_LOOKUP;
61
62 static STRING_LOOKUP mMachineTypes[] = {
63 EFI_IMAGE_MACHINE_IA32,
64 "IA32",
65 EFI_IMAGE_MACHINE_IA64,
66 "IA64",
67 EFI_IMAGE_MACHINE_X64,
68 "X64",
69 EFI_IMAGE_MACHINE_EBC,
70 "EBC",
71 0,
72 NULL
73 };
74
75 static STRING_LOOKUP mSubsystemTypes[] = {
76 EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
77 "EFI application",
78 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,
79 "EFI boot service driver",
80 EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,
81 "EFI runtime driver",
82 0,
83 NULL
84 };
85 //
86 // Function prototypes
87 //
88 static
89 void
90 Usage (
91 VOID
92 );
93
94 static
95 STATUS
96 ParseCommandLine (
97 int Argc,
98 char *Argv[]
99 );
100
101 static
102 STATUS
103 CheckPE32File (
104 INT8 *FileName,
105 FILE *Fptr,
106 UINT16 *MachineType,
107 UINT16 *SubSystem
108 );
109
110 static
111 STATUS
112 ProcessFile (
113 INT8 *InFileName,
114 INT8 *OutFileName
115 );
116
117 static
118 void
119 DumpImage (
120 INT8 *FileName
121 );
122
123 static
124 INT8 *
125 GetMachineTypeStr (
126 UINT16 MachineType
127 );
128
129 static
130 INT8 *
131 GetSubsystemTypeStr (
132 UINT16 SubsystemType
133 );
134
135 int
136 main (
137 int Argc,
138 char *Argv[]
139 )
140 /*++
141
142 Routine Description:
143
144
145 Arguments:
146
147 Argc - standard C main() argument count
148
149 Argv - standard C main() argument list
150
151 Returns:
152
153 0 success
154 non-zero otherwise
155
156 --*/
157 // GC_TODO: ] - add argument and description to function comment
158 {
159 INT8 *Ext;
160 UINT32 Status;
161
162 SetUtilityName (UTILITY_NAME);
163 //
164 // Parse the command line arguments
165 //
166 if (ParseCommandLine (Argc, Argv)) {
167 return STATUS_ERROR;
168 }
169 //
170 // If dumping an image, then do that and quit
171 //
172 if (mOptions.Dump) {
173 DumpImage (mOptions.InFileName);
174 goto Finish;
175 }
176 //
177 // Determine the output filename. Either what they specified on
178 // the command line, or the first input filename with a different extension.
179 //
180 if (!mOptions.OutFileName[0]) {
181 strcpy (mOptions.OutFileName, mOptions.InFileName);
182 //
183 // Find the last . on the line and replace the filename extension with
184 // the default
185 //
186 for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;
187 (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');
188 Ext--
189 )
190 ;
191 //
192 // If dot here, then insert extension here, otherwise append
193 //
194 if (*Ext != '.') {
195 Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);
196 }
197
198 strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);
199 }
200 //
201 // Make sure we don't have the same filename for input and output files
202 //
203 if (_stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {
204 Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");
205 goto Finish;
206 }
207 //
208 // Process the file
209 //
210 ProcessFile (mOptions.InFileName, mOptions.OutFileName);
211 Finish:
212 Status = GetUtilityStatus ();
213 return Status;
214 }
215
216 static
217 STATUS
218 ProcessFile (
219 INT8 *InFileName,
220 INT8 *OutFileName
221 )
222 /*++
223
224 Routine Description:
225
226 Process a PE32 EFI file.
227
228 Arguments:
229
230 InFileName - the file name pointer to the input file
231 OutFileName - the file name pointer to the output file
232
233 Returns:
234
235 STATUS_SUCCESS - the process has been finished successfully
236 STATUS_ERROR - error occured during the processing
237
238 --*/
239 {
240 STATUS Status;
241 FILE *InFptr;
242 FILE *OutFptr;
243 UINT16 MachineType;
244 UINT16 SubSystem;
245 EFI_TE_IMAGE_HEADER TEImageHeader;
246 UINT32 PESigOffset;
247 EFI_IMAGE_FILE_HEADER FileHeader;
248 EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
249 EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
250 UINT32 BytesStripped;
251 UINT32 FileSize;
252 UINT8 *Buffer;
253 long SaveFilePosition;
254
255 InFptr = NULL;
256 OutFptr = NULL;
257 Buffer = NULL;
258 Status = STATUS_ERROR;
259
260 //
261 // Try to open the input file
262 //
263 if ((InFptr = fopen (InFileName, "rb")) == NULL) {
264 Error (NULL, 0, 0, InFileName, "failed to open input file for reading");
265 return STATUS_ERROR;
266 }
267 //
268 // Double-check the file to make sure it's what we expect it to be
269 //
270 if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {
271 goto Finish;
272 }
273 //
274 // Initialize our new header
275 //
276 memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));
277
278 //
279 // Seek to the end to get the file size
280 //
281 fseek (InFptr, 0, SEEK_END);
282 FileSize = ftell (InFptr);
283 fseek (InFptr, 0, SEEK_SET);
284
285 //
286 // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit
287 // offset (from the start of the file) to the PE signature, which always
288 // follows the MSDOS stub. The PE signature is immediately followed by the
289 // COFF file header.
290 //
291 //
292 if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {
293 Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);
294 goto Finish;
295 }
296
297 if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {
298 Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");
299 goto Finish;
300 }
301
302 if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {
303 Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");
304 goto Finish;
305 }
306 //
307 // We should now be at the COFF file header. Read it in and verify it's
308 // of an image type we support.
309 //
310 if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {
311 Error (NULL, 0, 0, InFileName, "failed to read file header from image");
312 goto Finish;
313 }
314
315 if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) &&
316 (FileHeader.Machine != EFI_IMAGE_MACHINE_X64) &&
317 (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64)) {
318 Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);
319 goto Finish;
320 }
321 //
322 // Calculate the total number of bytes we're going to strip off. The '4' is for the
323 // PE signature PE\0\0. Then sanity check the size.
324 //
325 BytesStripped = PESigOffset + 4 + sizeof (EFI_IMAGE_FILE_HEADER) + FileHeader.SizeOfOptionalHeader;
326 if (BytesStripped >= FileSize) {
327 Error (NULL, 0, 0, InFileName, "attempt to strip more bytes than the total file size");
328 goto Finish;
329 }
330
331 if (BytesStripped &~0xFFFF) {
332 Error (NULL, 0, 0, InFileName, "attempt to strip more than 64K bytes", NULL);
333 goto Finish;
334 }
335
336 TEImageHeader.StrippedSize = (UINT16) BytesStripped;
337
338 //
339 // Read in the optional header. Assume PE32, and if not, then re-read as PE32+
340 //
341 SaveFilePosition = ftell (InFptr);
342 if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {
343 Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");
344 goto Finish;
345 }
346
347 if (OptionalHeader32.SectionAlignment != OptionalHeader32.FileAlignment) {
348 Error (NULL, 0, 0, InFileName, "Section alignment is not same to file alignment.");
349 goto Finish;
350 }
351
352 if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
353 //
354 // Fill in our new header with required data directory entries
355 //
356 TEImageHeader.AddressOfEntryPoint = OptionalHeader32.AddressOfEntryPoint;
357 //
358 // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);
359 //
360 // We're going to pack the subsystem into 1 byte. Make sure it fits
361 //
362 if (OptionalHeader32.Subsystem &~0xFF) {
363 Error (
364 NULL,
365 0,
366 0,
367 InFileName,
368 NULL,
369 "image subsystem 0x%X cannot be packed into 1 byte",
370 (UINT32) OptionalHeader32.Subsystem
371 );
372 goto Finish;
373 }
374
375 TEImageHeader.Subsystem = (UINT8) OptionalHeader32.Subsystem;
376 TEImageHeader.BaseOfCode = OptionalHeader32.BaseOfCode;
377 TEImageHeader.ImageBase = (UINT64) (OptionalHeader32.ImageBase);
378 if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
379 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
380 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
381 }
382
383 if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
384 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
385 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
386 }
387 } else if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
388 //
389 // Rewind and re-read the optional header
390 //
391 fseek (InFptr, SaveFilePosition, SEEK_SET);
392 if (fread (&OptionalHeader64, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {
393 Error (NULL, 0, 0, InFileName, "failed to re-read optional header from input file");
394 goto Finish;
395 }
396
397 TEImageHeader.AddressOfEntryPoint = OptionalHeader64.AddressOfEntryPoint;
398 //
399 // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);
400 //
401 // We're going to pack the subsystem into 1 byte. Make sure it fits
402 //
403 if (OptionalHeader64.Subsystem &~0xFF) {
404 Error (
405 NULL,
406 0,
407 0,
408 InFileName,
409 NULL,
410 "image subsystem 0x%X cannot be packed into 1 byte",
411 (UINT32) OptionalHeader64.Subsystem
412 );
413 goto Finish;
414 }
415
416 TEImageHeader.Subsystem = (UINT8) OptionalHeader64.Subsystem;
417 TEImageHeader.BaseOfCode = OptionalHeader64.BaseOfCode;
418 TEImageHeader.ImageBase = (UINT64) (OptionalHeader64.ImageBase);
419 if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
420 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
421 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
422 }
423
424 if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
425 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
426 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
427 }
428 } else {
429 Error (
430 NULL,
431 0,
432 0,
433 InFileName,
434 "unsupported magic number 0x%X found in optional header",
435 (UINT32) OptionalHeader32.Magic
436 );
437 goto Finish;
438 }
439 //
440 // Fill in the remainder of our new image header
441 //
442 TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE;
443 TEImageHeader.Machine = FileHeader.Machine;
444 //
445 // We're going to pack the number of sections into a single byte. Make sure it fits.
446 //
447 if (FileHeader.NumberOfSections &~0xFF) {
448 Error (
449 NULL,
450 0,
451 0,
452 InFileName,
453 NULL,
454 "image's number of sections 0x%X cannot be packed into 1 byte",
455 (UINT32) FileHeader.NumberOfSections
456 );
457 goto Finish;
458 }
459
460 TEImageHeader.NumberOfSections = (UINT8) FileHeader.NumberOfSections;
461
462 //
463 // Now open our output file
464 //
465 if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
466 Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");
467 goto Finish;
468 }
469 //
470 // Write the TE header
471 //
472 if (fwrite (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, OutFptr) != 1) {
473 Error (NULL, 0, 0, "failed to write image header to output file", NULL);
474 goto Finish;
475 }
476 //
477 // Position into the input file, read the part we're not stripping, and
478 // write it out.
479 //
480 fseek (InFptr, BytesStripped, SEEK_SET);
481 Buffer = (UINT8 *) malloc (FileSize - BytesStripped);
482 if (Buffer == NULL) {
483 Error (NULL, 0, 0, "application error", "failed to allocate memory");
484 goto Finish;
485 }
486
487 if (fread (Buffer, FileSize - BytesStripped, 1, InFptr) != 1) {
488 Error (NULL, 0, 0, InFileName, "failed to read remaining contents of input file");
489 goto Finish;
490 }
491
492 if (fwrite (Buffer, FileSize - BytesStripped, 1, OutFptr) != 1) {
493 Error (NULL, 0, 0, OutFileName, "failed to write all bytes to output file");
494 goto Finish;
495 }
496
497 Status = STATUS_SUCCESS;
498
499 Finish:
500 if (InFptr != NULL) {
501 fclose (InFptr);
502 }
503 //
504 // Close the output file. If there was an error, delete the output file so
505 // that a subsequent build will rebuild it.
506 //
507 if (OutFptr != NULL) {
508 fclose (OutFptr);
509 if (GetUtilityStatus () == STATUS_ERROR) {
510 remove (OutFileName);
511 }
512 }
513
514 //
515 // Free up our buffer
516 //
517 if (Buffer != NULL) {
518 free (Buffer);
519 }
520
521 return Status;
522 }
523
524 static
525 STATUS
526 CheckPE32File (
527 INT8 *FileName,
528 FILE *Fptr,
529 UINT16 *MachineType,
530 UINT16 *SubSystem
531 )
532 /*++
533
534 Routine Description:
535
536 GC_TODO: Add function description
537
538 Arguments:
539
540 FileName - GC_TODO: add argument description
541 Fptr - GC_TODO: add argument description
542 MachineType - GC_TODO: add argument description
543 SubSystem - GC_TODO: add argument description
544
545 Returns:
546
547 GC_TODO: add return values
548
549 --*/
550 {
551 /*++
552
553 Routine Description:
554
555 Given a file pointer to a supposed PE32 image file, verify that it is indeed a
556 PE32 image file, and then return the machine type in the supplied pointer.
557
558 Arguments:
559
560 Fptr File pointer to the already-opened PE32 file
561 MachineType Location to stuff the machine type of the PE32 file. This is needed
562 because the image may be Itanium-based, IA32, or EBC.
563
564 Returns:
565
566 0 success
567 non-zero otherwise
568
569 --*/
570 EFI_IMAGE_DOS_HEADER DosHeader;
571 EFI_IMAGE_FILE_HEADER FileHdr;
572 EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;
573 UINT32 PESig;
574 STATUS Status;
575
576 Status = STATUS_ERROR;
577 //
578 // Position to the start of the file
579 //
580 fseek (Fptr, 0, SEEK_SET);
581 //
582 // Read the DOS header
583 //
584 if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
585 Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");
586 goto Finish;
587 }
588 //
589 // Check the magic number (0x5A4D)
590 //
591 if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
592 Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");
593 goto Finish;
594 }
595 //
596 // Position into the file and check the PE signature
597 //
598 fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);
599 if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {
600 Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");
601 goto Finish;
602 }
603 //
604 // Check the PE signature in the header "PE\0\0"
605 //
606 if (PESig != EFI_IMAGE_NT_SIGNATURE) {
607 Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");
608 goto Finish;
609 }
610 //
611 // Read the file header
612 //
613 if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {
614 Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");
615 goto Finish;
616 }
617 //
618 // Read the optional header so we can get the subsystem
619 //
620 if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {
621 Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");
622 goto Finish;
623 }
624
625 *SubSystem = OptionalHdr.Subsystem;
626 if (mOptions.Verbose) {
627 fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem);
628 }
629 //
630 // Good to go
631 //
632 Status = STATUS_SUCCESS;
633 Finish:
634 fseek (Fptr, 0, SEEK_SET);
635 return Status;
636 }
637
638 static
639 int
640 ParseCommandLine (
641 int Argc,
642 char *Argv[]
643 )
644 /*++
645
646 Routine Description:
647
648 Given the Argc/Argv program arguments, and a pointer to an options structure,
649 parse the command-line options and check their validity.
650
651
652 Arguments:
653
654 Argc - standard C main() argument count
655 Argv - standard C main() argument list
656
657 Returns:
658
659 STATUS_SUCCESS success
660 non-zero otherwise
661
662 --*/
663 // GC_TODO: ] - add argument and description to function comment
664 {
665 //
666 // Clear out the options
667 //
668 memset ((char *) &mOptions, 0, sizeof (mOptions));
669 //
670 // Skip over the program name
671 //
672 Argc--;
673 Argv++;
674 //
675 // If no arguments, assume they want usage info
676 //
677 if (Argc == 0) {
678 Usage ();
679 return STATUS_ERROR;
680 }
681 //
682 // Process until no more arguments
683 //
684 while ((Argc > 0) && ((Argv[0][0] == '-') || (Argv[0][0] == '/'))) {
685 //
686 // To simplify string comparisons, replace slashes with dashes
687 //
688 Argv[0][0] = '-';
689 if (_stricmp (Argv[0], "-o") == 0) {
690 //
691 // Output filename specified with -o
692 // Make sure there's another parameter
693 //
694 if (Argc > 1) {
695 strcpy (mOptions.OutFileName, Argv[1]);
696 } else {
697 Error (NULL, 0, 0, Argv[0], "missing output file name with option");
698 Usage ();
699 return STATUS_ERROR;
700 }
701
702 Argv++;
703 Argc--;
704 } else if ((_stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {
705 //
706 // Help option
707 //
708 Usage ();
709 return STATUS_ERROR;
710 } else if (_stricmp (Argv[0], "-v") == 0) {
711 //
712 // -v for verbose
713 //
714 mOptions.Verbose = 1;
715 } else if (_stricmp (Argv[0], "-dump") == 0) {
716 //
717 // -dump for dumping an image
718 //
719 mOptions.Dump = 1;
720 } else {
721 Error (NULL, 0, 0, Argv[0], "unrecognized option");
722 Usage ();
723 return STATUS_ERROR;
724 }
725 //
726 // Next argument
727 //
728 Argv++;
729 Argc--;
730 }
731 //
732 // Better be one more arg for input file name
733 //
734 if (Argc == 0) {
735 Error (NULL, 0, 0, "input file name required", NULL);
736 Usage ();
737 return STATUS_ERROR;
738 }
739
740 if (Argc != 1) {
741 Error (NULL, 0, 0, Argv[1], "extra arguments on command line");
742 return STATUS_ERROR;
743 }
744
745 strcpy (mOptions.InFileName, Argv[0]);
746 return STATUS_SUCCESS;
747 }
748
749 static
750 void
751 Usage (
752 VOID
753 )
754 /*++
755
756 Routine Description:
757
758 Print usage information for this utility.
759
760 Arguments:
761
762 None.
763
764 Returns:
765
766 Nothing.
767
768 --*/
769 {
770 int Index;
771 const char *Str[] = {
772 UTILITY_NAME" "UTILITY_VERSION" - Intel Generate TE Image Utility",
773 " Copyright (C), 1999 - 2008 Intel Corporation",
774
775 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
776 " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
777 #endif
778 "",
779 "Usage:",
780 " "UTILITY_NAME" [OPTION]... PE32IMAGE",
781 "Description:",
782 " Generate a TE image from an EFI PE32 image.",
783 "Options:",
784 " -v - for verbose output",
785 " -dump - to dump the input file to a text file",
786 " -h -? - for this help information",
787 " -o OutFileName - to write output to OutFileName rather than PE32IMAGE"DEFAULT_OUTPUT_EXTENSION,
788 NULL
789 };
790 for (Index = 0; Str[Index] != NULL; Index++) {
791 fprintf (stdout, "%s\n", Str[Index]);
792 }
793 }
794
795 static
796 VOID
797 DumpImage (
798 INT8 *FileName
799 )
800 /*++
801
802 Routine Description:
803
804 Dump a specified image information
805
806 Arguments:
807
808 FileName - File name pointer to the image to dump
809
810 Returns:
811
812 Nothing.
813
814 --*/
815 {
816 FILE *InFptr;
817 EFI_TE_IMAGE_HEADER TEImageHeader;
818 INT8 *NamePtr;
819
820 //
821 // Open the input file
822 //
823 InFptr = NULL;
824
825 if ((InFptr = fopen (FileName, "rb")) == NULL) {
826 Error (NULL, 0, 0, FileName, "failed to open input file for reading");
827 return ;
828 }
829
830 if (fread (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, InFptr) != 1) {
831 Error (NULL, 0, 0, FileName, "failed to read image header from input file");
832 goto Finish;
833 }
834
835 if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
836 Error (NULL, 0, 0, FileName, "Image does not appear to be a TE image (bad signature)");
837 goto Finish;
838 }
839 //
840 // Dump the header
841 //
842 fprintf (stdout, "Header (%d bytes):\n", sizeof (EFI_TE_IMAGE_HEADER));
843 fprintf (stdout, " Signature: 0x%04X (TE)\n", (UINT32) TEImageHeader.Signature);
844 NamePtr = GetMachineTypeStr (TEImageHeader.Machine);
845 fprintf (stdout, " Machine: 0x%04X (%s)\n", (UINT32) TEImageHeader.Machine, NamePtr);
846 NamePtr = GetSubsystemTypeStr (TEImageHeader.Subsystem);
847 fprintf (stdout, " Subsystem: 0x%02X (%s)\n", (UINT32) TEImageHeader.Subsystem, NamePtr);
848 fprintf (stdout, " Number of sections 0x%02X\n", (UINT32) TEImageHeader.NumberOfSections);
849 fprintf (stdout, " Stripped size: 0x%04X\n", (UINT32) TEImageHeader.StrippedSize);
850 fprintf (stdout, " Entry point: 0x%08X\n", TEImageHeader.AddressOfEntryPoint);
851 fprintf (stdout, " Base of code: 0x%08X\n", TEImageHeader.BaseOfCode);
852 fprintf (stdout, " Data directories:\n");
853 fprintf (
854 stdout,
855 " %8X [%8X] RVA [size] of Base Relocation Directory\n",
856 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
857 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size
858 );
859 fprintf (
860 stdout,
861 " %8X [%8X] RVA [size] of Debug Directory\n",
862 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
863 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size
864 );
865
866 Finish:
867 if (InFptr != NULL) {
868 fclose (InFptr);
869 }
870 }
871
872 static
873 INT8 *
874 GetMachineTypeStr (
875 UINT16 MachineType
876 )
877 /*++
878
879 Routine Description:
880
881 GC_TODO: Add function description
882
883 Arguments:
884
885 MachineType - GC_TODO: add argument description
886
887 Returns:
888
889 GC_TODO: add return values
890
891 --*/
892 {
893 int Index;
894
895 for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {
896 if (mMachineTypes[Index].Value == MachineType) {
897 return mMachineTypes[Index].Name;
898 }
899 }
900
901 return "unknown";
902 }
903
904 static
905 INT8 *
906 GetSubsystemTypeStr (
907 UINT16 SubsystemType
908 )
909 /*++
910
911 Routine Description:
912
913 GC_TODO: Add function description
914
915 Arguments:
916
917 SubsystemType - GC_TODO: add argument description
918
919 Returns:
920
921 GC_TODO: add return values
922
923 --*/
924 {
925 int Index;
926
927 for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {
928 if (mSubsystemTypes[Index].Value == SubsystemType) {
929 return mSubsystemTypes[Index].Name;
930 }
931 }
932
933 return "unknown";
934 }