summaryrefslogtreecommitdiffstats
path: root/meta-aarch64/recipes-kernel/kexec-tools/files/add-arm64-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-aarch64/recipes-kernel/kexec-tools/files/add-arm64-support.patch')
-rw-r--r--meta-aarch64/recipes-kernel/kexec-tools/files/add-arm64-support.patch521
1 files changed, 521 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 0000000..30b0229
--- /dev/null
+++ b/meta-aarch64/recipes-kernel/kexec-tools/files/add-arm64-support.patch
@@ -0,0 +1,521 @@
1From 98215763db92c85668fd217cfc719322ce54e704 Mon Sep 17 00:00:00 2001
2From: Geoff Levand <geoff.levand@linaro.org>
3Date: Tue, 13 May 2014 10:59:52 -0700
4Subject: [PATCH 1/1] Add arm64 support
5
6Signed-off-by: Geoff Levand <geoff.levand@linaro.org>
7Signed-off-by: Fathi Boudra <fathi.boudra@linaro.org>
8---
9 configure.ac | 3
10 kexec/Makefile | 1
11 kexec/arch/arm64/Makefile | 31 +++++
12 kexec/arch/arm64/include/arch/options.h | 30 ++++
13 kexec/arch/arm64/kexec-arm64.c | 194 ++++++++++++++++++++++++++++++++
14 kexec/arch/arm64/kexec-arm64.h | 28 ++++
15 kexec/arch/arm64/kexec-elf-arm64.c | 147 ++++++++++++++++++++++++
16 kexec/kexec-syscall.h | 9 +
17 8 files changed, 441 insertions(+), 2 deletions(-)
18 create mode 100644 kexec/arch/arm64/Makefile
19 create mode 100644 kexec/arch/arm64/include/arch/options.h
20 create mode 100644 kexec/arch/arm64/kexec-arm64.c
21 create mode 100644 kexec/arch/arm64/kexec-arm64.h
22 create mode 100644 kexec/arch/arm64/kexec-elf-arm64.c
23
24--- a/configure.ac
25+++ b/configure.ac
26@@ -35,6 +35,9 @@ case $target_cpu in
27 ARCH="ppc64"
28 SUBARCH="LE"
29 ;;
30+ aarch64* )
31+ ARCH="arm64"
32+ ;;
33 arm* )
34 ARCH="arm"
35 ;;
36--- a/kexec/Makefile
37+++ b/kexec/Makefile
38@@ -71,6 +71,7 @@ KEXEC_SRCS += $($(ARCH)_FS2DT)
39
40 include $(srcdir)/kexec/arch/alpha/Makefile
41 include $(srcdir)/kexec/arch/arm/Makefile
42+include $(srcdir)/kexec/arch/arm64/Makefile
43 include $(srcdir)/kexec/arch/i386/Makefile
44 include $(srcdir)/kexec/arch/ia64/Makefile
45 include $(srcdir)/kexec/arch/m68k/Makefile
46--- /dev/null
47+++ b/kexec/arch/arm64/Makefile
48@@ -0,0 +1,31 @@
49+
50+arm64_FS2DT += kexec/fs2dt.c
51+arm64_FS2DT_INCLUDE += -include $(srcdir)/kexec/arch/arm64/kexec-arm64.h
52+
53+arm64_KEXEC_SRCS += \
54+ kexec/arch/arm64/kexec-arm64.c \
55+ kexec/arch/arm64/kexec-elf-arm64.c
56+
57+arm64_ARCH_REUSE_INITRD =
58+arm64_ADD_SEGMENT =
59+arm64_VIRT_TO_PHYS =
60+
61+dist += $(arm64_KEXEC_SRCS) \
62+ kexec/arch/arm64/Makefile \
63+ kexec/arch/arm64/kexec-arm64.h
64+
65+ifdef HAVE_LIBFDT
66+
67+LIBS += -lfdt
68+
69+else
70+
71+include $(srcdir)/kexec/libfdt/Makefile.libfdt
72+
73+libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%)
74+
75+arm64_CPPFLAGS = -I$(srcdir)/kexec/libfdt
76+
77+arm64_KEXEC_SRCS += $(libfdt_SRCS)
78+
79+endif
80--- /dev/null
81+++ b/kexec/arch/arm64/include/arch/options.h
82@@ -0,0 +1,30 @@
83+#ifndef KEXEC_ARCH_ARM64_OPTIONS_H
84+#define KEXEC_ARCH_ARM64_OPTIONS_H
85+
86+#define OPT_APPEND ((OPT_MAX)+0)
87+#define OPT_RAMDISK ((OPT_MAX)+1)
88+#define OPT_DTB ((OPT_MAX)+2)
89+#define OPT_ARCH_MAX ((OPT_MAX)+3)
90+
91+#define KEXEC_ARCH_OPTIONS \
92+ KEXEC_OPTIONS \
93+ { "append", 1, NULL, OPT_APPEND }, \
94+ { "command-line", 1, NULL, OPT_APPEND }, \
95+ { "dtb", 1, NULL, OPT_DTB }, \
96+ { "initrd", 1, NULL, OPT_RAMDISK }, \
97+ { "ramdisk", 1, NULL, OPT_RAMDISK }, \
98+
99+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */
100+
101+#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS
102+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
103+
104+struct arm64_opts {
105+ const char *command_line;
106+ const char *ramdisk;
107+ const char *dtb;
108+};
109+
110+struct arm64_opts arm64_opts;
111+
112+#endif /* KEXEC_ARCH_ARM64_OPTIONS_H */
113--- /dev/null
114+++ b/kexec/arch/arm64/kexec-arm64.c
115@@ -0,0 +1,194 @@
116+/*
117+ * ARM64 kexec support.
118+ */
119+
120+#define _GNU_SOURCE
121+
122+#include <dirent.h>
123+#include <errno.h>
124+#include <getopt.h>
125+#include <stdio.h>
126+#include <stddef.h>
127+
128+//#include <linux/kexec.h>
129+
130+#include "../../kexec.h"
131+#include "../../kexec-syscall.h"
132+#include "kexec-arm64.h"
133+#include "arch/options.h"
134+
135+/* Global varables the core kexec routines expect. */
136+
137+unsigned char reuse_initrd;
138+off_t initrd_base = 0;
139+off_t initrd_size = 0;
140+
141+struct memory_ranges usablemem_rgns = {
142+};
143+
144+const struct arch_map_entry arches[] = {
145+ { "aarch64", KEXEC_ARCH_ARM64 },
146+ { NULL, 0 },
147+};
148+
149+/* arm64 global varables. */
150+
151+struct arm64_opts arm64_opts;
152+
153+void arch_usage(void)
154+{
155+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
156+
157+ printf(
158+" --append=STRING Set the kernel command line to STRING.\n"
159+" --command-line=STRING Set the kernel command line to STRING.\n"
160+" --dtb=FILE Use FILE as the device tree blob.\n"
161+" --initrd=FILE Use FILE as the kernel initial ramdisk.\n"
162+" --ramdisk=FILE Use FILE as the kernel initial ramdisk.\n");
163+
164+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
165+}
166+
167+int arch_process_options(int argc, char **argv)
168+{
169+ static const char short_options[] = KEXEC_OPT_STR "";
170+ static const struct option options[] = {
171+ KEXEC_ARCH_OPTIONS
172+ { 0 }
173+ };
174+ int opt;
175+
176+ for (opt = 0; opt != -1; ) {
177+ opt = getopt_long(argc, argv, short_options, options, 0);
178+
179+ switch (opt) {
180+ case OPT_APPEND:
181+ arm64_opts.command_line = optarg;
182+ break;
183+ case OPT_RAMDISK:
184+ arm64_opts.ramdisk = optarg;
185+ break;
186+ case OPT_DTB:
187+ arm64_opts.dtb = optarg;
188+ break;
189+ default:
190+ break; /* Ignore core and unknown options */
191+ }
192+ }
193+
194+ dbgprintf("%s:%d: command_line: %s\n", __func__, __LINE__,
195+ arm64_opts.command_line);
196+ dbgprintf("%s:%d: ramdisk: %s\n", __func__, __LINE__,
197+ arm64_opts.ramdisk);
198+ dbgprintf("%s:%d: dtb: %s\n", __func__, __LINE__, arm64_opts.dtb);
199+
200+ return 0;
201+}
202+
203+void arch_reuse_initrd(void)
204+{
205+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
206+ reuse_initrd = 1;
207+}
208+
209+unsigned long virt_to_phys(unsigned long v)
210+{
211+ const unsigned long memstart_addr = 0x080000000UL; // FIXME: get from memory_range/DT
212+ const unsigned long page_offset = 0xffffffc000000000UL; // FIXME: from where???
213+ unsigned long p = (v & ~page_offset) + memstart_addr;
214+
215+ fprintf(stderr, "%s:%d: %016lx -> %016lx\n", __func__, __LINE__, v, p);
216+ return p;
217+}
218+
219+void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
220+ unsigned long base, size_t memsz)
221+{
222+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
223+ add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
224+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
225+}
226+
227+int get_memory_ranges(struct memory_range **range, int *ranges,
228+ unsigned long kexec_flags)
229+{
230+ /* FIXME: Should get this info from device tree. */
231+ static struct memory_range memory_range[KEXEC_SEGMENT_MAX];
232+ const char *iomem;
233+ int range_count = 0;
234+ char line[MAX_LINE];
235+ FILE *fp;
236+
237+ iomem = proc_iomem();
238+ fp = fopen(iomem, "r");
239+
240+ if (!fp) {
241+ fprintf(stderr, "Cannot open %s: %s\n", iomem, strerror(errno));
242+ return -1;
243+ }
244+
245+ dbgprintf("memory ranges:\n");
246+
247+ while(fgets(line, sizeof(line), fp) != 0) {
248+ struct memory_range r;
249+ char *str;
250+ int consumed;
251+
252+ if (range_count >= KEXEC_SEGMENT_MAX)
253+ break;
254+
255+ if (sscanf(line, "%Lx-%Lx : %n", &r.start, &r.end, &consumed)
256+ != 2)
257+ continue;
258+
259+ str = line + consumed;
260+ r.end++;
261+
262+ if (memcmp(str, "System RAM\n", 11)) {
263+ dbgprintf(" Skip: %016Lx - %016Lx : %s", r.start, r.end,
264+ str);
265+ continue;
266+ }
267+
268+ r.type = RANGE_RAM;
269+ memory_range[range_count] = r;
270+ range_count++;
271+
272+ dbgprintf(" Add: %016Lx - %016Lx : %s", r.start, r.end, str);
273+ }
274+
275+ fclose(fp);
276+ *range = memory_range;
277+ *ranges = range_count;
278+
279+ return 0;
280+}
281+
282+struct file_type file_type[] = {
283+ { "elf-arm64", elf_arm64_probe, elf_arm64_load, elf_arm64_usage },
284+};
285+
286+int file_types = sizeof(file_type) / sizeof(file_type[0]);
287+
288+int arch_compat_trampoline(struct kexec_info *info)
289+{
290+ return 0;
291+}
292+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
293+{
294+ return 0;
295+}
296+
297+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
298+ void *location, unsigned long address, unsigned long value)
299+{
300+}
301+
302+void arch_update_purgatory(struct kexec_info *UNUSED(info))
303+{
304+}
305+
306+int is_crashkernel_mem_reserved(void)
307+{
308+ return 0;
309+}
310--- /dev/null
311+++ b/kexec/arch/arm64/kexec-arm64.h
312@@ -0,0 +1,28 @@
313+/*
314+ * ARM64 kexec support.
315+ */
316+
317+#if !defined(KEXEC_ARM64_H)
318+#define KEXEC_ARM64_H
319+
320+/* #include <linux/kexec.h> FIXME: this is broken */
321+#include <sys/types.h>
322+
323+#include "../../kexec.h"
324+
325+#define KEXEC_SEGMENT_MAX 16 /* FIXME: this should come from <linux/kexec.h> */
326+
327+#define BOOT_BLOCK_VERSION 17
328+#define BOOT_BLOCK_LAST_COMP_VERSION 16
329+#define COMMAND_LINE_SIZE 512
330+
331+int elf_arm64_probe(const char *buf, off_t len);
332+int elf_arm64_load(int argc, char **argv, const char *buf, off_t len,
333+ struct kexec_info *info);
334+void elf_arm64_usage(void);
335+
336+struct memory_ranges usablemem_rgns;
337+off_t initrd_base;
338+off_t initrd_size;
339+
340+#endif
341--- /dev/null
342+++ b/kexec/arch/arm64/kexec-elf-arm64.c
343@@ -0,0 +1,147 @@
344+/*
345+ * ARM64 kexec support.
346+ */
347+
348+#define _GNU_SOURCE
349+
350+#include <elf.h>
351+#include <getopt.h>
352+#include <libfdt.h>
353+
354+#include "kexec-arm64.h"
355+
356+#include "../../kexec-syscall.h"
357+#include "../../fs2dt.h"
358+
359+#include "arch/options.h"
360+
361+#if !defined(EM_AARCH64)
362+# define EM_AARCH64 183
363+#endif
364+
365+int elf_arm64_probe(const char *buf, off_t len)
366+{
367+ int result;
368+ struct mem_ehdr ehdr;
369+
370+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
371+
372+ result = build_elf_exec_info(buf, len, &ehdr, 0);
373+
374+ if (result < 0) {
375+ dbgprintf("Not an ELF executable\n");
376+ goto out;
377+ }
378+
379+ if (ehdr.e_machine != EM_AARCH64) {
380+ dbgprintf("Not an AARCH64 executable\n");
381+ result = -1;
382+ goto out;
383+ }
384+
385+ result = 0;
386+
387+out:
388+ free_elf_info(&ehdr);
389+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
390+ return result;
391+}
392+
393+static off_t round_up(off_t v)
394+{
395+ return _ALIGN_DOWN(v + getpagesize(), getpagesize());
396+}
397+
398+int elf_arm64_load(int argc, char **argv, const char *buf, off_t len,
399+ struct kexec_info *info)
400+{
401+ char *dtb_buf;
402+ off_t dtb_base;
403+ off_t dtb_size;
404+ struct mem_ehdr ehdr;
405+ int result;
406+ //unsigned int command_line_len = strlen(arm64_opts.command_line) + 1;
407+
408+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
409+
410+ if (info->kexec_flags & KEXEC_ON_CRASH) {
411+ fprintf(stderr, "kexec: kdump not yet supported on arm64\n");
412+ return -1;
413+ }
414+
415+ result = build_elf_exec_info(buf, len, &ehdr, 0);
416+
417+ if (result < 0) {
418+ free_elf_info(&ehdr);
419+ fprintf(stderr, "%s:%d: build_elf_exec_info failed\n", __func__,
420+ __LINE__);
421+ return result;
422+ }
423+
424+ elf_exec_build_load(info, &ehdr, buf, len, 0);
425+
426+ info->entry = (void*)0x80080000UL; // FIXME
427+
428+ initrd_base = 0;
429+ initrd_size = 0;
430+
431+ if (arm64_opts.ramdisk) {
432+ char *buf;
433+
434+ buf = slurp_file(arm64_opts.ramdisk, &initrd_size);
435+
436+ if (!buf)
437+ fprintf(stderr, "kexec: empty ramdisk file\n");
438+ else {
439+ initrd_base = locate_hole(info, initrd_size, 0, 0, -1, -1);
440+
441+ add_segment_phys_virt(info, buf, initrd_size, initrd_base,
442+ initrd_size, 0);
443+ }
444+ }
445+
446+ fprintf(stderr, "%s:%d: initrd_base: %lx, initrd_size: %lx\n", __func__,
447+ __LINE__, (unsigned long)initrd_base, (unsigned long)initrd_size);
448+
449+ if (arm64_opts.dtb)
450+ dtb_buf = slurp_file(arm64_opts.dtb, &dtb_size);
451+ else
452+ create_flatten_tree(&dtb_buf, &dtb_size,
453+ arm64_opts.command_line);
454+
455+ fprintf(stderr, "%s:%d: dt magic: %x : %x\n", __func__, __LINE__,
456+ fdt32_to_cpu(*(uint32_t*)dtb_buf), *(uint32_t*)dtb_buf);
457+
458+ result = fdt_check_header(dtb_buf);
459+
460+ if (result) {
461+ fprintf(stderr, "Invalid FDT.\n");
462+ return -1;
463+ }
464+
465+ if (arm64_opts.command_line) {
466+ // FIXME: need to handle command line...
467+ fprintf(stderr, "%s:%d: command line support TODO\n", __func__, __LINE__);
468+ }
469+
470+if (1) {
471+ dtb_base = (unsigned long)info->entry + round_up(0xA43FA0); // computed kernel mem size.
472+
473+ fprintf(stderr, "%s:%d: dtb_base: %lx, dtb_size: %lx\n", __func__,
474+ __LINE__, (unsigned long)dtb_base, (unsigned long)dtb_size);
475+} else {
476+ dtb_base = locate_hole(info, dtb_size, 0, 0, -1, -1);
477+
478+ fprintf(stderr, "%s:%d: dtb_base: %lx, dtb_size: %lx\n", __func__,
479+ __LINE__, (unsigned long)dtb_base, (unsigned long)dtb_size);
480+}
481+ add_segment_phys_virt(info, dtb_buf, dtb_size, dtb_base, dtb_size, 0);
482+
483+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
484+ return 0;
485+}
486+
487+void elf_arm64_usage(void)
488+{
489+ fprintf(stderr, "%s:%d\n", __func__, __LINE__);
490+}
491--- a/kexec/kexec-syscall.h
492+++ b/kexec/kexec-syscall.h
493@@ -39,8 +39,8 @@
494 #ifdef __s390__
495 #define __NR_kexec_load 277
496 #endif
497-#ifdef __arm__
498-#define __NR_kexec_load __NR_SYSCALL_BASE + 347
499+#if defined(__arm__) || defined(__arm64__)
500+#define __NR_kexec_load __NR_SYSCALL_BASE + 347
501 #endif
502 #if defined(__mips__)
503 #define __NR_kexec_load 4311
504@@ -76,6 +76,8 @@ static inline long kexec_load(void *entr
505 #define KEXEC_ARCH_PPC64 (21 << 16)
506 #define KEXEC_ARCH_IA_64 (50 << 16)
507 #define KEXEC_ARCH_ARM (40 << 16)
508+#define KEXEC_ARCH_ARM64 (183 << 16)
509+/* #define KEXEC_ARCH_AARCH64 (183 << 16) */
510 #define KEXEC_ARCH_S390 (22 << 16)
511 #define KEXEC_ARCH_SH (42 << 16)
512 #define KEXEC_ARCH_MIPS_LE (10 << 16)
513@@ -121,5 +123,8 @@ static inline long kexec_load(void *entr
514 #ifdef __m68k__
515 #define KEXEC_ARCH_NATIVE KEXEC_ARCH_68K
516 #endif
517+#if defined(__arm64__)
518+#define KEXEC_ARCH_NATIVE KEXEC_ARCH_ARM64
519+#endif
520
521 #endif /* KEXEC_SYSCALL_H */