Unlike MIPS and kvx, where ELF is used as kernel image format, Linux ARM support defines its own flattened format. Other kernels may be distributed as ELF images though, so it makes sense to enable booting of ELF images on ARM as well. This has been tested booting FreeRTOS ELF executables on the ZynqMP. Note that this will refuse to boot kernel ELF images as those have type dyn, while the common ELF code in barebox will only boot type exec. Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- arch/arm/cpu/Makefile | 1 + arch/arm/cpu/bootm-elf.c | 56 ++++++++++++++++++++++++++++++++++++++ arch/arm/include/asm/elf.h | 5 ++++ include/elf.h | 1 + 4 files changed, 63 insertions(+) create mode 100644 arch/arm/cpu/bootm-elf.c diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile index 5baff2fad087..28161cd7d714 100644 --- a/arch/arm/cpu/Makefile +++ b/arch/arm/cpu/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_ARM_PSCI_CLIENT) += psci-client.o obj-$(CONFIG_CMD_ARM_CPUINFO) += cpuinfo.o obj-$(CONFIG_MMUINFO) += mmuinfo.o mmuinfo_$(S64_32).o obj-$(CONFIG_OFDEVICE) += dtb.o +obj-$(CONFIG_BOOTM_ELF) += bootm-elf.o ifeq ($(CONFIG_MMU),) obj-$(CONFIG_CPU_32v7) += no-mmu.o diff --git a/arch/arm/cpu/bootm-elf.c b/arch/arm/cpu/bootm-elf.c new file mode 100644 index 000000000000..bcca3931f22f --- /dev/null +++ b/arch/arm/cpu/bootm-elf.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define pr_fmt(fmt) "ELF: " fmt + +#include <bootm.h> +#include <elf.h> +#include <common.h> +#include <init.h> +#include <errno.h> + +static int do_bootm_elf(struct image_data *data) +{ + void (*fn)(unsigned long x0, unsigned long x1, unsigned long x2, + unsigned long x3); + struct elf_image *elf = data->elf; + int ret; + + if (elf_hdr_e_machine(elf, elf->hdr_buf) != ELF_ARCH) { + pr_err("Unsupported machine: 0x%02x, but 0x%02x expected\n", + elf_hdr_e_machine(elf, elf->hdr_buf), ELF_ARCH); + + return -EINVAL; + } + + ret = bootm_load_os(data, data->os_address); + if (ret) + return ret; + + if (data->dryrun) + return ret; + + ret = of_overlay_load_firmware(); + if (ret) + return ret; + + shutdown_barebox(); + + fn = (void *) (unsigned long) data->os_address; + + fn(0, 0, 0, 0); + + pr_err("ELF application terminated\n"); + return -EINVAL; +} + +static struct image_handler elf_handler = { + .name = "ELF", + .bootm = do_bootm_elf, + .filetype = filetype_elf, +}; + +static int arm_register_elf_image_handler(void) +{ + return register_image_handler(&elf_handler); +} +late_initcall(arm_register_elf_image_handler); diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h index 486275a3361d..4043e6fd5b99 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -22,6 +22,7 @@ typedef struct user_fp elf_fpregset_t; #endif #define EM_ARM 40 +#define EM_AARCH64 183 #define EF_ARM_APCS26 0x08 #define EF_ARM_SOFT_FLOAT 0x200 #define EF_ARM_EABI_MASK 0xFF000000 @@ -44,7 +45,11 @@ typedef struct user_fp elf_fpregset_t; #else #define ELF_DATA ELFDATA2LSB #endif +#ifdef CONFIG_CPU_64 +#define ELF_ARCH EM_AARCH64 +#else #define ELF_ARCH EM_ARM +#endif #ifdef __KERNEL__ #ifndef __ASSEMBLY__ diff --git a/include/elf.h b/include/elf.h index 12673e93ed0d..de1549ee8620 100644 --- a/include/elf.h +++ b/include/elf.h @@ -432,6 +432,7 @@ ELF_GET_FIELD(hdr, e_phnum, u16) ELF_GET_FIELD(hdr, e_phoff, u64) ELF_GET_FIELD(hdr, e_phentsize, u16) ELF_GET_FIELD(hdr, e_type, u16) +ELF_GET_FIELD(hdr, e_machine, u16) ELF_GET_FIELD(phdr, p_paddr, u64) ELF_GET_FIELD(phdr, p_filesz, u64) ELF_GET_FIELD(phdr, p_memsz, u64) -- 2.39.2