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