aboutsummaryrefslogtreecommitdiff
path: root/meta-aarch64
diff options
context:
space:
mode:
authorFathi Boudra <fathi.boudra@linaro.org>2014-05-10 14:05:32 +0300
committerFathi Boudra <fathi.boudra@linaro.org>2014-05-10 14:05:32 +0300
commitb17339cbfcbb5bfa41ad83aec0c9f19708e53e82 (patch)
tree67db8f68b1b14a559c3efcbbf70b638e36f17c4f /meta-aarch64
parentc05814dcdf5c08625198b03c8e2861ecff0c8072 (diff)
kexec-tools: add arm64 support
Change-Id: Ica930ad9d8b15c3fb1f16fdcab2aa943dd60fe30 Signed-off-by: Fathi Boudra <fathi.boudra@linaro.org>
Diffstat (limited to 'meta-aarch64')
-rw-r--r--meta-aarch64/recipes-kernel/kexec-tools/files/add-arm64-support.patch578
-rw-r--r--meta-aarch64/recipes-kernel/kexec-tools/kexec-tools_2.0.6.bbappend5
2 files changed, 583 insertions, 0 deletions
diff --git a/meta-aarch64/recipes-kernel/kexec-tools/files/add-arm64-support.patch b/meta-aarch64/recipes-kernel/kexec-tools/files/add-arm64-support.patch
new file mode 100644
index 00000000..61e5aaac
--- /dev/null
+++ b/meta-aarch64/recipes-kernel/kexec-tools/files/add-arm64-support.patch
@@ -0,0 +1,578 @@
+From 3d285550c826be5932807857b21b22d8296a8b4a Mon Sep 17 00:00:00 2001
+From: Geoff Levand <geoff@infradead.org>
+Date: Fri, 9 May 2014 13:45:10 -0700
+Subject: [PATCH 1/1] Add arm64 support
+
+Signed-off-by: Geoff Levand <geoff@infradead.org>
+---
+ configure.ac | 3 +
+ kexec/Makefile | 1 +
+ kexec/arch/arm64/Makefile | 31 +++++
+ kexec/arch/arm64/include/arch/options.h | 30 +++++
+ kexec/arch/arm64/kexec-arm64.c | 228 ++++++++++++++++++++++++++++++++
+ kexec/arch/arm64/kexec-arm64.h | 28 ++++
+ kexec/arch/arm64/kexec-elf-arm64.c | 147 ++++++++++++++++++++
+ kexec/kexec-syscall.h | 9 +-
+ 8 files changed, 475 insertions(+), 2 deletions(-)
+ create mode 100644 kexec/arch/arm64/Makefile
+ create mode 100644 kexec/arch/arm64/include/arch/options.h
+ create mode 100644 kexec/arch/arm64/kexec-arm64.c
+ create mode 100644 kexec/arch/arm64/kexec-arm64.h
+ create mode 100644 kexec/arch/arm64/kexec-elf-arm64.c
+
+diff --git a/configure.ac b/configure.ac
+index 31d1bbe..c6e8bd6 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -35,6 +35,9 @@ case $target_cpu in
+ ARCH="ppc64"
+ SUBARCH="LE"
+ ;;
++ aarch64 )
++ ARCH="arm64"
++ ;;
+ arm* )
+ ARCH="arm"
+ ;;
+diff --git a/kexec/Makefile b/kexec/Makefile
+index 7d3175b..9777ec3 100644
+--- a/kexec/Makefile
++++ b/kexec/Makefile
+@@ -71,6 +71,7 @@ KEXEC_SRCS += $($(ARCH)_FS2DT)
+
+ include $(srcdir)/kexec/arch/alpha/Makefile
+ include $(srcdir)/kexec/arch/arm/Makefile
++include $(srcdir)/kexec/arch/arm64/Makefile
+ include $(srcdir)/kexec/arch/i386/Makefile
+ include $(srcdir)/kexec/arch/ia64/Makefile
+ include $(srcdir)/kexec/arch/m68k/Makefile
+diff --git a/kexec/arch/arm64/Makefile b/kexec/arch/arm64/Makefile
+new file mode 100644
+index 0000000..6c6a8e9
+--- /dev/null
++++ b/kexec/arch/arm64/Makefile
+@@ -0,0 +1,31 @@
++
++arm64_FS2DT += kexec/fs2dt.c
++arm64_FS2DT_INCLUDE += -include $(srcdir)/kexec/arch/arm64/kexec-arm64.h
++
++arm64_KEXEC_SRCS += \
++ kexec/arch/arm64/kexec-arm64.c \
++ kexec/arch/arm64/kexec-elf-arm64.c
++
++arm64_ARCH_REUSE_INITRD =
++arm64_ADD_SEGMENT =
++arm64_VIRT_TO_PHYS =
++
++dist += $(arm64_KEXEC_SRCS) \
++ kexec/arch/arm64/Makefile \
++ kexec/arch/arm64/kexec-arm64.h
++
++ifdef HAVE_LIBFDT
++
++LIBS += -lfdt
++
++else
++
++include $(srcdir)/kexec/libfdt/Makefile.libfdt
++
++libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%)
++
++arm64_CPPFLAGS = -I$(srcdir)/kexec/libfdt
++
++arm64_KEXEC_SRCS += $(libfdt_SRCS)
++
++endif
+diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h
+new file mode 100644
+index 0000000..c9a0287
+--- /dev/null
++++ b/kexec/arch/arm64/include/arch/options.h
+@@ -0,0 +1,30 @@
++#ifndef KEXEC_ARCH_ARM64_OPTIONS_H
++#define KEXEC_ARCH_ARM64_OPTIONS_H
++
++#define OPT_APPEND ((OPT_MAX)+0)
++#define OPT_RAMDISK ((OPT_MAX)+1)
++#define OPT_DTB ((OPT_MAX)+2)
++#define OPT_ARCH_MAX ((OPT_MAX)+3)
++
++#define KEXEC_ARCH_OPTIONS \
++ KEXEC_OPTIONS \
++ { "append", 1, NULL, OPT_APPEND }, \
++ { "command-line", 1, NULL, OPT_APPEND }, \
++ { "dtb", 1, NULL, OPT_DTB }, \
++ { "initrd", 1, NULL, OPT_RAMDISK }, \
++ { "ramdisk", 1, NULL, OPT_RAMDISK }, \
++
++#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */
++
++#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS
++#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
++
++struct arm64_opts {
++ const char *command_line;
++ const char *ramdisk;
++ const char *dtb;
++};
++
++struct arm64_opts arm64_opts;
++
++#endif /* KEXEC_ARCH_ARM64_OPTIONS_H */
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+new file mode 100644
+index 0000000..e02c38d
+--- /dev/null
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -0,0 +1,228 @@
++/*
++ * ARM64 kexec support.
++ */
++
++#define _GNU_SOURCE
++
++#include <errno.h>
++#include <getopt.h>
++#include <stddef.h>
++
++//#include <linux/kexec.h>
++
++#include "../../kexec.h"
++#include "../../kexec-syscall.h"
++#include "kexec-arm64.h"
++#include "arch/options.h"
++
++/* Global varables the core kexec routines expect. */
++
++unsigned char reuse_initrd;
++off_t initrd_base = 0;
++off_t initrd_size = 0;
++
++struct memory_ranges usablemem_rgns = {
++};
++
++const struct arch_map_entry arches[] = {
++ { "aarch64", KEXEC_ARCH_ARM64 },
++ { NULL, 0 },
++};
++
++/* arm64 global varables. */
++
++struct arm64_opts arm64_opts;
++
++void arch_usage(void)
++{
++ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
++
++ printf(
++" --append=STRING Set the kernel command line to STRING.\n"
++" --command-line=STRING Set the kernel command line to STRING.\n"
++" --dtb=FILE Use FILE as the device tree blob.\n"
++" --initrd=FILE Use FILE as the kernel initial ramdisk.\n"
++" --ramdisk=FILE Use FILE as the kernel initial ramdisk.\n");
++
++ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
++}
++
++int arch_process_options(int argc, char **argv)
++{
++ static const char short_options[] = KEXEC_OPT_STR "";
++ static const struct option options[] = {
++ KEXEC_ARCH_OPTIONS
++ { 0 }
++ };
++ int opt;
++
++ for (opt = 0; opt != -1; ) {
++ opt = getopt_long(argc, argv, short_options, options, 0);
++
++ switch (opt) {
++ case OPT_APPEND:
++ arm64_opts.command_line = optarg;
++ break;
++ case OPT_RAMDISK:
++ arm64_opts.ramdisk = optarg;
++ break;
++ case OPT_DTB:
++ arm64_opts.dtb = optarg;
++ break;
++ default:
++ break; /* Ignore core and unknown options */
++ }
++ }
++
++ dbgprintf("%s:%d: command_line: %s\n", __func__, __LINE__,
++ arm64_opts.command_line);
++ dbgprintf("%s:%d: ramdisk: %s\n", __func__, __LINE__,
++ arm64_opts.ramdisk);
++ dbgprintf("%s:%d: dtb: %s\n", __func__, __LINE__, arm64_opts.dtb);
++
++ return 0;
++}
++
++int is_crashkernel_mem_reserved(void)
++{
++ return 0; /* TODO: kdump not implemented yet. */
++}
++
++void arch_reuse_initrd(void)
++{
++ reuse_initrd = 1;
++}
++
++void arch_update_purgatory(struct kexec_info *UNUSED(info))
++{
++ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__);
++}
++
++unsigned long virt_to_phys(unsigned long addr)
++{
++ fprintf(stderr, "%s:%d: %016lx -> %016lx\n", __func__, __LINE__, addr,
++ addr + 0x080000000UL);
++ return addr + 0x080000000UL;
++}
++
++void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
++ unsigned long base, size_t memsz)
++{
++ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
++ add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
++ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
++}
++
++static int get_memory_ranges_1(struct memory_range **range, int *ranges,
++ unsigned long kexec_flags)
++{
++ static struct memory_range memory_range[KEXEC_SEGMENT_MAX];
++ const char *iomem;
++ int range_count = 0;
++ char line[MAX_LINE];
++ FILE *fp;
++
++ iomem = proc_iomem();
++ fp = fopen(iomem, "r");
++
++ if (!fp) {
++ fprintf(stderr, "Cannot open %s: %s\n",
++ iomem, strerror(errno));
++ return -1;
++ }
++
++ dbgprintf("memory ranges:\n");
++
++ while(fgets(line, sizeof(line), fp) != 0) {
++ struct memory_range r;
++ char *str;
++ int consumed;
++
++ if (range_count >= KEXEC_SEGMENT_MAX)
++ break;
++
++ if (sscanf(line, "%Lx-%Lx : %n", &r.start, &r.end, &consumed)
++ != 2)
++ continue;
++
++ str = line + consumed;
++ r.end++;
++
++ if (memcmp(str, "System RAM\n", 11)) {
++ dbgprintf(" Skip: %016Lx - %016Lx : %s", r.start, r.end,
++ str);
++ continue;
++ }
++
++ r.type = RANGE_RAM;
++ memory_range[range_count] = r;
++ range_count++;
++
++ dbgprintf(" Add: %016Lx - %016Lx : %s", r.start, r.end, str);
++ }
++
++ fclose(fp);
++ *range = memory_range;
++ *ranges = range_count;
++
++ return 0;
++}
++
++static int get_memory_ranges_2(struct memory_range **range, int *ranges,
++ unsigned long UNUSED(kexec_flags))
++{
++ static struct memory_range memory_range[2];
++
++ memory_range[0].start = 0x080000000;
++ memory_range[0].end = 0x100000000;
++ memory_range[0].type = RANGE_RAM;
++
++ memory_range[1].start = 0x900000000;
++ memory_range[1].end = 0x880000000;
++ memory_range[1].type = RANGE_RAM;
++
++ *range = memory_range;
++ *ranges = sizeof(memory_range) / sizeof(memory_range[0]);
++
++ return 0;
++}
++
++int get_memory_ranges(struct memory_range **range, int *ranges,
++ unsigned long kexec_flags)
++{
++ /* FIXME: Should get this info from device tree. */
++
++ return get_memory_ranges_1(range, ranges, kexec_flags);
++}
++
++struct file_type file_type[] = {
++ { "elf-arm64", elf_arm64_probe, elf_arm64_load, elf_arm64_usage },
++};
++
++int file_types = sizeof(file_type) / sizeof(file_type[0]);
++
++int arch_compat_trampoline(struct kexec_info *info)
++{
++ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__);
++ return 0;
++}
++
++
++int machine_verify_elf_rel(struct mem_ehdr *ehdr)
++{
++ (void)ehdr;
++
++ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__);
++ return 0;
++}
++
++void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
++ void *location, unsigned long address, unsigned long value)
++{
++ (void)ehdr;
++ (void)r_type;
++ (void)location;
++ (void)address;
++ (void)value;
++ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__);
++}
+diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
+new file mode 100644
+index 0000000..673d525
+--- /dev/null
++++ b/kexec/arch/arm64/kexec-arm64.h
+@@ -0,0 +1,28 @@
++/*
++ * ARM64 kexec support.
++ */
++
++#if !defined(KEXEC_ARM64_H)
++#define KEXEC_ARM64_H
++
++/* #include <linux/kexec.h> FIXME: this is broken */
++#include <sys/types.h>
++
++#include "../../kexec.h"
++
++#define KEXEC_SEGMENT_MAX 16 /* FIXME: this should come from <linux/kexec.h> */
++
++#define BOOT_BLOCK_VERSION 17
++#define BOOT_BLOCK_LAST_COMP_VERSION 16
++#define COMMAND_LINE_SIZE 512
++
++int elf_arm64_probe(const char *buf, off_t len);
++int elf_arm64_load(int argc, char **argv, const char *buf, off_t len,
++ struct kexec_info *info);
++void elf_arm64_usage(void);
++
++struct memory_ranges usablemem_rgns;
++off_t initrd_base;
++off_t initrd_size;
++
++#endif
+diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
+new file mode 100644
+index 0000000..b267a15
+--- /dev/null
++++ b/kexec/arch/arm64/kexec-elf-arm64.c
+@@ -0,0 +1,147 @@
++/*
++ * ARM64 kexec support.
++ */
++
++#define _GNU_SOURCE
++
++#include <elf.h>
++#include <getopt.h>
++#include <libfdt.h>
++
++#include "kexec-arm64.h"
++
++#include "../../kexec-syscall.h"
++#include "../../fs2dt.h"
++
++#include "arch/options.h"
++
++#if !defined(EM_AARCH64)
++# define EM_AARCH64 183
++#endif
++
++int elf_arm64_probe(const char *buf, off_t len)
++{
++ int result;
++ struct mem_ehdr ehdr;
++
++ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
++
++ result = build_elf_exec_info(buf, len, &ehdr, 0);
++
++ if (result < 0) {
++ dbgprintf("Not an ELF executable\n");
++ goto out;
++ }
++
++ if (ehdr.e_machine != EM_AARCH64) {
++ dbgprintf("Not an AARCH64 executable\n");
++ result = -1;
++ goto out;
++ }
++
++ result = 0;
++
++out:
++ free_elf_info(&ehdr);
++ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
++ return result;
++}
++
++static off_t round_up(off_t v)
++{
++ return _ALIGN_DOWN(v + getpagesize(), getpagesize());
++}
++
++int elf_arm64_load(int argc, char **argv, const char *buf, off_t len,
++ struct kexec_info *info)
++{
++ char *dtb_buf;
++ off_t dtb_base;
++ off_t dtb_size;
++ struct mem_ehdr ehdr;
++ int result;
++ //unsigned int command_line_len = strlen(arm64_opts.command_line) + 1;
++
++ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
++
++ if (info->kexec_flags & KEXEC_ON_CRASH) {
++ fprintf(stderr, "kexec: kdump not yet supported on arm64\n");
++ return -1;
++ }
++
++ result = build_elf_exec_info(buf, len, &ehdr, 0);
++
++ if (result < 0) {
++ free_elf_info(&ehdr);
++ fprintf(stderr, "%s:%d: build_elf_exec_info failed\n", __func__,
++ __LINE__);
++ return result;
++ }
++
++ elf_exec_build_load(info, &ehdr, buf, len, 0);
++
++ info->entry = (void*)0x80080000UL; // FIXME
++
++ initrd_base = 0;
++ initrd_size = 0;
++
++ if (arm64_opts.ramdisk) {
++ char *buf;
++
++ buf = slurp_file(arm64_opts.ramdisk, &initrd_size);
++
++ if (!buf)
++ fprintf(stderr, "kexec: empty ramdisk file\n");
++ else {
++ initrd_base = locate_hole(info, initrd_size, 0, 0, -1, -1);
++
++ add_segment_phys_virt(info, buf, initrd_size, initrd_base,
++ initrd_size, 0);
++ }
++ }
++
++ fprintf(stderr, "%s:%d: initrd_base: %lx, initrd_size: %lx\n", __func__,
++ __LINE__, (unsigned long)initrd_base, (unsigned long)initrd_size);
++
++ if (arm64_opts.dtb)
++ dtb_buf = slurp_file(arm64_opts.dtb, &dtb_size);
++ else
++ create_flatten_tree(&dtb_buf, &dtb_size,
++ arm64_opts.command_line);
++
++ fprintf(stderr, "%s:%d: dt magic: %x : %x\n", __func__, __LINE__,
++ fdt32_to_cpu(*(uint32_t*)dtb_buf), *(uint32_t*)dtb_buf);
++
++ result = fdt_check_header(dtb_buf);
++
++ if (result) {
++ fprintf(stderr, "Invalid FDT.\n");
++ return -1;
++ }
++
++ if (arm64_opts.command_line) {
++ // FIXME: need to handle command line...
++ fprintf(stderr, "%s:%d: command line support TODO\n", __func__, __LINE__);
++ }
++
++if (1) {
++ dtb_base = (unsigned long)info->entry + round_up(0xA43FA0); // computed kernel mem size.
++
++ fprintf(stderr, "%s:%d: dtb_base: %lx, dtb_size: %lx\n", __func__,
++ __LINE__, (unsigned long)dtb_base, (unsigned long)dtb_size);
++} else {
++ dtb_base = locate_hole(info, dtb_size, 0, 0, -1, -1);
++
++ fprintf(stderr, "%s:%d: dtb_base: %lx, dtb_size: %lx\n", __func__,
++ __LINE__, (unsigned long)dtb_base, (unsigned long)dtb_size);
++}
++ add_segment_phys_virt(info, dtb_buf, dtb_size, dtb_base, dtb_size, 0);
++
++ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
++ return 0;
++}
++
++void elf_arm64_usage(void)
++{
++ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
++}
+diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
+index 6238044..ccca19c 100644
+--- a/kexec/kexec-syscall.h
++++ b/kexec/kexec-syscall.h
+@@ -39,8 +39,8 @@
+ #ifdef __s390__
+ #define __NR_kexec_load 277
+ #endif
+-#ifdef __arm__
+-#define __NR_kexec_load __NR_SYSCALL_BASE + 347
++#if defined(__arm__) || defined(__arm64__)
++#define __NR_kexec_load __NR_SYSCALL_BASE + 347
+ #endif
+ #if defined(__mips__)
+ #define __NR_kexec_load 4311
+@@ -76,6 +76,8 @@ static inline long kexec_load(void *entry, unsigned long nr_segments,
+ #define KEXEC_ARCH_PPC64 (21 << 16)
+ #define KEXEC_ARCH_IA_64 (50 << 16)
+ #define KEXEC_ARCH_ARM (40 << 16)
++#define KEXEC_ARCH_ARM64 (183 << 16)
++/* #define KEXEC_ARCH_AARCH64 (183 << 16) */
+ #define KEXEC_ARCH_S390 (22 << 16)
+ #define KEXEC_ARCH_SH (42 << 16)
+ #define KEXEC_ARCH_MIPS_LE (10 << 16)
+@@ -121,5 +123,8 @@ static inline long kexec_load(void *entry, unsigned long nr_segments,
+ #ifdef __m68k__
+ #define KEXEC_ARCH_NATIVE KEXEC_ARCH_68K
+ #endif
++#if defined(__arm64__)
++#define KEXEC_ARCH_NATIVE KEXEC_ARCH_ARM64
++#endif
+
+ #endif /* KEXEC_SYSCALL_H */
+--
+1.9.3
+
diff --git a/meta-aarch64/recipes-kernel/kexec-tools/kexec-tools_2.0.6.bbappend b/meta-aarch64/recipes-kernel/kexec-tools/kexec-tools_2.0.6.bbappend
new file mode 100644
index 00000000..6417ffa3
--- /dev/null
+++ b/meta-aarch64/recipes-kernel/kexec-tools/kexec-tools_2.0.6.bbappend
@@ -0,0 +1,5 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI_append = " file://add-arm64-support.patch"
+
+COMPATIBLE_HOST = "(x86_64|i.86|arm|aarch64|powerpc|mips).*-(linux|freebsd.*)"