]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/TianoTools/GenTEImage/GenTEImage.c
26349b4b83e33a8e7d28906725b82a0afdb2d9d6
[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 <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] == '-') || (Argv[0][0] == '/'))) {
676 //
677 // To simplify string comparisons, replace slashes with dashes
678 //
679 Argv[0][0] = '-';
680 if (stricmp (Argv[0], "-o") == 0) {
681 //
682 // Output filename specified with -o
683 // Make sure there's another parameter
684 //
685 if (Argc > 1) {
686 strcpy (mOptions.OutFileName, Argv[1]);
687 } else {
688 Error (NULL, 0, 0, Argv[0], "missing output file name with option");
689 Usage ();
690 return STATUS_ERROR;
691 }
692
693 Argv++;
694 Argc--;
695 } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {
696 //
697 // Help option
698 //
699 Usage ();
700 return STATUS_ERROR;
701 } else if (stricmp (Argv[0], "-v") == 0) {
702 //
703 // -v for verbose
704 //
705 mOptions.Verbose = 1;
706 } else if (stricmp (Argv[0], "-dump") == 0) {
707 //
708 // -dump for dumping an image
709 //
710 mOptions.Dump = 1;
711 } else {
712 Error (NULL, 0, 0, Argv[0], "unrecognized option");
713 Usage ();
714 return STATUS_ERROR;
715 }
716 //
717 // Next argument
718 //
719 Argv++;
720 Argc--;
721 }
722 //
723 // Better be one more arg for input file name
724 //
725 if (Argc == 0) {
726 Error (NULL, 0, 0, "input file name required", NULL);
727 Usage ();
728 return STATUS_ERROR;
729 }
730
731 if (Argc != 1) {
732 Error (NULL, 0, 0, Argv[1], "extra arguments on command line");
733 return STATUS_ERROR;
734 }
735
736 strcpy (mOptions.InFileName, Argv[0]);
737 return STATUS_SUCCESS;
738 }
739
740 static
741 void
742 Usage (
743 VOID
744 )
745 /*++
746
747 Routine Description:
748
749 Print usage information for this utility.
750
751 Arguments:
752
753 None.
754
755 Returns:
756
757 Nothing.
758
759 --*/
760 {
761 int Index;
762 static const char *Msg[] = {
763 UTILITY_NAME " version "UTILITY_VERSION " - TE image utility",
764 " Generate a TE image from an EFI PE32 image",
765 " Usage: "UTILITY_NAME " {-v} {-dump} {-h|-?} {-o OutFileName} InFileName",
766 " [-e|-b] [FileName(s)]",
767 " where:",
768 " -v - for verbose output",
769 " -dump - to dump the input file to a text file",
770 " -h -? - for this help information",
771 " -o OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,
772 " InFileName - name of the input PE32 file",
773 "",
774 NULL
775 };
776 for (Index = 0; Msg[Index] != NULL; Index++) {
777 fprintf (stdout, "%s\n", Msg[Index]);
778 }
779 }
780
781 static
782 VOID
783 DumpImage (
784 INT8 *FileName
785 )
786 /*++
787
788 Routine Description:
789
790 Dump a specified image information
791
792 Arguments:
793
794 FileName - File name pointer to the image to dump
795
796 Returns:
797
798 Nothing.
799
800 --*/
801 {
802 FILE *InFptr;
803 EFI_TE_IMAGE_HEADER TEImageHeader;
804 INT8 *NamePtr;
805
806 //
807 // Open the input file
808 //
809 InFptr = NULL;
810
811 if ((InFptr = fopen (FileName, "rb")) == NULL) {
812 Error (NULL, 0, 0, FileName, "failed to open input file for reading");
813 return ;
814 }
815
816 if (fread (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, InFptr) != 1) {
817 Error (NULL, 0, 0, FileName, "failed to read image header from input file");
818 goto Finish;
819 }
820
821 if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
822 Error (NULL, 0, 0, FileName, "Image does not appear to be a TE image (bad signature)");
823 goto Finish;
824 }
825 //
826 // Dump the header
827 //
828 fprintf (stdout, "Header (%d bytes):\n", sizeof (EFI_TE_IMAGE_HEADER));
829 fprintf (stdout, " Signature: 0x%04X (TE)\n", (UINT32) TEImageHeader.Signature);
830 NamePtr = GetMachineTypeStr (TEImageHeader.Machine);
831 fprintf (stdout, " Machine: 0x%04X (%s)\n", (UINT32) TEImageHeader.Machine, NamePtr);
832 NamePtr = GetSubsystemTypeStr (TEImageHeader.Subsystem);
833 fprintf (stdout, " Subsystem: 0x%02X (%s)\n", (UINT32) TEImageHeader.Subsystem, NamePtr);
834 fprintf (stdout, " Number of sections 0x%02X\n", (UINT32) TEImageHeader.NumberOfSections);
835 fprintf (stdout, " Stripped size: 0x%04X\n", (UINT32) TEImageHeader.StrippedSize);
836 fprintf (stdout, " Entry point: 0x%08X\n", TEImageHeader.AddressOfEntryPoint);
837 fprintf (stdout, " Base of code: 0x%08X\n", TEImageHeader.BaseOfCode);
838 fprintf (stdout, " Data directories:\n");
839 fprintf (
840 stdout,
841 " %8X [%8X] RVA [size] of Base Relocation Directory\n",
842 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
843 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size
844 );
845 fprintf (
846 stdout,
847 " %8X [%8X] RVA [size] of Debug Directory\n",
848 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
849 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size
850 );
851
852 Finish:
853 if (InFptr != NULL) {
854 fclose (InFptr);
855 }
856 }
857
858 static
859 INT8 *
860 GetMachineTypeStr (
861 UINT16 MachineType
862 )
863 /*++
864
865 Routine Description:
866
867 GC_TODO: Add function description
868
869 Arguments:
870
871 MachineType - GC_TODO: add argument description
872
873 Returns:
874
875 GC_TODO: add return values
876
877 --*/
878 {
879 int Index;
880
881 for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {
882 if (mMachineTypes[Index].Value == MachineType) {
883 return mMachineTypes[Index].Name;
884 }
885 }
886
887 return "unknown";
888 }
889
890 static
891 INT8 *
892 GetSubsystemTypeStr (
893 UINT16 SubsystemType
894 )
895 /*++
896
897 Routine Description:
898
899 GC_TODO: Add function description
900
901 Arguments:
902
903 SubsystemType - GC_TODO: add argument description
904
905 Returns:
906
907 GC_TODO: add return values
908
909 --*/
910 {
911 int Index;
912
913 for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {
914 if (mSubsystemTypes[Index].Value == SubsystemType) {
915 return mSubsystemTypes[Index].Name;
916 }
917 }
918
919 return "unknown";
920 }