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