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