summaryrefslogtreecommitdiffstats
path: root/src/util
diff options
context:
space:
mode:
authorMichael Brown2015-10-19 21:01:19 +0200
committerMichael Brown2016-05-06 13:08:44 +0200
commit1a16f67a28c6e8b9875b07e15c7c379cfc147e69 (patch)
tree4f58c91b43ca8862d8219026c70e89717a514b89 /src/util
parent[bitops] Fix typo in test case (diff)
downloadipxe-1a16f67a28c6e8b9875b07e15c7c379cfc147e69.tar.gz
ipxe-1a16f67a28c6e8b9875b07e15c7c379cfc147e69.tar.xz
ipxe-1a16f67a28c6e8b9875b07e15c7c379cfc147e69.zip
[arm] Add support for 32-bit ARM
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/util')
-rw-r--r--src/util/efirom.c1
-rw-r--r--src/util/elf2efi.c110
2 files changed, 64 insertions, 47 deletions
diff --git a/src/util/efirom.c b/src/util/efirom.c
index a982c19a..72829cbd 100644
--- a/src/util/efirom.c
+++ b/src/util/efirom.c
@@ -81,6 +81,7 @@ static void read_pe_info ( void *pe, uint16_t *machine,
*machine = nt->nt32.FileHeader.Machine;
switch ( *machine ) {
case EFI_IMAGE_MACHINE_IA32:
+ case EFI_IMAGE_MACHINE_ARMTHUMB_MIXED:
*subsystem = nt->nt32.OptionalHeader.Subsystem;
break;
case EFI_IMAGE_MACHINE_X64:
diff --git a/src/util/elf2efi.c b/src/util/elf2efi.c
index 5e1050e3..01ddfd68 100644
--- a/src/util/elf2efi.c
+++ b/src/util/elf2efi.c
@@ -70,20 +70,14 @@
#endif
-#define EFI_FILE_ALIGN 0x20
+#define ELF_MREL( mach, type ) ( (mach) | ( (type) << 16 ) )
-struct elf_machine {
- unsigned int pe_machine;
- unsigned int r_none;
- unsigned int r_abs;
- unsigned int r_pcrel;
-};
+#define EFI_FILE_ALIGN 0x20
struct elf_file {
void *data;
size_t len;
const Elf_Ehdr *ehdr;
- struct elf_machine *machine;
};
struct pe_section {
@@ -136,20 +130,6 @@ static struct pe_header efi_pe_header = {
},
};
-static struct elf_machine machine_i386 = {
- .pe_machine = EFI_IMAGE_MACHINE_IA32,
- .r_none = R_386_NONE,
- .r_abs = R_386_32,
- .r_pcrel = R_386_PC32,
-};
-
-static struct elf_machine machine_x86_64 = {
- .pe_machine = EFI_IMAGE_MACHINE_X64,
- .r_none = R_X86_64_NONE,
- .r_abs = R_X86_64_64,
- .r_pcrel = R_X86_64_PC32,
-};
-
/** Command-line options */
struct options {
unsigned int subsystem;
@@ -355,19 +335,6 @@ static void read_elf_file ( const char *name, struct elf_file *elf ) {
exit ( 1 );
}
}
-
- /* Identify architecture */
- switch ( ehdr->e_machine ) {
- case EM_386:
- elf->machine = &machine_i386;
- break;
- case EM_X86_64:
- elf->machine = &machine_x86_64;
- break;
- default:
- eprintf ( "Unknown ELF architecture %d\n", ehdr->e_machine );
- exit ( 1 );
- }
}
/**
@@ -416,6 +383,36 @@ static const char * elf_string ( struct elf_file *elf, unsigned int section,
}
/**
+ * Set machine architecture
+ *
+ * @v elf ELF file
+ * @v pe_header PE file header
+ */
+static void set_machine ( struct elf_file *elf, struct pe_header *pe_header ) {
+ const Elf_Ehdr *ehdr = elf->ehdr;
+ uint16_t machine;
+
+ /* Identify machine architecture */
+ switch ( ehdr->e_machine ) {
+ case EM_386:
+ machine = EFI_IMAGE_MACHINE_IA32;
+ break;
+ case EM_X86_64:
+ machine = EFI_IMAGE_MACHINE_X64;
+ break;
+ case EM_ARM:
+ machine = EFI_IMAGE_MACHINE_ARMTHUMB_MIXED;
+ break;
+ default:
+ eprintf ( "Unknown ELF architecture %d\n", ehdr->e_machine );
+ exit ( 1 );
+ }
+
+ /* Set machine architecture */
+ pe_header->nt.FileHeader.Machine = machine;
+}
+
+/**
* Process section
*
* @v elf ELF file
@@ -568,6 +565,7 @@ static void process_reloc ( struct elf_file *elf, const Elf_Shdr *shdr,
const Elf_Rel *rel, struct pe_relocs **pe_reltab ) {
unsigned int type = ELF_R_TYPE ( rel->r_info );
unsigned int sym = ELF_R_SYM ( rel->r_info );
+ unsigned int mrel = ELF_MREL ( elf->ehdr->e_machine, type );
size_t offset = ( shdr->sh_addr + rel->r_offset );
/* Look up symbol and process relocation */
@@ -579,18 +577,36 @@ static void process_reloc ( struct elf_file *elf, const Elf_Shdr *shdr,
/* Skip absolute symbols; the symbol value won't
* change when the object is loaded.
*/
- } else if ( type == elf->machine->r_none ) {
- /* Ignore dummy relocations used by REQUIRE_SYMBOL() */
- } else if ( type == elf->machine->r_abs ) {
- /* Generate an 8-byte or 4-byte PE relocation */
- generate_pe_reloc ( pe_reltab, offset, sizeof ( Elf_Addr ) );
- } else if ( type == elf->machine->r_pcrel ) {
- /* Skip PC-relative relocations; all relative offsets
- * remain unaltered when the object is loaded.
- */
} else {
- eprintf ( "Unrecognised relocation type %d\n", type );
- exit ( 1 );
+ switch ( mrel ) {
+ case ELF_MREL ( EM_386, R_386_NONE ) :
+ case ELF_MREL ( EM_ARM, R_ARM_NONE ) :
+ case ELF_MREL ( EM_X86_64, R_X86_64_NONE ) :
+ /* Ignore dummy relocations used by REQUIRE_SYMBOL() */
+ break;
+ case ELF_MREL ( EM_386, R_386_32 ) :
+ case ELF_MREL ( EM_ARM, R_ARM_ABS32 ) :
+ /* Generate a 4-byte PE relocation */
+ generate_pe_reloc ( pe_reltab, offset, 4 );
+ break;
+ case ELF_MREL ( EM_X86_64, R_X86_64_64 ) :
+ /* Generate an 8-byte PE relocation */
+ generate_pe_reloc ( pe_reltab, offset, 8 );
+ break;
+ case ELF_MREL ( EM_386, R_386_PC32 ) :
+ case ELF_MREL ( EM_ARM, R_ARM_CALL ) :
+ case ELF_MREL ( EM_ARM, R_ARM_THM_PC22 ) :
+ case ELF_MREL ( EM_ARM, R_ARM_THM_JUMP24 ) :
+ case ELF_MREL ( EM_X86_64, R_X86_64_PC32 ) :
+ /* Skip PC-relative relocations; all relative
+ * offsets remain unaltered when the object is
+ * loaded.
+ */
+ break;
+ default:
+ eprintf ( "Unrecognised relocation type %d\n", type );
+ exit ( 1 );
+ }
}
}
@@ -835,7 +851,7 @@ static void elf2pe ( const char *elf_name, const char *pe_name,
/* Initialise the PE header */
memcpy ( &pe_header, &efi_pe_header, sizeof ( pe_header ) );
- pe_header.nt.FileHeader.Machine = elf.machine->pe_machine;
+ set_machine ( &elf, &pe_header );
pe_header.nt.OptionalHeader.AddressOfEntryPoint = elf.ehdr->e_entry;
pe_header.nt.OptionalHeader.Subsystem = opts->subsystem;