diff options
author | Michael Brown <mcb30@ipxe.org> | 2015-10-19 20:01:19 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2016-05-06 12:08:44 +0100 |
commit | 1a16f67a28c6e8b9875b07e15c7c379cfc147e69 (patch) | |
tree | 4f58c91b43ca8862d8219026c70e89717a514b89 /src/util | |
parent | 49a5bcfba626a8fc01612d0b3f50b56c51529618 (diff) | |
download | ipxe-1a16f67a28c6e8b9875b07e15c7c379cfc147e69.tar.gz |
[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.c | 1 | ||||
-rw-r--r-- | src/util/elf2efi.c | 110 |
2 files changed, 64 insertions, 47 deletions
diff --git a/src/util/efirom.c b/src/util/efirom.c index a982c19ae..72829cbd4 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 5e1050e3d..01ddfd681 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; |