|
@@ -25,6 +25,7 @@
|
25
|
25
|
#include <unistd.h>
|
26
|
26
|
#include <errno.h>
|
27
|
27
|
#include <assert.h>
|
|
28
|
+#include <getopt.h>
|
28
|
29
|
#include <bfd.h>
|
29
|
30
|
|
30
|
31
|
/* Include the EFI PE image header file */
|
|
@@ -69,6 +70,8 @@ typedef uint64_t UINT64;
|
69
|
70
|
#define BIT31 0x80000000
|
70
|
71
|
#include "../include/gpxe/efi/IndustryStandard/PeImage.h"
|
71
|
72
|
|
|
73
|
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
|
|
74
|
+
|
72
|
75
|
#define EFI_FILE_ALIGN 0x20
|
73
|
76
|
|
74
|
77
|
struct pe_section {
|
|
@@ -127,13 +130,17 @@ static struct pe_header efi_pe_header = {
|
127
|
130
|
.FileAlignment = EFI_FILE_ALIGN,
|
128
|
131
|
.SizeOfImage = sizeof ( efi_pe_header ),
|
129
|
132
|
.SizeOfHeaders = sizeof ( efi_pe_header ),
|
130
|
|
- .Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
|
131
|
133
|
.NumberOfRvaAndSizes =
|
132
|
134
|
EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES,
|
133
|
135
|
},
|
134
|
136
|
},
|
135
|
137
|
};
|
136
|
138
|
|
|
139
|
+/** Command-line options */
|
|
140
|
+struct options {
|
|
141
|
+ unsigned int subsystem;
|
|
142
|
+};
|
|
143
|
+
|
137
|
144
|
/**
|
138
|
145
|
* Allocate memory
|
139
|
146
|
*
|
|
@@ -145,7 +152,7 @@ static void * xmalloc ( size_t len ) {
|
145
|
152
|
|
146
|
153
|
ptr = malloc ( len );
|
147
|
154
|
if ( ! ptr ) {
|
148
|
|
- fprintf ( stderr, "Could not allocate %zd bytes\n", len );
|
|
155
|
+ eprintf ( "Could not allocate %zd bytes\n", len );
|
149
|
156
|
exit ( 1 );
|
150
|
157
|
}
|
151
|
158
|
|
|
@@ -190,7 +197,7 @@ static void generate_pe_reloc ( struct pe_relocs **pe_reltab,
|
190
|
197
|
reloc |= 0x2000;
|
191
|
198
|
break;
|
192
|
199
|
default:
|
193
|
|
- fprintf ( stderr, "Unsupported relocation size %zd\n", size );
|
|
200
|
+ eprintf ( "Unsupported relocation size %zd\n", size );
|
194
|
201
|
exit ( 1 );
|
195
|
202
|
}
|
196
|
203
|
|
|
@@ -271,7 +278,7 @@ static bfd * open_input_bfd ( const char *filename ) {
|
271
|
278
|
/* Open the file */
|
272
|
279
|
bfd = bfd_openr ( filename, NULL );
|
273
|
280
|
if ( ! bfd ) {
|
274
|
|
- fprintf ( stderr, "Cannot open %s: ", filename );
|
|
281
|
+ eprintf ( "Cannot open %s: ", filename );
|
275
|
282
|
bfd_perror ( NULL );
|
276
|
283
|
exit ( 1 );
|
277
|
284
|
}
|
|
@@ -280,7 +287,7 @@ static bfd * open_input_bfd ( const char *filename ) {
|
280
|
287
|
* we get a segfault from later BFD calls.
|
281
|
288
|
*/
|
282
|
289
|
if ( bfd_check_format ( bfd, bfd_object ) < 0 ) {
|
283
|
|
- fprintf ( stderr, "%s is not an object file\n", filename );
|
|
290
|
+ eprintf ( "%s is not an object file\n", filename );
|
284
|
291
|
exit ( 1 );
|
285
|
292
|
}
|
286
|
293
|
|
|
@@ -442,8 +449,7 @@ static struct pe_section * process_section ( bfd *bfd,
|
442
|
449
|
if ( flags & SEC_LOAD ) {
|
443
|
450
|
if ( ! bfd_get_section_contents ( bfd, section, new->contents,
|
444
|
451
|
0, section_memsz ) ) {
|
445
|
|
- fprintf ( stderr, "Cannot read section %s: ",
|
446
|
|
- section->name );
|
|
452
|
+ eprintf ( "Cannot read section %s: ", section->name );
|
447
|
453
|
bfd_perror ( NULL );
|
448
|
454
|
exit ( 1 );
|
449
|
455
|
}
|
|
@@ -518,8 +524,7 @@ static void process_reloc ( bfd *bfd, asection *section, arelent *rel,
|
518
|
524
|
* remain unaltered when the object is loaded.
|
519
|
525
|
*/
|
520
|
526
|
} else {
|
521
|
|
- fprintf ( stderr, "Unrecognised relocation type %s\n",
|
522
|
|
- howto->name );
|
|
527
|
+ eprintf ( "Unrecognised relocation type %s\n", howto->name );
|
523
|
528
|
exit ( 1 );
|
524
|
529
|
}
|
525
|
530
|
}
|
|
@@ -670,7 +675,7 @@ static void write_pe_file ( struct pe_header *pe_header,
|
670
|
675
|
for ( section = pe_sections ; section ; section = section->next ) {
|
671
|
676
|
if ( fseek ( pe, section->hdr.PointerToRawData,
|
672
|
677
|
SEEK_SET ) != 0 ) {
|
673
|
|
- fprintf ( stderr, "Could not seek to %lx: %s\n",
|
|
678
|
+ eprintf ( "Could not seek to %lx: %s\n",
|
674
|
679
|
section->hdr.PointerToRawData,
|
675
|
680
|
strerror ( errno ) );
|
676
|
681
|
exit ( 1 );
|
|
@@ -678,7 +683,7 @@ static void write_pe_file ( struct pe_header *pe_header,
|
678
|
683
|
if ( section->hdr.SizeOfRawData &&
|
679
|
684
|
( fwrite ( section->contents, section->hdr.SizeOfRawData,
|
680
|
685
|
1, pe ) != 1 ) ) {
|
681
|
|
- fprintf ( stderr, "Could not write section %.8s: %s\n",
|
|
686
|
+ eprintf ( "Could not write section %.8s: %s\n",
|
682
|
687
|
section->hdr.Name, strerror ( errno ) );
|
683
|
688
|
exit ( 1 );
|
684
|
689
|
}
|
|
@@ -691,7 +696,8 @@ static void write_pe_file ( struct pe_header *pe_header,
|
691
|
696
|
* @v elf_name ELF file name
|
692
|
697
|
* @v pe_name PE file name
|
693
|
698
|
*/
|
694
|
|
-static void elf2pe ( const char *elf_name, const char *pe_name ) {
|
|
699
|
+static void elf2pe ( const char *elf_name, const char *pe_name,
|
|
700
|
+ struct options *opts ) {
|
695
|
701
|
bfd *bfd;
|
696
|
702
|
asymbol **symtab;
|
697
|
703
|
asection *section;
|
|
@@ -711,6 +717,7 @@ static void elf2pe ( const char *elf_name, const char *pe_name ) {
|
711
|
717
|
memcpy ( &pe_header, &efi_pe_header, sizeof ( pe_header ) );
|
712
|
718
|
pe_header.nt.OptionalHeader.AddressOfEntryPoint =
|
713
|
719
|
bfd_get_start_address ( bfd );
|
|
720
|
+ pe_header.nt.OptionalHeader.Subsystem = opts->subsystem;
|
714
|
721
|
|
715
|
722
|
/* For each input section, build an output section and create
|
716
|
723
|
* the appropriate relocation records
|
|
@@ -742,7 +749,7 @@ static void elf2pe ( const char *elf_name, const char *pe_name ) {
|
742
|
749
|
/* Write out PE file */
|
743
|
750
|
pe = fopen ( pe_name, "w" );
|
744
|
751
|
if ( ! pe ) {
|
745
|
|
- fprintf ( stderr, "Could not open %s for writing: %s\n",
|
|
752
|
+ eprintf ( "Could not open %s for writing: %s\n",
|
746
|
753
|
pe_name, strerror ( errno ) );
|
747
|
754
|
exit ( 1 );
|
748
|
755
|
}
|
|
@@ -753,12 +760,84 @@ static void elf2pe ( const char *elf_name, const char *pe_name ) {
|
753
|
760
|
bfd_close ( bfd );
|
754
|
761
|
}
|
755
|
762
|
|
|
763
|
+/**
|
|
764
|
+ * Print help
|
|
765
|
+ *
|
|
766
|
+ * @v program_name Program name
|
|
767
|
+ */
|
|
768
|
+static void print_help ( const char *program_name ) {
|
|
769
|
+ eprintf ( "Syntax: %s [--subsystem=<number>] infile outfile\n",
|
|
770
|
+ program_name );
|
|
771
|
+}
|
|
772
|
+
|
|
773
|
+/**
|
|
774
|
+ * Parse command-line options
|
|
775
|
+ *
|
|
776
|
+ * @v argc Argument count
|
|
777
|
+ * @v argv Argument list
|
|
778
|
+ * @v opts Options structure to populate
|
|
779
|
+ */
|
|
780
|
+static int parse_options ( const int argc, char **argv,
|
|
781
|
+ struct options *opts ) {
|
|
782
|
+ char *end;
|
|
783
|
+ int c;
|
|
784
|
+
|
|
785
|
+ while (1) {
|
|
786
|
+ int option_index = 0;
|
|
787
|
+ static struct option long_options[] = {
|
|
788
|
+ { "subsystem", required_argument, NULL, 's' },
|
|
789
|
+ { "help", 0, NULL, 'h' },
|
|
790
|
+ { 0, 0, 0, 0 }
|
|
791
|
+ };
|
|
792
|
+
|
|
793
|
+ if ( ( c = getopt_long ( argc, argv, "s:h",
|
|
794
|
+ long_options,
|
|
795
|
+ &option_index ) ) == -1 ) {
|
|
796
|
+ break;
|
|
797
|
+ }
|
|
798
|
+
|
|
799
|
+ switch ( c ) {
|
|
800
|
+ case 's':
|
|
801
|
+ opts->subsystem = strtoul ( optarg, &end, 0 );
|
|
802
|
+ if ( *end ) {
|
|
803
|
+ eprintf ( "Invalid subsytem \"%s\"\n",
|
|
804
|
+ optarg );
|
|
805
|
+ exit ( 2 );
|
|
806
|
+ }
|
|
807
|
+ break;
|
|
808
|
+ case 'h':
|
|
809
|
+ print_help ( argv[0] );
|
|
810
|
+ exit ( 0 );
|
|
811
|
+ case '?':
|
|
812
|
+ default:
|
|
813
|
+ exit ( 2 );
|
|
814
|
+ }
|
|
815
|
+ }
|
|
816
|
+ return optind;
|
|
817
|
+}
|
|
818
|
+
|
756
|
819
|
int main ( int argc, char **argv ) {
|
|
820
|
+ struct options opts = {
|
|
821
|
+ .subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
|
|
822
|
+ };
|
|
823
|
+ unsigned int infile_index;
|
|
824
|
+ const char *infile;
|
|
825
|
+ const char *outfile;
|
757
|
826
|
|
758
|
827
|
/* Initialise libbfd */
|
759
|
828
|
bfd_init();
|
760
|
829
|
|
761
|
|
- elf2pe ( argv[1], argv[2] );
|
|
830
|
+ /* Parse command-line arguments */
|
|
831
|
+ infile_index = parse_options ( argc, argv, &opts );
|
|
832
|
+ if ( argc != ( infile_index + 2 ) ) {
|
|
833
|
+ print_help ( argv[0] );
|
|
834
|
+ exit ( 2 );
|
|
835
|
+ }
|
|
836
|
+ infile = argv[infile_index];
|
|
837
|
+ outfile = argv[infile_index + 1];
|
|
838
|
+
|
|
839
|
+ /* Convert file */
|
|
840
|
+ elf2pe ( infile, outfile, &opts );
|
762
|
841
|
|
763
|
842
|
return 0;
|
764
|
843
|
}
|