Blame SOURCES/kexec-tools-2.0.8-arm64-Kexec-Add-support-for-binary-image.patch

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