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