[PATCH 2/3] ARM: add support for booting ELF executables

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux