|
|
a6d77e |
From 6dd781cca908aea5f282b5c980d806c2f35ea171 Mon Sep 17 00:00:00 2001
|
|
|
a6d77e |
Message-Id: <6dd781cca908aea5f282b5c980d806c2f35ea171.1431592766.git.panand@redhat.com>
|
|
|
a6d77e |
In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
|
|
|
a6d77e |
References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
|
|
|
a6d77e |
From: Pratyush Anand <panand@redhat.com>
|
|
|
a6d77e |
Date: Mon, 13 Apr 2015 17:19:49 +0530
|
|
|
a6d77e |
Subject: [PATCH 05/17] arm64: Kexec: Add support for binary image
|
|
|
a6d77e |
|
|
|
a6d77e |
This patch adds support to use binary image ie arch/arm64/boot/Image.
|
|
|
a6d77e |
|
|
|
a6d77e |
Binary image does not have sufficient knowledge to extract page offset
|
|
|
a6d77e |
information, which is needed by kexec tool. Use a new command parameter
|
|
|
a6d77e |
--page-offset, so that user can provide page offset information for
|
|
|
a6d77e |
linear mapping.
|
|
|
a6d77e |
|
|
|
a6d77e |
Signed-off-by: Pratyush Anand <panand@redhat.com>
|
|
|
a6d77e |
---
|
|
|
a6d77e |
kexec/arch/arm64/include/arch/options.h | 9 ++--
|
|
|
a6d77e |
kexec/arch/arm64/kexec-arm64.c | 3 ++
|
|
|
a6d77e |
kexec/arch/arm64/kexec-arm64.h | 2 +
|
|
|
a6d77e |
kexec/arch/arm64/kexec-image-arm64.c | 86 +++++++++++++++++++++++++++++++--
|
|
|
a6d77e |
4 files changed, 93 insertions(+), 7 deletions(-)
|
|
|
a6d77e |
|
|
|
a6d77e |
diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h
|
|
|
a6d77e |
index afe3e9827ff3..fa4ad2c68642 100644
|
|
|
a6d77e |
--- a/kexec/arch/arm64/include/arch/options.h
|
|
|
a6d77e |
+++ b/kexec/arch/arm64/include/arch/options.h
|
|
|
a6d77e |
@@ -5,9 +5,10 @@
|
|
|
a6d77e |
#define OPT_DTB ((OPT_MAX)+1)
|
|
|
a6d77e |
#define OPT_INITRD ((OPT_MAX)+2)
|
|
|
a6d77e |
#define OPT_LITE ((OPT_MAX)+3)
|
|
|
a6d77e |
-#define OPT_PORT ((OPT_MAX)+4)
|
|
|
a6d77e |
-#define OPT_REUSE_CMDLINE ((OPT_MAX+5))
|
|
|
a6d77e |
-#define OPT_ARCH_MAX ((OPT_MAX)+6)
|
|
|
a6d77e |
+#define OPT_PAGE_OFFSET ((OPT_MAX)+4)
|
|
|
a6d77e |
+#define OPT_PORT ((OPT_MAX)+5)
|
|
|
a6d77e |
+#define OPT_REUSE_CMDLINE ((OPT_MAX+6))
|
|
|
a6d77e |
+#define OPT_ARCH_MAX ((OPT_MAX)+7)
|
|
|
a6d77e |
|
|
|
a6d77e |
#define KEXEC_ARCH_OPTIONS \
|
|
|
a6d77e |
KEXEC_OPTIONS \
|
|
|
a6d77e |
@@ -16,6 +17,7 @@
|
|
|
a6d77e |
{ "dtb", 1, NULL, OPT_DTB }, \
|
|
|
a6d77e |
{ "initrd", 1, NULL, OPT_INITRD }, \
|
|
|
a6d77e |
{ "lite", 0, NULL, OPT_LITE }, \
|
|
|
a6d77e |
+ { "page-offset", 1, NULL, OPT_PAGE_OFFSET }, \
|
|
|
a6d77e |
{ "port", 1, NULL, OPT_PORT }, \
|
|
|
a6d77e |
{ "ramdisk", 1, NULL, OPT_INITRD }, \
|
|
|
a6d77e |
{ "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \
|
|
|
a6d77e |
@@ -38,6 +40,7 @@ struct arm64_opts {
|
|
|
a6d77e |
const char *command_line;
|
|
|
a6d77e |
const char *dtb;
|
|
|
a6d77e |
const char *initrd;
|
|
|
a6d77e |
+ uint64_t page_offset;
|
|
|
a6d77e |
uint64_t port;
|
|
|
a6d77e |
int lite;
|
|
|
a6d77e |
};
|
|
|
a6d77e |
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
|
|
|
a6d77e |
index 6398e55fe575..86408598a465 100644
|
|
|
a6d77e |
--- a/kexec/arch/arm64/kexec-arm64.c
|
|
|
a6d77e |
+++ b/kexec/arch/arm64/kexec-arm64.c
|
|
|
a6d77e |
@@ -100,6 +100,9 @@ int arch_process_options(int argc, char **argv)
|
|
|
a6d77e |
case OPT_PORT:
|
|
|
a6d77e |
arm64_opts.port = strtoull(optarg, NULL, 0);
|
|
|
a6d77e |
break;
|
|
|
a6d77e |
+ case OPT_PAGE_OFFSET:
|
|
|
a6d77e |
+ arm64_opts.page_offset = strtoull(optarg, NULL, 0);
|
|
|
a6d77e |
+ break;
|
|
|
a6d77e |
default:
|
|
|
a6d77e |
break; /* Ignore core and unknown options. */
|
|
|
a6d77e |
}
|
|
|
a6d77e |
diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
|
|
|
a6d77e |
index 057acf313b49..7f0ca13fec11 100644
|
|
|
a6d77e |
--- a/kexec/arch/arm64/kexec-arm64.h
|
|
|
a6d77e |
+++ b/kexec/arch/arm64/kexec-arm64.h
|
|
|
a6d77e |
@@ -17,6 +17,8 @@
|
|
|
a6d77e |
#define BOOT_BLOCK_LAST_COMP_VERSION 16
|
|
|
a6d77e |
#define COMMAND_LINE_SIZE 512
|
|
|
a6d77e |
|
|
|
a6d77e |
+#define ARM64_DEFAULT_PAGE_OFFSET 0xfffffe0000000000
|
|
|
a6d77e |
+
|
|
|
a6d77e |
int elf_arm64_probe(const char *kernel_buf, off_t kernel_size);
|
|
|
a6d77e |
int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
|
|
|
a6d77e |
off_t kernel_size, struct kexec_info *info);
|
|
|
a6d77e |
diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
|
|
|
a6d77e |
index b025dc6c0185..c577b96d5e31 100644
|
|
|
a6d77e |
--- a/kexec/arch/arm64/kexec-image-arm64.c
|
|
|
a6d77e |
+++ b/kexec/arch/arm64/kexec-image-arm64.c
|
|
|
a6d77e |
@@ -8,6 +8,7 @@
|
|
|
a6d77e |
#include <errno.h>
|
|
|
a6d77e |
#include <getopt.h>
|
|
|
a6d77e |
#include <libfdt.h>
|
|
|
a6d77e |
+#include <stdlib.h>
|
|
|
a6d77e |
|
|
|
a6d77e |
#include "dt-ops.h"
|
|
|
a6d77e |
#include "image-header.h"
|
|
|
a6d77e |
@@ -31,20 +32,97 @@ int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
|
|
|
a6d77e |
dbgprintf("%s: PE format: %s\n", __func__,
|
|
|
a6d77e |
(arm64_header_check_pe_sig(h) ? "yes" : "no"));
|
|
|
a6d77e |
|
|
|
a6d77e |
- fprintf(stderr, "kexec: arm64 binary Image files are currently NOT SUPPORTED.\n");
|
|
|
a6d77e |
+ return 0;
|
|
|
a6d77e |
+}
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+static unsigned long long get_kernel_text_sym(void)
|
|
|
a6d77e |
+{
|
|
|
a6d77e |
+ const char *kallsyms = "/proc/kallsyms";
|
|
|
a6d77e |
+ const char *text = "_text";
|
|
|
a6d77e |
+ char sym[128];
|
|
|
a6d77e |
+ char line[128];
|
|
|
a6d77e |
+ FILE *fp;
|
|
|
a6d77e |
+ unsigned long long vaddr;
|
|
|
a6d77e |
+ char type;
|
|
|
a6d77e |
|
|
|
a6d77e |
- return -1;
|
|
|
a6d77e |
+ fp = fopen(kallsyms, "r"); if (!fp) {
|
|
|
a6d77e |
+ fprintf(stderr, "Cannot open %s\n", kallsyms);
|
|
|
a6d77e |
+ return 0;
|
|
|
a6d77e |
+ }
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ while(fgets(line, sizeof(line), fp) != NULL) {
|
|
|
a6d77e |
+ if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
|
|
|
a6d77e |
+ continue;
|
|
|
a6d77e |
+ if (strcmp(sym, text) == 0) {
|
|
|
a6d77e |
+ dbgprintf("kernel symbol %s vaddr = %16llx\n", text, vaddr);
|
|
|
a6d77e |
+ return vaddr;
|
|
|
a6d77e |
+ }
|
|
|
a6d77e |
+ }
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ fprintf(stderr, "Cannot get kernel %s symbol address\n", text);
|
|
|
a6d77e |
+ return 0;
|
|
|
a6d77e |
+}
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+static unsigned long long get_kernel_page_offset(void)
|
|
|
a6d77e |
+{
|
|
|
a6d77e |
+ unsigned long long text_sym_addr = get_kernel_text_sym();
|
|
|
a6d77e |
+ unsigned long long text_page_offset =
|
|
|
a6d77e |
+ text_sym_addr & 0xFFFFFFFFFFE00000;
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ if(arm64_opts.page_offset) {
|
|
|
a6d77e |
+ if (text_page_offset != arm64_opts.page_offset)
|
|
|
a6d77e |
+ dbgprintf("User page offset %lx did not match with text page offset %llx\n",
|
|
|
a6d77e |
+ arm64_opts.page_offset, text_page_offset);
|
|
|
a6d77e |
+ return arm64_opts.page_offset;
|
|
|
a6d77e |
+ } else if(text_page_offset) {
|
|
|
a6d77e |
+ dbgprintf("text page offset is %llx\n", text_page_offset);
|
|
|
a6d77e |
+ return text_page_offset;
|
|
|
a6d77e |
+ } else {
|
|
|
a6d77e |
+ return ARM64_DEFAULT_PAGE_OFFSET;
|
|
|
a6d77e |
+ }
|
|
|
a6d77e |
}
|
|
|
a6d77e |
|
|
|
a6d77e |
int image_arm64_load(int argc, char **argv, const char *kernel_buf,
|
|
|
a6d77e |
off_t kernel_size, struct kexec_info *info)
|
|
|
a6d77e |
{
|
|
|
a6d77e |
- return -ENOSYS;
|
|
|
a6d77e |
+ int result;
|
|
|
a6d77e |
+ uint64_t start;
|
|
|
a6d77e |
+ const struct arm64_image_header *h;
|
|
|
a6d77e |
+ char *header_option = NULL;
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ h = (const struct arm64_image_header *)(kernel_buf);
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ arm64_mem.text_offset = le64_to_cpu(h->text_offset);
|
|
|
a6d77e |
+ arm64_mem.image_size = le64_to_cpu(h->image_size);
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ arm64_mem.page_offset = get_kernel_page_offset();
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ result = parse_iomem_single("Kernel code\n", &start, NULL);
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ if (result) {
|
|
|
a6d77e |
+ fprintf(stderr, "kexec: Could not get kernel code address.\n");
|
|
|
a6d77e |
+ return -1;
|
|
|
a6d77e |
+ }
|
|
|
a6d77e |
+ start -= arm64_mem.text_offset;
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ /* Add kernel */
|
|
|
a6d77e |
+ add_segment_phys_virt(info, kernel_buf, kernel_size,
|
|
|
a6d77e |
+ start + arm64_mem.text_offset,
|
|
|
a6d77e |
+ kernel_size, 0);
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ info->entry = (void *)start + arm64_mem.text_offset;
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ result = arm64_load_other_segments(info, (unsigned long)info->entry);
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ if (header_option)
|
|
|
a6d77e |
+ free(header_option);
|
|
|
a6d77e |
+
|
|
|
a6d77e |
+ return result;
|
|
|
a6d77e |
}
|
|
|
a6d77e |
|
|
|
a6d77e |
void image_arm64_usage(void)
|
|
|
a6d77e |
{
|
|
|
a6d77e |
printf(
|
|
|
a6d77e |
" An arm64 binary Image file, big or little endian.\n"
|
|
|
a6d77e |
-" This file type is currently NOT SUPPORTED.\n\n");
|
|
|
a6d77e |
+" --page-offset Kernel page-offset for binary image load.\n");
|
|
|
a6d77e |
}
|
|
|
a6d77e |
--
|
|
|
a6d77e |
2.1.0
|
|
|
a6d77e |
|