diff --git a/RISC-V-Add-support-for-kexec-on-kexec-tools.patch b/RISC-V-Add-support-for-kexec-on-kexec-tools.patch
new file mode 100644
index 0000000..ba08d51
--- /dev/null
+++ b/RISC-V-Add-support-for-kexec-on-kexec-tools.patch
@@ -0,0 +1,1176 @@
+From patchwork Tue Apr 16 12:32:33 2019
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Nick Kossifidis <mick@ics.forth.gr>
+X-Patchwork-Id: 10902923
+Return-Path: 
+ <linux-riscv-bounces+patchwork-linux-riscv=patchwork.kernel.org@lists.infradead.org>
+Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org
+ [172.30.200.125])
+	by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A6106139A
+	for <patchwork-linux-riscv@patchwork.kernel.org>;
+ Tue, 16 Apr 2019 12:32:59 +0000 (UTC)
+Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1])
+	by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 69ED428947
+	for <patchwork-linux-riscv@patchwork.kernel.org>;
+ Tue, 16 Apr 2019 12:32:59 +0000 (UTC)
+Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486)
+	id 67BF1289EB; Tue, 16 Apr 2019 12:32:59 +0000 (UTC)
+X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on
+	pdx-wl-mail.web.codeaurora.org
+X-Spam-Level: 
+X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED,
+	DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1
+Received: from bombadil.infradead.org (bombadil.infradead.org
+ [198.137.202.133])
+	(using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits))
+	(No client certificate requested)
+	by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7660828947
+	for <patchwork-linux-riscv@patchwork.kernel.org>;
+ Tue, 16 Apr 2019 12:32:56 +0000 (UTC)
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
+	d=lists.infradead.org; s=bombadil.20170209; h=Sender:
+	Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:
+	List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:To
+	:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:
+	Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:
+	List-Owner; bh=bVaz2qf+pdqHQbaLqHKrRQa2jYTkBAObofgtNsLrdWA=; b=LnueSkO/6mncL2
+	5NzTPBXvv+JLFAnax3AaV9WXPt99dbBpWrkMaC1mxHushNGv/zzj5KvtfQ8dQpc5zGKUVQn7Y71xw
+	C2expvPdG5CijZ2AE6jiTlibqthLVCKKFIiBEiT7XpbxNxx9l8zj+t6WyLUQeDTY91JwJRB8Q8Saj
+	ridsvgG38xoKzZZBpC5Mk+aNQ0UykfVPjL7iTO660EgxbpX6O/e3uSRjGQbNrqrZvJAu6o4Zz3fNJ
+	woomnB7QiWp7sxf6irM6bVfCmb3jOn85sS5tMT8FiXJA3MEgV3pQX0g2kgEnLfuYeIz0kMAN5PpM0
+	rkH1aLH299yU2dcEh/sg==;
+Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org)
+	by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux))
+	id 1hGNGe-0001xW-VI; Tue, 16 Apr 2019 12:32:52 +0000
+Received: from mailgate-2.ics.forth.gr ([139.91.1.5])
+ by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux))
+ id 1hGNGY-0001ws-S9; Tue, 16 Apr 2019 12:32:51 +0000
+Received: from av1.ics.forth.gr (av3in [139.91.1.77])
+ by mailgate-2.ics.forth.gr (8.14.4/ICS-FORTH/V10-1.8-GATE) with ESMTP id
+ x3GCWc4e019120; Tue, 16 Apr 2019 12:32:40 GMT
+X-AuditID: 8b5b9d4d-8f5ff7000000235c-72-5cb5cb66eff6
+Received: from enigma.ics.forth.gr (enigma.ics.forth.gr [139.91.1.35])
+ by av1.ics.forth.gr (SMTP Outbound / FORTH / ICS) with SMTP id
+ 6F.1D.09052.66BC5BC5; Tue, 16 Apr 2019 15:32:38 +0300 (EEST)
+Received: from trampakoulas.ics.forth.gr (trampakoulas.ics.forth.gr
+ [139.91.92.59]) (authenticated bits=0)
+ by enigma.ics.forth.gr (8.15.1//ICS-FORTH/V10.5.0C-EXTNULL-SSL-SASL) with
+ ESMTPSA id x3GCWYxg012723
+ (version=TLSv1.2 cipher=DHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO);
+ Tue, 16 Apr 2019 15:32:37 +0300
+X-ICS-AUTH-INFO: Authenticated user: mick@ics.forth.gr at ics.forth.gr
+From: Nick Kossifidis <mick@ics.forth.gr>
+To: horms@verge.net.au
+Subject: [PATCH] RISC-V: Add support for kexec on kexec-tools
+Date: Tue, 16 Apr 2019 15:32:33 +0300
+Message-Id: <20190416123233.4779-1-mick@ics.forth.gr>
+X-Mailer: git-send-email 2.21.0
+MIME-Version: 1.0
+X-Greylist: inspected by milter-greylist-4.6.2 (mailgate-2.ics.forth.gr
+ [139.91.1.5]);
+ Tue, 16 Apr 2019 12:32:40 +0000 (GMT) for IP:'139.91.1.77' DOMAIN:'av3in'
+ HELO:'av1.ics.forth.gr' FROM:'mick@ics.forth.gr' RCPT:''
+X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2
+ (mailgate-2.ics.forth.gr [139.91.1.5]); Tue, 16 Apr 2019 12:32:40 +0000 (GMT)
+X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 
+X-CRM114-CacheID: sfid-20190416_053247_465442_0666DD49 
+X-CRM114-Status: GOOD (  28.51  )
+X-BeenThere: linux-riscv@lists.infradead.org
+X-Mailman-Version: 2.1.21
+Precedence: list
+List-Id: <linux-riscv.lists.infradead.org>
+List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-riscv>,
+ <mailto:linux-riscv-request@lists.infradead.org?subject=unsubscribe>
+List-Archive: <http://lists.infradead.org/pipermail/linux-riscv/>
+List-Post: <mailto:linux-riscv@lists.infradead.org>
+List-Help: <mailto:linux-riscv-request@lists.infradead.org?subject=help>
+List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-riscv>,
+ <mailto:linux-riscv-request@lists.infradead.org?subject=subscribe>
+Cc: Nick Kossifidis <mick@ics.forth.gr>, linux-riscv@lists.infradead.org,
+ palmer@sifive.com, kexec@lists.infradead.org
+Sender: "linux-riscv" <linux-riscv-bounces@lists.infradead.org>
+Errors-To: 
+ linux-riscv-bounces+patchwork-linux-riscv=patchwork.kernel.org@lists.infradead.org
+X-Virus-Scanned: ClamAV using ClamSMTP
+
+This patch adds kexec support for RISC-V on kexec-tools.
+For now this only includes support for the kexec call, no
+kexec_file or kdump / crashkernel. The only supported image
+type is an ELF image such as vmlinux. When the new kernel
+starts a0 will contain the current hart id and a1 the
+pointer to the dtb (PA).
+
+Note: Until we have CPU suspend support on RISC-V we can't
+fully recover on an SMP system, the kernel side will call
+smp_send_stop(), so at this point we pass "nosmp" to the
+next kernel as a temporary workaround.
+
+I tested this on riscv64 QEMU on both smp and non-smp
+setups and works as expected.
+
+Signed-off-by: Nick Kossifidis <mick@ics.forth.gr>
+---
+ configure.ac                            |   3 +
+ include/elf.h                           |   3 +-
+ kexec/Makefile                          |   1 +
+ kexec/arch/riscv/Makefile               |  34 ++
+ kexec/arch/riscv/include/arch/options.h |  43 ++
+ kexec/arch/riscv/kexec-elf-riscv.c      | 281 ++++++++++++
+ kexec/arch/riscv/kexec-riscv.c          | 545 ++++++++++++++++++++++++
+ kexec/arch/riscv/kexec-riscv.h          |  24 ++
+ kexec/kexec-syscall.h                   |   4 +
+ purgatory/Makefile                      |   1 +
+ purgatory/arch/riscv/Makefile           |   7 +
+ 12 files changed, 947 insertions(+), 3 deletions(-)
+ create mode 100644 kexec/arch/riscv/Makefile
+ create mode 100644 kexec/arch/riscv/include/arch/options.h
+ create mode 100644 kexec/arch/riscv/kexec-elf-riscv.c
+ create mode 100644 kexec/arch/riscv/kexec-riscv.c
+ create mode 100644 kexec/arch/riscv/kexec-riscv.h
+ create mode 100644 purgatory/arch/riscv/Makefile
+
+diff --git a/configure.ac b/configure.ac
+index 19c99db..4f53054 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -55,6 +55,9 @@ case $target_cpu in
+ 	ia64|x86_64|alpha|m68k )
+ 		ARCH="$target_cpu"
+ 		;;
++	riscv32|riscv64 )
++		ARCH="riscv"
++		;;
+ 	* )
+ 		AC_MSG_ERROR([unsupported architecture $target_cpu])
+ 		;;
+diff --git a/include/elf.h b/include/elf.h
+index b7677a2..3e42449 100644
+--- a/include/elf.h
++++ b/include/elf.h
+@@ -259,7 +259,8 @@ typedef struct
+ #define EM_ARC_A5	93		/* ARC Cores Tangent-A5 */
+ #define EM_XTENSA	94		/* Tensilica Xtensa Architecture */
+ #define EM_AARCH64	183		/* ARM AARCH64 */
+-#define EM_NUM		184
++#define EM_RISCV	243		/* RISC-V */
++#define EM_NUM		244
+ 
+ /* If it is necessary to assign new unofficial EM_* values, please
+    pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+diff --git a/kexec/Makefile b/kexec/Makefile
+index 4db84d8..c8978f2 100644
+--- a/kexec/Makefile
++++ b/kexec/Makefile
+@@ -89,6 +89,7 @@ include $(srcdir)/kexec/arch/mips/Makefile
+ include $(srcdir)/kexec/arch/cris/Makefile
+ include $(srcdir)/kexec/arch/ppc/Makefile
+ include $(srcdir)/kexec/arch/ppc64/Makefile
++include $(srcdir)/kexec/arch/riscv/Makefile
+ include $(srcdir)/kexec/arch/s390/Makefile
+ include $(srcdir)/kexec/arch/sh/Makefile
+ include $(srcdir)/kexec/arch/x86_64/Makefile
+diff --git a/kexec/arch/riscv/Makefile b/kexec/arch/riscv/Makefile
+new file mode 100644
+index 0000000..13d8fea
+--- /dev/null
++++ b/kexec/arch/riscv/Makefile
+@@ -0,0 +1,34 @@
++#
++# kexec riscv
++#
++riscv_KEXEC_SRCS =  kexec/arch/riscv/kexec-riscv.c
++riscv_KEXEC_SRCS += kexec/arch/riscv/kexec-elf-riscv.c
++
++riscv_MEM_REGIONS = kexec/mem_regions.c
++
++riscv_DT_OPS += kexec/dt-ops.c
++
++riscv_ARCH_REUSE_INITRD =
++
++riscv_CPPFLAGS += -I $(srcdir)/kexec/
++
++dist += kexec/arch/riscv/Makefile $(riscv_KEXEC_SRCS)			\
++	kexec/arch/riscv/kexec-riscv.h					\
++	kexec/arch/riscv/include/arch/options.h
++
++ifdef HAVE_LIBFDT
++
++LIBS += -lfdt
++
++else
++
++include $(srcdir)/kexec/libfdt/Makefile.libfdt
++
++libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%)
++
++riscv_CPPFLAGS += -I$(srcdir)/kexec/libfdt
++
++riscv_KEXEC_SRCS += $(libfdt_SRCS)
++
++endif
++
+diff --git a/kexec/arch/riscv/include/arch/options.h b/kexec/arch/riscv/include/arch/options.h
+new file mode 100644
+index 0000000..52a0801
+--- /dev/null
++++ b/kexec/arch/riscv/include/arch/options.h
+@@ -0,0 +1,43 @@
++#ifndef KEXEC_ARCH_RISCV_OPTIONS_H
++#define KEXEC_ARCH_RISCV_OPTIONS_H
++
++#define OPT_APPEND		((OPT_MAX)+0)
++#define OPT_DTB			((OPT_MAX)+1)
++#define OPT_INITRD		((OPT_MAX)+2)
++#define	OPT_CMDLINE		((OPT_MAX)+3)
++#define OPT_REUSE_CMDLINE	((OPT_MAX)+4)
++#define OPT_ARCH_MAX		((OPT_MAX)+5)
++
++/* Options relevant to the architecture (excluding loader-specific ones),
++ * in this case none:
++ */
++#define KEXEC_ARCH_OPTIONS \
++	KEXEC_OPTIONS \
++	{ "append",		1, 0, OPT_APPEND}, \
++	{ "dtb",		1, 0, OPT_DTB }, \
++	{ "initrd",		1, 0, OPT_INITRD }, \
++	{ "command-line",	1, 0, OPT_CMDLINE}, \
++	{ "reuse-cmdline",	0, NULL, OPT_REUSE_CMDLINE }, \
++
++
++#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
++
++/* The following two #defines list ALL of the options added by all of the
++ * architecture's loaders.
++ * o	main() uses this complete list to scan for its options, ignoring
++ *	arch-specific/loader-specific ones.
++ * o	Then, arch_process_options() uses this complete list to scan for its
++ *	options, ignoring general/loader-specific ones.
++ * o	Then, the file_type[n].load re-scans for options, using
++ *	KEXEC_ARCH_OPTIONS plus its loader-specific options subset.
++ *	Any unrecognised options cause an error here.
++ *
++ * This is done so that main()'s/arch_process_options()'s getopt_long() calls
++ * don't choose a kernel filename from random arguments to options they don't
++ * recognise -- as they now recognise (if not act upon) all possible options.
++ */
++#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS
++
++#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
++
++#endif /* KEXEC_ARCH_RISCV_OPTIONS_H */
+diff --git a/kexec/arch/riscv/kexec-elf-riscv.c b/kexec/arch/riscv/kexec-elf-riscv.c
+new file mode 100644
+index 0000000..094a058
+--- /dev/null
++++ b/kexec/arch/riscv/kexec-elf-riscv.c
+@@ -0,0 +1,281 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2019 FORTH-ICS/CARV
++ *		       Nick Kossifidis <mick@ics.forth.gr>
++ */
++
++#include "kexec.h"
++#include "dt-ops.h"		/* For dtb_set/clear_initrd() */
++#include <elf.h>		/* For ELF header handling */
++#include <errno.h>		/* For EFBIG/EINVAL */
++#include <unistd.h>		/* For getpagesize() */
++#include "kexec-riscv.h"
++
++extern struct riscv_opts arch_options;
++
++/*********\
++* HELPERS *
++\*********/
++
++/*
++ * Go through the available physical memory regions and
++ * find one that can hold an image of the specified size.
++ * Note: This is called after get_memory_ranges so
++ * info->memory_range[] should be populated. Also note that
++ * memory ranges are sorted, so we'll return the first region
++ * that's big enough for holding the image.
++ */
++static int elf_riscv_find_pbase(struct kexec_info *info, off_t *addr,
++				off_t size)
++{
++	int i = 0;
++	off_t start = 0;
++	off_t end = 0;
++
++	for (i = 0; i < info->memory_ranges; i++) {
++		if (info->memory_range[i].type != RANGE_RAM)
++			continue;
++
++		start = info->memory_range[i].start;
++		end = info->memory_range[i].end;
++
++		/*
++		 * Kernel should be aligned to the nearest
++		 * hugepage (2MB for RV64, 4MB for RV32).
++		 *
++		 * XXX: Region's base address may be already aligned but
++		 * firmware may be loaded there and we'll overwrite it (or
++		 * get a fault due to PMP). Until BBL / OpenSBI update the
++		 * device tree to mark their memory as reserved the assumption
++		 * is that the kernel won't use any memory below its load
++		 * address, that the firmware will be < 2MB in size and that
++		 * the kernel will not use the first hugepage (where the
++		 * firmware is), hence the + 1 below.
++		 */
++#if __riscv_xlen == 64
++		start = _ALIGN_UP(start + 1, 0x200000);
++#else
++		start = _ALIGN_UP(start + 1, 0x400000);
++#endif
++
++		if (end > start && ((end - start) >= size)) {
++			*addr = start;
++			return 0;
++		}
++	}
++
++	return -EFBIG;
++}
++
++/**************\
++* ENTRY POINTS *
++\**************/
++
++int elf_riscv_probe(const char *buf, off_t len)
++{
++	struct mem_ehdr ehdr = {0};
++	int ret = 0;
++
++	ret = build_elf_exec_info(buf, len, &ehdr, 0);
++	if (ret < 0)
++		goto cleanup;
++
++	if (ehdr.e_machine != EM_RISCV) {
++		fprintf(stderr, "Not for this architecture.\n");
++		ret = -EINVAL;
++		goto cleanup;
++	}
++
++	ret = 0;
++
++ cleanup:
++	free_elf_info(&ehdr);
++	return ret;
++}
++
++void elf_riscv_usage(void)
++{
++}
++
++int elf_riscv_load(int argc, char **argv, const char *buf, off_t len,
++	struct kexec_info *info)
++{
++	struct mem_ehdr ehdr = {0};
++	struct mem_phdr *phdr = NULL;
++	struct fdt_image *fdt = arch_options.fdt;
++	char *initrd_buf = NULL;
++	off_t initrd_size = 0;
++	unsigned long initrd_base = 0;
++	off_t new_base_addr = 0;
++	off_t kernel_size = 0;
++	off_t page_size = getpagesize();
++	off_t max_addr = 0;
++	off_t old_base_addr = 0;
++	off_t old_start_addr = 0;
++	int i = 0;
++	int ret = 0;
++
++	if (info->file_mode) {
++		fprintf(stderr, "kexec_file not supported on this "
++				"architecture\n");
++		return -EINVAL;
++	}
++
++	/* Parse the ELF file */
++	ret = build_elf_exec_info(buf, len, &ehdr, 0);
++	if (ret < 0) {
++		fprintf(stderr, "ELF exec parse failed\n");
++		return -EINVAL;
++	}
++
++	max_addr = elf_max_addr(&ehdr);
++	old_base_addr = max_addr;
++	old_start_addr = max_addr;
++
++	/*
++	 * Get the memory footprint, base physical
++	 * and start address of the ELF image
++	 */
++	for (i = 0; i < ehdr.e_phnum; i++) {
++		phdr = &ehdr.e_phdr[i];
++		if (phdr->p_type != PT_LOAD)
++			continue;
++
++		/*
++		 * Note: According to ELF spec the loadable regions
++		 * are sorted on p_vaddr, not p_paddr.
++		 */
++		if (old_base_addr > phdr->p_paddr)
++			old_base_addr = phdr->p_paddr;
++
++		if (phdr->p_vaddr == ehdr.e_entry ||
++		    phdr->p_paddr == ehdr.e_entry)
++			old_start_addr = phdr->p_paddr;
++
++		kernel_size += _ALIGN_UP(phdr->p_memsz, page_size);
++	}
++
++	if (old_base_addr == max_addr || kernel_size == 0) {
++		fprintf(stderr, "No loadable segments present on the "
++				"provided ELF image\n");
++		return -EINVAL;
++	}
++
++	if (old_start_addr == max_addr) {
++		fprintf(stderr, "Could not find the entry point address of "
++				"provided ELF image\n");
++		return -EINVAL;
++	}
++
++	dbgprintf("Got ELF with total memsz %luKB\n"
++		  "Base paddr: 0x%lX, start_addr: 0x%lX\n",
++		  kernel_size / 1024, old_base_addr, old_start_addr);
++
++	/* Get a continuous physical region that can hold the kernel */
++	ret = elf_riscv_find_pbase(info, &new_base_addr, kernel_size);
++	if (ret < 0) {
++		fprintf(stderr, "Could not find a memory region for the "
++				"provided ELF image\n");
++		return ret;
++	}
++
++	dbgprintf("New base paddr for the ELF: 0x%lX\n", new_base_addr);
++
++	/* Re-set the base physical address of the ELF */
++	for (i = 0; i < ehdr.e_phnum; i++) {
++		phdr = &ehdr.e_phdr[i];
++		if (phdr->p_type != PT_LOAD)
++			continue;
++
++		phdr->p_paddr -= old_base_addr;
++		phdr->p_paddr += new_base_addr;
++	}
++
++	/* Re-set the entry point address */
++	ehdr.e_entry = (old_start_addr - old_base_addr) + new_base_addr;
++	info->entry = (void *) ehdr.e_entry;
++	dbgprintf("New entry point for the ELF: 0x%llX\n", ehdr.e_entry);
++
++
++	/* Load the ELF executable */
++	ret = elf_exec_load(&ehdr, info);
++	if (ret < 0) {
++		fprintf(stderr, "ELF exec load failed\n");
++		return ret;
++	}
++
++	/* Do we need to include an initrd image ? */
++	if (!arch_options.initrd_path && !arch_options.initrd_end)
++		dtb_clear_initrd(&fdt->buf, &fdt->size);
++	else if (arch_options.initrd_path) {
++		if (arch_options.initrd_end)
++			fprintf(stderr, "Warning: An initrd image was provided"
++					", will ignore reuseinitrd\n");
++
++		initrd_buf = slurp_file(arch_options.initrd_path,
++					&initrd_size);
++
++		/*
++		 * Create dummy initrd entries in fdt to get the updated
++		 * fdt size
++		 */
++		dtb_set_initrd(&fdt->buf, &fdt->size, max_addr,
++			       max_addr + initrd_size);
++
++		/* Put initrd above kernel + device tree */
++		initrd_base = add_buffer_virt(info, initrd_buf, initrd_size,
++					initrd_size, sizeof(void *),
++					_ALIGN_UP(ehdr.e_entry + kernel_size
++						  + fdt->size, page_size),
++					max_addr, 1);
++
++		/*
++		 * Now that the buffer for initrd is prepared, update the dtb
++		 * with an appropriate location
++		 */
++		dtb_set_initrd(&fdt->buf, &fdt->size, initrd_base,
++			       initrd_base + initrd_size);
++
++		dbgprintf("Base addr for initrd image: 0x%lX\n", initrd_base);
++	}
++
++	add_buffer(info, fdt->buf, fdt->size, fdt->size, 0,
++		_ALIGN_UP(ehdr.e_entry + kernel_size, page_size),
++		max_addr, 1);
++
++	return 0;
++}
++
++
++/*******\
++* STUBS *
++\*******/
++
++int machine_verify_elf_rel(struct mem_ehdr *ehdr)
++{
++	if (ehdr->ei_data != ELFDATA2MSB)
++		return 0;
++#if __riscv_xlen == 64
++	if (ehdr->ei_class != ELFCLASS64)
++#else
++	if (ehdr->ei_class != ELFCLASS32)
++#endif
++		return 0;
++	if (ehdr->e_machine != EM_RISCV)
++		return 0;
++	return 1;
++}
++
++void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr),
++			   struct mem_sym *UNUSED(sym),
++			   unsigned long r_type,
++			   void *UNUSED(location),
++			   unsigned long UNUSED(address),
++			   unsigned long UNUSED(value))
++{
++	switch (r_type) {
++	default:
++		die("Unknown rela relocation: %lu\n", r_type);
++		break;
++	}
++}
+diff --git a/kexec/arch/riscv/kexec-riscv.c b/kexec/arch/riscv/kexec-riscv.c
+new file mode 100644
+index 0000000..dfda729
+--- /dev/null
++++ b/kexec/arch/riscv/kexec-riscv.c
+@@ -0,0 +1,545 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2019 FORTH-ICS/CARV
++ *		       Nick Kossifidis <mick@ics.forth.gr>
++ */
++
++#include "kexec-syscall.h"	/* For KEXEC_ARCH_RISCV */
++#include "kexec.h"		/* For OPT_MAX and concat_cmdline() */
++#include "mem_regions.h"	/* For mem_regions_sort() */
++#include "dt-ops.h"		/* For dtb_set_bootargs() */
++#include <arch/options.h>	/* For KEXEC_ARCH_OPTIONS */
++#include <getopt.h>		/* For struct option */
++#include <sys/stat.h>		/* For stat() and struct stat */
++#include <stdlib.h>		/* For free() */
++#include <errno.h>		/* For EINVAL */
++#include <libfdt.h>		/* For DeviceTree handling */
++#include "kexec-riscv.h"
++
++const struct arch_map_entry arches[] = {
++	{ "riscv32", KEXEC_ARCH_RISCV },
++	{ "riscv64", KEXEC_ARCH_RISCV },
++	{ NULL, 0 },
++};
++
++
++struct file_type file_type[] = {
++	{"elf-riscv", elf_riscv_probe, elf_riscv_load, elf_riscv_usage},
++};
++int file_types = sizeof(file_type) / sizeof(file_type[0]);
++
++/*****************\
++* USAGE / OPTIONS *
++\*****************/
++
++static const char riscv_opts_usage[] =
++"	--append=STRING		Append STRING to the kernel command line.\n"
++"	--dtb=FILE		Use FILE as the device tree blob.\n"
++"	--initrd=FILE		Use FILE as the kernel initial ramdisk.\n"
++"	--cmdline=STRING	Use STRING as the kernel's command line.\n"
++"	--reuse-cmdline		Use kernel command line from running system.\n";
++
++struct riscv_opts arch_options = {0};
++
++static struct fdt_image fdt = {0};
++
++void arch_usage(void)
++{
++	printf(riscv_opts_usage);
++}
++
++int arch_process_options(int argc, char **argv)
++{
++	static const struct option options[] = {
++		KEXEC_ARCH_OPTIONS
++		{ 0 },
++	};
++	static const char short_options[] = KEXEC_ARCH_OPT_STR;
++	struct stat st = {0};
++	char *append = NULL;
++	char *cmdline = NULL;
++	void *tmp = NULL;
++	off_t tmp_size = 0;
++	int opt = 0;
++	int ret = 0;
++
++	while ((opt = getopt_long(argc, argv, short_options,
++				  options, 0)) != -1) {
++		switch (opt) {
++		case OPT_APPEND:
++			append = optarg;
++			break;
++		case OPT_CMDLINE:
++			if (cmdline)
++				fprintf(stderr,
++					"Warning: Kernel's cmdline "
++					"set twice !\n");
++			cmdline = optarg;
++			break;
++		case OPT_REUSE_CMDLINE:
++			if (cmdline)
++				fprintf(stderr,
++					"Warning: Kernel's cmdline "
++					"set twice !\n");
++			cmdline = get_command_line();
++			break;
++		case OPT_DTB:
++			ret = stat(optarg, &st);
++			if (ret) {
++				fprintf(stderr,
++					"Could not find the provided dtb !\n");
++				return -EINVAL;
++			}
++			arch_options.fdt_path = optarg;
++			break;
++		case OPT_INITRD:
++			ret = stat(optarg, &st);
++			if (ret) {
++				fprintf(stderr,
++					"Could not find the provided "
++					"initrd image !\n");
++				return -EINVAL;
++			}
++			arch_options.initrd_path = optarg;
++			break;
++		default:
++			break;
++		}
++	}
++
++	/* Handle Kernel's command line */
++	if (append && !cmdline)
++		fprintf(stderr, "Warning: No cmdline provided, "
++				"using append string as cmdline\n");
++	if (!append && !cmdline)
++		fprintf(stderr, "Warning: No cmdline or append string "
++				"provided\n");
++
++	if (append || cmdline)
++		/*
++		 * Note that this also handles the case where "cmdline"
++		 * or "append" is NULL.
++		 */
++		arch_options.cmdline = concat_cmdline(cmdline, append);
++
++	/*
++	 * XXX: Until we have suspend ready over SBI, make sure we pass nosmp
++	 * to the next kernel.
++	 */
++	arch_options.cmdline = concat_cmdline(arch_options.cmdline, "nosmp");
++	fprintf(stderr, "Note: Passing nosmp to the next kernel until CPU "
++			"suspend is supported on RISC-V\n");
++
++	/* Handle FDT image */
++	if (!arch_options.fdt_path) {
++		ret = stat("/sys/firmware/fdt", &st);
++		if (ret) {
++			fprintf(stderr, "No dtb provided and "
++					"/sys/firmware/fdt is not present\n");
++			return -EINVAL;
++		}
++		fprintf(stderr, "Warning: No dtb provided, "
++				"using /sys/firmware/fdt\n");
++		arch_options.fdt_path = "/sys/firmware/fdt";
++	}
++
++	tmp = slurp_file(arch_options.fdt_path, &tmp_size);
++	ret = fdt_check_header(tmp);
++	if (ret) {
++		fprintf(stderr, "Got an ivalid fdt image !\n");
++		free(tmp);
++		return -EINVAL;
++	}
++	fdt.buf = tmp;
++	fdt.size = tmp_size;
++
++	arch_options.fdt = &fdt;
++
++	if (arch_options.cmdline) {
++		ret = dtb_set_bootargs(&fdt.buf, &fdt.size,
++				       arch_options.cmdline);
++		if (ret < 0) {
++			fprintf(stderr, "Could not set bootargs on "
++					"the fdt image\n");
++			return ret;
++		}
++	}
++
++	return 0;
++}
++
++/*
++ * This one is called after arch_process_options so we already
++ * have an fdt image in place.
++ */
++void arch_reuse_initrd(void)
++{
++	uint32_t addr_cells = 0;
++	const uint32_t *prop32 = NULL;
++	const uint64_t *prop64 = NULL;
++	int prop_size = 0;
++	const void *addr = 0;
++	uint64_t initrd_start = 0;
++	uint64_t initrd_end = 0;
++	int chosen_offset = 0;
++
++	chosen_offset = fdt_subnode_offset(fdt.buf, 0, "chosen");
++	if (chosen_offset < 0) {
++		fprintf(stderr, "No /chosen node found on fdt image "
++				"unable to reuse initrd\n");
++		return;
++	}
++
++	prop32 = fdt_getprop(fdt.buf, 0, "#address-cells", NULL);
++	if (!prop32) {
++		fprintf(stderr, "No #address-cells property on root node\n");
++		return;
++	}
++	addr_cells = be32_to_cpu(*prop32);
++
++	addr = fdt_getprop(fdt.buf, chosen_offset,
++			   "linux,initrd-start", &prop_size);
++	if (!addr) {
++		fprintf(stderr, "Could not get linux,initrd-start\n");
++		return;
++	}
++	switch (addr_cells) {
++	case 1:
++		prop32 = (const uint32_t *) addr;
++		initrd_start = (uint64_t) be32_to_cpu(*prop32);
++		break;
++	case 2:
++		prop64 = (const uint64_t *) addr;
++		initrd_start = (uint64_t) be64_to_cpu(*prop64);
++		break;
++	default:
++		fprintf(stderr, "Invalid #address-cells property\n");
++		return;
++	}
++
++
++	addr = fdt_getprop(fdt.buf, chosen_offset,
++			   "linux,initrd-end", &prop_size);
++	if (!addr) {
++		fprintf(stderr, "Could not get linux,initrd-end\n");
++		return;
++	}
++	switch (addr_cells) {
++	case 1:
++		prop32 = (const uint32_t *) addr;
++		initrd_end = (uint64_t) be32_to_cpu(*prop32);
++		break;
++	case 2:
++		prop64 = (const uint64_t *) addr;
++		initrd_end = (uint64_t) be64_to_cpu(*prop64);
++		break;
++	default:
++		fprintf(stderr, "Invalid #address-cells property\n");
++		return;
++	}
++
++	arch_options.initrd_start = initrd_start;
++	arch_options.initrd_end = initrd_end;
++	dbgprintf("initrd_start: 0x%lX, initrd_end: 0x%lX\n",
++		  initrd_start, initrd_end);
++
++}
++
++
++
++/***************\
++* MEMORY RANGES *
++\***************/
++
++static struct memory_ranges mem_ranges = {0};
++
++static int add_memory_range(uint64_t start, uint64_t end, unsigned type)
++{
++	struct memory_range *tmp_buf = NULL;
++	struct memory_range *ranges = NULL;
++	size_t tmp_size = mem_ranges.size + 1;
++
++	tmp_buf = realloc(mem_ranges.ranges,
++			  tmp_size * sizeof(struct memory_range));
++	if (!tmp_buf) {
++		perror("Unable to expand memory ranges array");
++		return -errno;
++	}
++
++	mem_ranges.ranges = tmp_buf;
++	mem_ranges.size = tmp_size;
++	mem_ranges.max_size = tmp_size;
++
++	ranges = mem_ranges.ranges;
++
++	ranges[mem_ranges.size].start = start;
++	ranges[mem_ranges.size].end = end;
++	ranges[mem_ranges.size].type = type;
++
++	dbgprintf("mem_ranges[%u]: %016llX - %016llX %s\n",
++		  mem_ranges.size,
++		  ranges[mem_ranges.size].start,
++		  ranges[mem_ranges.size].end,
++		  type == RANGE_RESERVED ? "RANGE_RESERVED" : "RANGE_RAM");
++
++	mem_ranges.size++;
++
++	return 0;
++}
++
++static int parse_memory_region(int node_offset, int type)
++{
++	uint32_t addr_cells = 0;
++	uint32_t size_cells = 0;
++	const uint32_t *prop32 = NULL;
++	const uint64_t *prop64 = NULL;
++	int prop_size = 0;
++	const char *reg = NULL;
++	uint64_t addr = 0;
++	uint64_t size = 0;
++	int offset = 0;
++	int entry_size = 0;
++	int num_entries = 0;
++	int ret = 0;
++
++	/*
++	 * Get address-cells and size-cells properties (according to
++	 * binding spec these are the same as in the root node)
++	 */
++	prop32 = fdt_getprop(fdt.buf, 0, "#address-cells", NULL);
++	if (!prop32) {
++		fprintf(stderr, "No #address-cells property on root node\n");
++		return -EINVAL;
++	}
++	addr_cells = be32_to_cpu(*prop32);
++
++	prop32 = fdt_getprop(fdt.buf, 0, "#size-cells", NULL);
++	if (!prop32) {
++		fprintf(stderr, "No #size-cells property on root node\n");
++		return -EINVAL;
++	}
++	size_cells = be32_to_cpu(*prop32);
++
++	/*
++	 * Parse the reg array, acording to device tree spec it includes
++	 * an arbitary number of <address><size> pairs
++	 */
++	entry_size = (addr_cells + size_cells) * sizeof(uint32_t);
++	reg = fdt_getprop(fdt.buf, node_offset, "reg", &prop_size);
++	if (!reg) {
++		fprintf(stderr, "Warning: Malformed memory region with no "
++				"reg property (%s) !\n",
++				fdt_get_name(fdt.buf, node_offset, NULL));
++		return -EINVAL;
++	}
++
++	num_entries = prop_size / entry_size;
++	dbgprintf("Got region with %i entries: %s\n", num_entries,
++		  fdt_get_name(fdt.buf, node_offset, NULL));
++
++	for (num_entries--; num_entries >= 0; num_entries--) {
++		offset = num_entries * entry_size;
++		switch (addr_cells) {
++		case 1:
++			prop32 = (const uint32_t *) (reg + offset);
++			addr = (uint64_t) be32_to_cpu(*prop32);
++			break;
++		case 2:
++			prop64 = (const uint64_t *) (reg + offset);
++			addr = be64_to_cpu(*prop64);
++			break;
++		default:
++			fprintf(stderr, "Invalid #address-cells property !\n");
++			return -EINVAL;
++		}
++
++
++		switch (size_cells) {
++		case 1:
++			prop32 = (const uint32_t *) (reg + offset +
++				 (addr_cells * sizeof(uint32_t)));
++			size = (uint64_t) be32_to_cpu(*prop32);
++			break;
++		case 2:
++			prop64 = (const uint64_t *) (reg + offset +
++				 (addr_cells * sizeof(uint32_t)));
++			size = be64_to_cpu(*prop64);
++			break;
++		default:
++			fprintf(stderr, "Invalid #size-cells property !\n");
++			return -EINVAL;
++		}
++
++		ret = add_memory_range(addr, addr + size - 1, type);
++		if (ret)
++			return ret;
++
++	}
++
++	return 0;
++}
++
++static int parse_memory_reservations_table(void)
++{
++	int total_memrsrv = 0;
++	uint64_t addr = 0;
++	uint64_t size = 0;
++	int ret = 0;
++	int i = 0;
++
++	total_memrsrv = fdt_num_mem_rsv(fdt.buf);
++	for (i = 0; i < total_memrsrv; i++) {
++		ret = fdt_get_mem_rsv(fdt.buf, i, &addr, &size);
++		if (ret)
++			continue;
++		ret = add_memory_range(addr, addr + size - 1,
++				       RANGE_RESERVED);
++		if (ret)
++			return ret;
++	}
++
++	return 0;
++}
++
++static int parse_reserved_memory_regions(void)
++{
++	int node_offset = 0;
++	int node_depth = 0;
++	int parent_depth = 0;
++	int ranges_size = 0;
++	int ret = 0;
++
++	/* This calls fdt_next_node internaly */
++	node_offset = fdt_subnode_offset(fdt.buf, 0, "reserved-memory");
++	if (node_offset == -FDT_ERR_NOTFOUND)
++		return 0;
++	else {
++		fprintf(stderr, "Error while looking for reserved-memory: %s\n",
++			fdt_strerror(node_offset));
++		return node_offset;
++	}
++
++	parent_depth = fdt_node_depth(fdt.buf, node_offset);
++	if (parent_depth < 0) {
++		fprintf(stderr, "Error while looking for reserved-memory: %s\n",
++			fdt_strerror(parent_depth));
++		return parent_depth;
++	}
++
++	/* Look for the ranges property */
++	fdt_getprop(fdt.buf, node_offset, "ranges", &ranges_size);
++	if (ranges_size < 0) {
++		fprintf(stderr, "Malformed reserved-memory node !\n");
++		return -EINVAL;
++	}
++
++	/* Got the parent node, check for sub-nodes */
++
++	/* fdt_next_node() increases or decreases depth */
++	node_depth = parent_depth;
++	node_offset = fdt_next_node(fdt.buf, node_offset, &node_depth);
++	if (ret < 0) {
++		fprintf(stderr, "Unable to get next node: %s\n",
++			fdt_strerror(ret));
++		return -EINVAL;
++	}
++
++	while (node_depth != parent_depth) {
++		ret = parse_memory_region(node_offset, RANGE_RESERVED);
++		if (ret)
++			return ret;
++
++		node_offset = fdt_next_node(fdt.buf, node_offset, &node_depth);
++		if (ret < 0) {
++			fprintf(stderr, "Unable to get next node: %s\n",
++				fdt_strerror(ret));
++			return -EINVAL;
++		}
++	}
++
++	return 0;
++}
++
++static int parse_memory_regions(void)
++{
++	int node_offset = 0;
++	int num_regions = 0;
++	int ret = 0;
++
++	for (; ; num_regions++) {
++		node_offset = fdt_subnode_offset(fdt.buf, node_offset,
++						 "memory");
++		if (node_offset < 0)
++			break;
++
++		ret = parse_memory_region(node_offset, RANGE_RAM);
++		if (ret)
++			return ret;
++	}
++
++	if (!num_regions) {
++		fprintf(stderr, "Malformed dtb, no /memory nodes present !\n");
++		return -EINVAL;
++	}
++
++	dbgprintf("Got %i /memory nodes\n", num_regions);
++
++	return 0;
++}
++
++
++int get_memory_ranges(struct memory_range **range, int *ranges,
++		      unsigned long kexec_flags)
++{
++	int ret = 0;
++
++	ret = parse_memory_regions();
++	if (ret)
++		return ret;
++
++	ret = parse_reserved_memory_regions();
++	if (ret)
++		return ret;
++
++	ret = parse_memory_reservations_table();
++	if (ret)
++		return ret;
++
++	if (arch_options.initrd_start && arch_options.initrd_end) {
++		dbgprintf("Marking current intird image as reserved\n");
++		add_memory_range(arch_options.initrd_start,
++				 arch_options.initrd_end, RANGE_RESERVED);
++	}
++
++
++	mem_regions_sort(&mem_ranges);
++
++	*range = mem_ranges.ranges;
++	*ranges = mem_ranges.size;
++
++	return 0;
++}
++
++/*******\
++* STUBS *
++\*******/
++
++int arch_compat_trampoline(struct kexec_info *UNUSED(info))
++{
++	return 0;
++}
++
++void arch_update_purgatory(struct kexec_info *UNUSED(info))
++{
++}
++
++int is_crashkernel_mem_reserved(void)
++{
++	return 0;
++}
++
++int get_crash_kernel_load_range(uint64_t *start, uint64_t *end)
++{
++	return 0;
++}
++
+diff --git a/kexec/arch/riscv/kexec-riscv.h b/kexec/arch/riscv/kexec-riscv.h
+new file mode 100644
+index 0000000..547b109
+--- /dev/null
++++ b/kexec/arch/riscv/kexec-riscv.h
+@@ -0,0 +1,24 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2019 FORTH-ICS/CARV
++ *		       Nick Kossifidis <mick@ics.forth.gr>
++ */
++
++struct fdt_image {
++	char	*buf;
++	off_t	size;
++};
++
++struct riscv_opts {
++	char *cmdline;
++	char *fdt_path;
++	char *initrd_path;
++	uint64_t initrd_start;
++	uint64_t initrd_end;
++	struct fdt_image *fdt;
++};
++
++int elf_riscv_probe(const char *buf, off_t len);
++void elf_riscv_usage(void);
++int elf_riscv_load(int argc, char **argv, const char *buf, off_t len,
++		   struct kexec_info *info);
+diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
+index dac1c1f..74b93d8 100644
+--- a/kexec/kexec-syscall.h
++++ b/kexec/kexec-syscall.h
+@@ -126,6 +126,7 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
+ #define KEXEC_ARCH_MIPS_LE (10 << 16)
+ #define KEXEC_ARCH_MIPS    ( 8 << 16)
+ #define KEXEC_ARCH_CRIS    (76 << 16)
++#define KEXEC_ARCH_RISCV   (243 << 16)
+ 
+ #define KEXEC_MAX_SEGMENTS 16
+ 
+@@ -169,5 +170,8 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
+ #if defined(__arm64__)
+ #define KEXEC_ARCH_NATIVE	KEXEC_ARCH_ARM64
+ #endif
++#if defined(__riscv__) || defined(__riscv)
++#define KEXEC_ARCH_NATIVE	KEXEC_ARCH_RISCV
++#endif
+ 
+ #endif /* KEXEC_SYSCALL_H */
+diff --git a/purgatory/Makefile b/purgatory/Makefile
+index 2dd6c47..0a9d1c1 100644
+--- a/purgatory/Makefile
++++ b/purgatory/Makefile
+@@ -25,6 +25,7 @@ include $(srcdir)/purgatory/arch/ia64/Makefile
+ include $(srcdir)/purgatory/arch/mips/Makefile
+ include $(srcdir)/purgatory/arch/ppc/Makefile
+ include $(srcdir)/purgatory/arch/ppc64/Makefile
++include $(srcdir)/purgatory/arch/riscv/Makefile
+ include $(srcdir)/purgatory/arch/s390/Makefile
+ include $(srcdir)/purgatory/arch/sh/Makefile
+ include $(srcdir)/purgatory/arch/x86_64/Makefile
+diff --git a/purgatory/arch/riscv/Makefile b/purgatory/arch/riscv/Makefile
+new file mode 100644
+index 0000000..8bded71
+--- /dev/null
++++ b/purgatory/arch/riscv/Makefile
+@@ -0,0 +1,7 @@
++#
++# Purgatory riscv
++#
++
++riscv_PURGATORY_SRCS =
++
++dist += purgatory/arch/sh/Makefile $(riscv_PURGATORY_SRCS)
diff --git a/kexec-tools-SYS_getrandom.patch b/kexec-tools-SYS_getrandom.patch
deleted file mode 100644
index 7f444ae..0000000
--- a/kexec-tools-SYS_getrandom.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From: Petr Tesarik <ptesarik@suse.com>
-Subject: Define SYS_getrandom if needed
-Upstream: never, build fix for SLE12
-
-SLE12 did not provide a definition for SYS_getrandom.
-
-Signed-off-by: Petr Tesarik <ptesarik@suse.com>
----
- kexec/arch/arm64/kexec-arm64.c |    5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/kexec/arch/arm64/kexec-arm64.c
-+++ b/kexec/arch/arm64/kexec-arm64.c
-@@ -34,6 +34,11 @@
- #include "mem_regions.h"
- #include "arch/options.h"
- 
-+#ifndef __NR_getrandom
-+#define __NR_getrandom 278
-+__SYSCALL(__NR_getrandom, sys_getrandom)
-+#endif
-+
- #define ROOT_NODE_ADDR_CELLS_DEFAULT 1
- #define ROOT_NODE_SIZE_CELLS_DEFAULT 1
- 
diff --git a/kexec-tools-add-variant-helper-functions.patch b/kexec-tools-add-variant-helper-functions.patch
deleted file mode 100644
index f71cbc6..0000000
--- a/kexec-tools-add-variant-helper-functions.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-From: AKASHI Takahiro <takahiro.akashi@linaro.org>
-Date: Fri, 11 Jan 2019 01:59:44 +0900
-Subject: kexec: add variant helper functions for handling memory regions
-References: jsc#SLE-9943
-Upstream: not yet, it's under review in upstream
-
-mem_regions_alloc_and_add() and mem_regions_alloc_and_exclude() are
-functionally equivalent to, respectively, mem_regions_add() and
-mem_regions_exclude() except the formers will re-allocate memory
-dynamically when no more entries are available in 'ranges' array.
-
-Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
-Signed-off-by: Chester Lin <clin@suse.com>
----
- kexec/mem_regions.c | 42 ++++++++++++++++++++++++++++++++++++++++++
- kexec/mem_regions.h |  7 +++++++
- 2 files changed, 49 insertions(+)
-
-diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c
-index 50c8abccb93a..ad7d3f13fd84 100644
---- a/kexec/mem_regions.c
-+++ b/kexec/mem_regions.c
-@@ -125,3 +125,45 @@ int mem_regions_exclude(struct memory_ranges *ranges,
- 	}
- 	return 0;
- }
-+
-+#define KEXEC_MEMORY_RANGES 16
-+
-+int mem_regions_alloc_and_add(struct memory_ranges *ranges,
-+			      unsigned long long base,
-+			      unsigned long long length, int type)
-+{
-+	void *new_ranges;
-+
-+	if (ranges->size >= ranges->max_size) {
-+		new_ranges = realloc(ranges->ranges,
-+				sizeof(struct memory_range) *
-+				(ranges->max_size + KEXEC_MEMORY_RANGES));
-+		if (!new_ranges)
-+			return -1;
-+
-+		ranges->ranges = new_ranges;
-+		ranges->max_size += KEXEC_MEMORY_RANGES;
-+	}
-+
-+	return mem_regions_add(ranges, base, length, type);
-+}
-+
-+int mem_regions_alloc_and_exclude(struct memory_ranges *ranges,
-+				  const struct memory_range *range)
-+{
-+	void *new_ranges;
-+
-+	/* for safety, we should have at least one free entry in ranges */
-+	if (ranges->size >= ranges->max_size) {
-+		new_ranges = realloc(ranges->ranges,
-+				sizeof(struct memory_range) *
-+				(ranges->max_size + KEXEC_MEMORY_RANGES));
-+		if (!new_ranges)
-+			return -1;
-+
-+		ranges->ranges = new_ranges;
-+		ranges->max_size += KEXEC_MEMORY_RANGES;
-+	}
-+
-+	return mem_regions_exclude(ranges, range);
-+}
-diff --git a/kexec/mem_regions.h b/kexec/mem_regions.h
-index ae9e972b0206..e306d67e3261 100644
---- a/kexec/mem_regions.h
-+++ b/kexec/mem_regions.h
-@@ -12,4 +12,11 @@ int mem_regions_exclude(struct memory_ranges *ranges,
- int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
-                     unsigned long long length, int type);
- 
-+int mem_regions_alloc_and_exclude(struct memory_ranges *ranges,
-+				  const struct memory_range *range);
-+
-+int mem_regions_alloc_and_add(struct memory_ranges *ranges,
-+			      unsigned long long base,
-+			      unsigned long long length, int type);
-+
- #endif
diff --git a/kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch b/kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch
deleted file mode 100644
index 4516d1a..0000000
--- a/kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-From: AKASHI Takahiro <takahiro.akashi@linaro.org>
-Date: Fri, 11 Jan 2019 01:59:46 +0900
-Subject: arm64: kdump: deal with a lot of resource entries in /proc/iomem
-References: jsc#SLE-9943
-Upstream: not yet, it's under review in upstream
-
-As described in the commit ("arm64: kexec: allocate memory space avoiding
-reserved regions"), /proc/iomem now has a lot of "reserved" entries, and
-it's not just enough to have a fixed size of memory range array.
-
-With this patch, kdump is allowed to handle arbitrary number of memory
-ranges, using mem_regions_alloc_and_xxx() functions.
-
-Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
-Signed-off-by: Chester Lin <clin@suse.com>
----
- kexec/arch/arm64/crashdump-arm64.c | 25 ++++++++++---------------
- 1 file changed, 10 insertions(+), 15 deletions(-)
-
-diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
-index 4fd7aa8fd43c..38d1a0f3000d 100644
---- a/kexec/arch/arm64/crashdump-arm64.c
-+++ b/kexec/arch/arm64/crashdump-arm64.c
-@@ -23,13 +23,8 @@
- #include "kexec-elf.h"
- #include "mem_regions.h"
- 
--/* memory ranges on crashed kernel */
--static struct memory_range system_memory_ranges[CRASH_MAX_MEMORY_RANGES];
--static struct memory_ranges system_memory_rgns = {
--	.size = 0,
--	.max_size = CRASH_MAX_MEMORY_RANGES,
--	.ranges = system_memory_ranges,
--};
-+/* memory ranges of crashed kernel */
-+static struct memory_ranges system_memory_rgns;
- 
- /* memory range reserved for crashkernel */
- struct memory_range crash_reserved_mem;
-@@ -82,7 +77,7 @@ static uint64_t get_kernel_page_offset(void)
-  *
-  * This function is called once for each memory region found in /proc/iomem.
-  * It locates system RAM and crashkernel reserved memory and places these to
-- * variables, respectively, system_memory_ranges and crash_reserved_mem.
-+ * variables, respectively, system_memory_rgns and usablemem_rgns.
-  */
- 
- static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
-@@ -90,11 +85,11 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
- 				unsigned long long length)
- {
- 	if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0)
--		return mem_regions_add(&usablemem_rgns,
--				       base, length, RANGE_RAM);
-+		return mem_regions_alloc_and_add(&usablemem_rgns,
-+						base, length, RANGE_RAM);
- 	else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0)
--		return mem_regions_add(&system_memory_rgns,
--				       base, length, RANGE_RAM);
-+		return mem_regions_alloc_and_add(&system_memory_rgns,
-+						base, length, RANGE_RAM);
- 	else if (strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) == 0)
- 		elf_info.kern_paddr_start = base;
- 	else if (strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) == 0)
-@@ -135,9 +130,9 @@ static int crash_get_memory_ranges(void)
- 
- 	dbgprint_mem_range("Reserved memory range", &crash_reserved_mem, 1);
- 
--	if (mem_regions_exclude(&system_memory_rgns, &crash_reserved_mem)) {
--		fprintf(stderr,
--			"Error: Number of crash memory ranges excedeed the max limit\n");
-+	if (mem_regions_alloc_and_exclude(&system_memory_rgns,
-+						&crash_reserved_mem)) {
-+		fprintf(stderr, "Cannot allocate memory for ranges\n");
- 		return -ENOMEM;
- 	}
- 
diff --git a/kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch b/kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch
deleted file mode 100644
index a4f95a2..0000000
--- a/kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch
+++ /dev/null
@@ -1,247 +0,0 @@
-From: AKASHI Takahiro <takahiro.akashi@linaro.org>
-Date: Fri, 11 Jan 2019 01:59:45 +0900
-Subject: arm64: kexec: allocate memory space avoiding reserved regions
-References: jsc#SLE-9943
-Upstream: not yet, it's under review in upstream
-
-On UEFI/ACPI-only system, some memory regions, including but not limited
-to UEFI memory map and ACPI tables, must be preserved across kexec'ing.
-Otherwise, they can be corrupted and result in early failure in booting
-a new kernel.
-
-In recent kernels, /proc/iomem now has an extended file format like:
-	40000000-5871ffff : System RAM
-	  41800000-426affff : Kernel code
-	  426b0000-42aaffff : reserved
-	  42ab0000-42c64fff : Kernel data
-	  54400000-583fffff : Crash kernel
-	  58590000-585effff : reserved
-	  58700000-5871ffff : reserved
-	58720000-58b5ffff : reserved
-	58b60000-5be3ffff : System RAM
-	  58b61000-58b61fff : reserved
-	  59a77000-59a77fff : reserved
-	5be40000-5becffff : reserved
-	5bed0000-5bedffff : System RAM
-	5bee0000-5bffffff : reserved
-	5c000000-5fffffff : System RAM
-	  5da00000-5e9fffff : reserved
-	  5ec00000-5edfffff : reserved
-	  5ef6a000-5ef6afff : reserved
-	  5ef6b000-5efcafff : reserved
-	  5efcd000-5efcffff : reserved
-	  5efd0000-5effffff : reserved
-	  5f000000-5fffffff : reserved
-
-where the "reserved" entries at the top level or under System RAM (and
-its descendant resources) are ones of such kind and should not be regarded
-as usable memory ranges where several free spaces for loading kexec data
-will be allocated.
-
-With this patch, get_memory_ranges() will handle this format of file
-correctly. Note that, for safety, unknown regions, in addition to
-"reserved" ones, will also be excluded.
-
-Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
-Signed-off-by: Chester Lin <clin@suse.com>
----
- kexec/arch/arm64/kexec-arm64.c | 146 ++++++++++++++++++++-------------
- 1 file changed, 87 insertions(+), 59 deletions(-)
-
-diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
-index 1cde75d1a771..2e923b54f5b1 100644
---- a/kexec/arch/arm64/kexec-arm64.c
-+++ b/kexec/arch/arm64/kexec-arm64.c
-@@ -10,7 +10,9 @@
- #include <inttypes.h>
- #include <libfdt.h>
- #include <limits.h>
-+#include <stdio.h>
- #include <stdlib.h>
-+#include <string.h>
- #include <sys/stat.h>
- #include <linux/elf-em.h>
- #include <elf.h>
-@@ -29,6 +31,7 @@
- #include "fs2dt.h"
- #include "iomem.h"
- #include "kexec-syscall.h"
-+#include "mem_regions.h"
- #include "arch/options.h"
- 
- #define ROOT_NODE_ADDR_CELLS_DEFAULT 1
-@@ -899,19 +902,33 @@ int get_phys_base_from_pt_load(unsigned long *phys_offset)
- 	return 0;
- }
- 
-+static bool to_be_excluded(char *str)
-+{
-+	if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) ||
-+	    !strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) ||
-+	    !strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) ||
-+	    !strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)))
-+		return false;
-+	else
-+		return true;
-+}
-+
- /**
-- * get_memory_ranges_iomem_cb - Helper for get_memory_ranges_iomem.
-+ * get_memory_ranges - Try to get the memory ranges from
-+ * /proc/iomem.
-  */
--
--static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
--	unsigned long long base, unsigned long long length)
-+int get_memory_ranges(struct memory_range **range, int *ranges,
-+	unsigned long kexec_flags)
- {
--	int ret;
- 	unsigned long phys_offset = UINT64_MAX;
--	struct memory_range *r;
--
--	if (nr >= KEXEC_SEGMENT_MAX)
--		return -1;
-+	FILE *fp;
-+	const char *iomem = proc_iomem();
-+	char line[MAX_LINE], *str;
-+	unsigned long long start, end;
-+	int n, consumed;
-+	struct memory_ranges memranges;
-+	struct memory_range *last, excl_range;
-+	int ret;
- 
- 	if (!try_read_phys_offset_from_kcore) {
- 		/* Since kernel version 4.19, 'kcore' contains
-@@ -945,17 +962,65 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
- 		try_read_phys_offset_from_kcore = true;
- 	}
- 
--	r = (struct memory_range *)data + nr;
-+	fp = fopen(iomem, "r");
-+	if (!fp)
-+		die("Cannot open %s\n", iomem);
-+
-+	memranges.ranges = NULL;
-+	memranges.size = memranges.max_size  = 0;
-+
-+	while (fgets(line, sizeof(line), fp) != 0) {
-+		n = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed);
-+		if (n != 2)
-+			continue;
-+		str = line + consumed;
-+
-+		if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM))) {
-+			ret = mem_regions_alloc_and_add(&memranges,
-+					start, end - start + 1, RANGE_RAM);
-+			if (ret) {
-+				fprintf(stderr,
-+					"Cannot allocate memory for ranges\n");
-+				return -ENOMEM;
-+			}
- 
--	if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)))
--		r->type = RANGE_RAM;
--	else if (!strncmp(str, IOMEM_RESERVED, strlen(IOMEM_RESERVED)))
--		r->type = RANGE_RESERVED;
--	else
--		return 1;
-+			dbgprintf("%s:+[%d] %016llx - %016llx\n", __func__,
-+				memranges.size - 1,
-+				memranges.ranges[memranges.size - 1].start,
-+				memranges.ranges[memranges.size - 1].end);
-+		} else if (to_be_excluded(str)) {
-+			if (!memranges.size)
-+				continue;
-+
-+			/*
-+			 * Note: mem_regions_exclude() doesn't guarantee
-+			 * that the ranges are sorted out, but as long as
-+			 * we cope with /proc/iomem, we only operate on
-+			 * the last entry and so it is safe.
-+			 */
- 
--	r->start = base;
--	r->end = base + length - 1;
-+			/* The last System RAM range */
-+			last = &memranges.ranges[memranges.size - 1];
-+
-+			if (last->end < start)
-+				/* New resource outside of System RAM */
-+				continue;
-+			if (end < last->start)
-+				/* Already excluded by parent resource */
-+				continue;
-+
-+			excl_range.start = start;
-+			excl_range.end = end;
-+			mem_regions_alloc_and_exclude(&memranges, &excl_range);
-+			dbgprintf("%s:-      %016llx - %016llx\n",
-+					__func__, start, end);
-+		}
-+	}
-+
-+	fclose(fp);
-+
-+	*range = memranges.ranges;
-+	*ranges = memranges.size;
- 
- 	/* As a fallback option, we can try determining the PHYS_OFFSET
- 	 * value from the '/proc/iomem' entries as well.
-@@ -976,52 +1041,15 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
- 	 * between the user-space and kernel space 'PHYS_OFFSET'
- 	 * value.
- 	 */
--	set_phys_offset(r->start, "iomem");
-+	if (memranges.size)
-+		set_phys_offset(memranges.ranges[0].start, "iomem");
- 
--	dbgprintf("%s: %016llx - %016llx : %s", __func__, r->start,
--		r->end, str);
-+	dbgprint_mem_range("System RAM ranges;",
-+				memranges.ranges, memranges.size);
- 
- 	return 0;
- }
- 
--/**
-- * get_memory_ranges_iomem - Try to get the memory ranges from
-- * /proc/iomem.
-- */
--
--static int get_memory_ranges_iomem(struct memory_range *array,
--	unsigned int *count)
--{
--	*count = kexec_iomem_for_each_line(NULL,
--		get_memory_ranges_iomem_cb, array);
--
--	if (!*count) {
--		dbgprintf("%s: failed: No RAM found.\n", __func__);
--		return EFAILED;
--	}
--
--	return 0;
--}
--
--/**
-- * get_memory_ranges - Try to get the memory ranges some how.
-- */
--
--int get_memory_ranges(struct memory_range **range, int *ranges,
--	unsigned long kexec_flags)
--{
--	static struct memory_range array[KEXEC_SEGMENT_MAX];
--	unsigned int count;
--	int result;
--
--	result = get_memory_ranges_iomem(array, &count);
--
--	*range = result ? NULL : array;
--	*ranges = result ? 0 : count;
--
--	return result;
--}
--
- int arch_compat_trampoline(struct kexec_info *info)
- {
- 	return 0;
diff --git a/kexec-tools-build-multiboot2-for-i386.patch b/kexec-tools-build-multiboot2-for-i386.patch
deleted file mode 100644
index 3f162a0..0000000
--- a/kexec-tools-build-multiboot2-for-i386.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From: Chris Packham <chris.packham@alliedtelesis.co.nz>
-Date: Sun, 17 Nov 2019 15:52:15 -0800
-Subject: kexec: build multiboot2 for i386
-References: jsc#SLE-9943
-Upstream: Queued, http://lists.infradead.org/pipermail/kexec/2020-January/024311.html
-
-This addresses the following compilation issues when building for i386.
-
- kexec/arch/i386/kexec-x86.c:39:22: error: 'multiboot2_x86_probe' undeclared here (not in a function); did you mean 'multiboot_x86_probe'?
-   { "multiboot2-x86", multiboot2_x86_probe, multiboot2_x86_load,
-                       ^~~~~~~~~~~~~~~~~~~~
-                       multiboot_x86_probe
- kexec/arch/i386/kexec-x86.c:39:44: error: 'multiboot2_x86_load' undeclared here (not in a function); did you mean 'multiboot_x86_load'?
-   { "multiboot2-x86", multiboot2_x86_probe, multiboot2_x86_load,
-                                             ^~~~~~~~~~~~~~~~~~~
-                                             multiboot_x86_load
- kexec/arch/i386/kexec-x86.c:40:4: error: 'multiboot2_x86_usage' undeclared here (not in a function); did you mean 'multiboot_x86_usage'?
-     multiboot2_x86_usage },
-     ^~~~~~~~~~~~~~~~~~~~
-     multiboot_x86_usage
- make: *** [Makefile:114: kexec/arch/i386/kexec-x86.o] Error 1
- make: *** Waiting for unfinished jobs....
-
-Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
-Signed-off-by: Chester Lin <clin@suse.com>
----
-I wasn't sure whether this should be fixed by linking with kexec-mb2-x86.o or
-by removing the code from kexec-x86.c. I went for the former but I'd happily
-change to the latter.
-
- kexec/arch/i386/Makefile    | 2 +-
- kexec/arch/i386/kexec-x86.h | 5 +++++
- 2 files changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/kexec/arch/i386/Makefile b/kexec/arch/i386/Makefile
-index 105cefd..f486103 100644
---- a/kexec/arch/i386/Makefile
-+++ b/kexec/arch/i386/Makefile
-@@ -7,6 +7,7 @@ i386_KEXEC_SRCS += kexec/arch/i386/kexec-elf-x86.c
- i386_KEXEC_SRCS += kexec/arch/i386/kexec-elf-rel-x86.c
- i386_KEXEC_SRCS += kexec/arch/i386/kexec-bzImage.c
- i386_KEXEC_SRCS += kexec/arch/i386/kexec-multiboot-x86.c
-+i386_KEXEC_SRCS += kexec/arch/i386/kexec-mb2-x86.c
- i386_KEXEC_SRCS += kexec/arch/i386/kexec-beoboot-x86.c
- i386_KEXEC_SRCS += kexec/arch/i386/kexec-nbi.c
- i386_KEXEC_SRCS += kexec/arch/i386/x86-linux-setup.c
-@@ -14,7 +15,6 @@ i386_KEXEC_SRCS += kexec/arch/i386/crashdump-x86.c
- 
- dist += kexec/arch/i386/Makefile $(i386_KEXEC_SRCS)			\
- 	kexec/arch/i386/crashdump-x86.h					\
--	kexec/arch/i386/kexec-mb2-x86.c					\
- 	kexec/arch/i386/kexec-x86.h					\
- 	kexec/arch/i386/x86-linux-setup.h				\
- 	kexec/arch/i386/include/arch/options.h
-diff --git a/kexec/arch/i386/kexec-x86.h b/kexec/arch/i386/kexec-x86.h
-index 1b58c3b..0f941df 100644
---- a/kexec/arch/i386/kexec-x86.h
-+++ b/kexec/arch/i386/kexec-x86.h
-@@ -60,6 +60,11 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
- 	struct kexec_info *info);
- void multiboot_x86_usage(void);
- 
-+int multiboot2_x86_load(int argc, char **argv, const char *buf, off_t len,
-+			struct kexec_info *info);
-+void multiboot2_x86_usage(void);
-+int multiboot2_x86_probe(const char *buf, off_t buf_len);
-+
- int elf_x86_probe(const char *buf, off_t len);
- int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
- 	struct kexec_info *info);
diff --git a/kexec-tools-fix-kexec_file_load-error-handling.patch b/kexec-tools-fix-kexec_file_load-error-handling.patch
deleted file mode 100644
index 9a24ebb..0000000
--- a/kexec-tools-fix-kexec_file_load-error-handling.patch
+++ /dev/null
@@ -1,230 +0,0 @@
-From 0ec1fd23847ba103f967e3377e2a1b13712cff6e Mon Sep 17 00:00:00 2001
-From: Petr Tesarik <ptesarik@suse.com>
-Date: Thu, 12 Mar 2020 20:12:12 +0100
-Upstream: not yet, patch sent 2020-03-12 
-Subject: Fix kexec_file_load(2) error handling
-References: bsc#1166105
-
-The handling of kexec_file_load() error conditions needs some
-improvement.
-
-First, on failure, the system call itself returns -1 and sets
-errno. It is wrong to check the return value itself.
-
-Second, do_kexec_file_load() mixes different types of error
-codes (-1, return value of a load method, negative kernel error
-number). Let it always return one of the reason codes defined in
-kexec/kexec.h.
-
-Third, the caller of do_kexec_file_load() cannot know what exactly
-failed inside that function, so it should not check errno directly.
-All it needs to know is whether it makes sense to fall back to the
-other syscall. Add an error code for that purpose (EFALLBACK), and
-let do_kexec_file_load() decide.
-
-Fourth, do_kexec_file_load() should not print any error message if
-it returns EFALLBACK, because the fallback syscall may succeed
-later, and the user is confused whether the command failed, or not.
-Move the error message towards the end of main().
-
-Signed-off-by: Petr Tesarik <ptesarik@suse.com>
----
- kexec/kexec.c | 114 ++++++++++++++++++++++++++++++----------------------------
- kexec/kexec.h |   1 +
- 2 files changed, 61 insertions(+), 54 deletions(-)
-
-diff --git a/kexec/kexec.c b/kexec/kexec.c
-index bc6ab3d..33c1b4b 100644
---- a/kexec/kexec.c
-+++ b/kexec/kexec.c
-@@ -836,11 +836,21 @@ static int kexec_file_unload(unsigned long kexec_file_flags)
- {
- 	int ret = 0;
- 
-+	if (!is_kexec_file_load_implemented())
-+		return EFALLBACK;
-+
- 	ret = kexec_file_load(-1, -1, 0, NULL, kexec_file_flags);
- 	if (ret != 0) {
--		/* The unload failed, print some debugging information */
--		fprintf(stderr, "kexec_file_load(unload) failed\n: %s\n",
--			strerror(errno));
-+		if (errno == ENOSYS) {
-+			ret = EFALLBACK;
-+		} else {
-+			/*
-+			 * The unload failed, print some debugging
-+			 * information */
-+			fprintf(stderr, "kexec_file_load(unload) failed: %s\n",
-+				strerror(errno));
-+			ret = EFAILED;
-+		}
- 	}
- 	return ret;
- }
-@@ -1182,15 +1192,13 @@ static int do_kexec_file_load(int fileind, int argc, char **argv,
- 	info.file_mode = 1;
- 	info.initrd_fd = -1;
- 
--	if (!is_kexec_file_load_implemented()) {
--		fprintf(stderr, "syscall kexec_file_load not available.\n");
--		return -ENOSYS;
--	}
-+	if (!is_kexec_file_load_implemented())
-+		return EFALLBACK;
- 
- 	if (argc - fileind <= 0) {
- 		fprintf(stderr, "No kernel specified\n");
- 		usage();
--		return -1;
-+		return EFAILED;
- 	}
- 
- 	kernel = argv[fileind];
-@@ -1199,7 +1207,7 @@ static int do_kexec_file_load(int fileind, int argc, char **argv,
- 	if (kernel_fd == -1) {
- 		fprintf(stderr, "Failed to open file %s:%s\n", kernel,
- 				strerror(errno));
--		return -1;
-+		return EFAILED;
- 	}
- 
- 	/* slurp in the input kernel */
-@@ -1225,7 +1233,7 @@ static int do_kexec_file_load(int fileind, int argc, char **argv,
- 	if (i == file_types) {
- 		fprintf(stderr, "Cannot determine the file type " "of %s\n",
- 				kernel);
--		return -1;
-+		return EFAILED;
- 	}
- 
- 	ret = file_type[i].load(argc, argv, kernel_buf, kernel_size, &info);
-@@ -1243,9 +1251,43 @@ static int do_kexec_file_load(int fileind, int argc, char **argv,
- 
- 	ret = kexec_file_load(kernel_fd, info.initrd_fd, info.command_line_len,
- 			info.command_line, info.kexec_flags);
--	if (ret != 0)
--		fprintf(stderr, "kexec_file_load failed: %s\n",
--					strerror(errno));
-+	if (ret != 0) {
-+		switch (errno) {
-+			/*
-+			 * Something failed with signature verification.
-+			 * Reject the image.
-+			 */
-+		case ELIBBAD:
-+		case EKEYREJECTED:
-+		case ENOPKG:
-+		case ENOKEY:
-+		case EBADMSG:
-+		case EMSGSIZE:
-+			/* Reject by default. */
-+		default:
-+			ret = EFAILED;
-+			break;
-+
-+			/* Not implemented. */
-+		case ENOSYS:
-+			/*
-+			 * Parsing image or other options failed
-+			 * The image may be invalid or image
-+			 * type may not supported by kernel so
-+			 * retry parsing in kexec-tools.
-+			 */
-+		case EINVAL:
-+		case ENOEXEC:
-+			/*
-+			 * ENOTSUP can be unsupported image
-+			 * type or unsupported PE signature
-+			 * wrapper type, duh.
-+			 */
-+		case ENOTSUP:
-+			ret = EFALLBACK;
-+			break;
-+		}
-+	}
- 
- 	close(kernel_fd);
- 	return ret;
-@@ -1496,7 +1538,7 @@ int main(int argc, char *argv[])
- 	if (do_unload) {
- 		if (do_kexec_file_syscall) {
- 			result = kexec_file_unload(kexec_file_flags);
--			if ((result == -ENOSYS) && do_kexec_fallback)
-+			if (result == EFALLBACK && do_kexec_fallback)
- 				do_kexec_file_syscall = 0;
- 		}
- 		if (!do_kexec_file_syscall)
-@@ -1506,46 +1548,8 @@ int main(int argc, char *argv[])
- 		if (do_kexec_file_syscall) {
- 			result = do_kexec_file_load(fileind, argc, argv,
- 						 kexec_file_flags);
--			if (do_kexec_fallback) switch (result) {
--				/*
--				 * Something failed with signature verification.
--				 * Reject the image.
--				 */
--				case -ELIBBAD:
--				case -EKEYREJECTED:
--				case -ENOPKG:
--				case -ENOKEY:
--				case -EBADMSG:
--				case -EMSGSIZE:
--					/*
--					 * By default reject or do nothing if
--					 * succeded
--					 */
--				default: break;
--				case -ENOSYS: /* not implemented */
--					/*
--					 * Parsing image or other options failed
--					 * The image may be invalid or image
--					 * type may not supported by kernel so
--					 * retry parsing in kexec-tools.
--					 */
--				case -EINVAL:
--				case -ENOEXEC:
--					 /*
--					  * ENOTSUP can be unsupported image
--					  * type or unsupported PE signature
--					  * wrapper type, duh
--					  *
--					  * The kernel sometimes wrongly
--					  * returns ENOTSUPP (524) - ignore
--					  * that. It is not supposed to be seen
--					  * by userspace so seeing it is a
--					  * kernel bug
--					  */
--				case -ENOTSUP:
--					do_kexec_file_syscall = 0;
--					break;
--			}
-+			if (result == EFALLBACK && do_kexec_fallback)
-+				do_kexec_file_syscall = 0;
- 		}
- 		if (!do_kexec_file_syscall)
- 			result = my_load(type, fileind, argc, argv,
-@@ -1570,6 +1574,8 @@ int main(int argc, char *argv[])
- 	if ((result == 0) && do_load_jump_back_helper) {
- 		result = my_load_jump_back_helper(kexec_flags, entry);
- 	}
-+	if (result == EFALLBACK)
-+		fputs("syscall kexec_file_load not available.\n", stderr);
- 
- 	fflush(stdout);
- 	fflush(stderr);
-diff --git a/kexec/kexec.h b/kexec/kexec.h
-index a97b9ce..28fd129 100644
---- a/kexec/kexec.h
-+++ b/kexec/kexec.h
-@@ -63,6 +63,7 @@
-  */
- #define EFAILED		-1	/* default error code */
- #define ENOCRASHKERNEL	-2	/* no memory reserved for crashkernel */
-+#define EFALLBACK	-3	/* fallback to kexec_load(2) may work */
- 
- /*
-  * This function doesn't actually exist.  The idea is that when someone
--- 
-2.16.4
-
diff --git a/kexec-tools-print-error-if-kexec_file_load-fails.patch b/kexec-tools-print-error-if-kexec_file_load-fails.patch
deleted file mode 100644
index 9b0c5e6..0000000
--- a/kexec-tools-print-error-if-kexec_file_load-fails.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From: Hari Bathini <hbathini@linux.ibm.com>
-Date: Wed Mar 16 16:03:05 2022 +0530
-Subject: kexec-tools: print error if kexec_file_load fails
-References: bsc#1197176
-Git-commit: 1d7a308bf7349fcf1627e950159029dfccf85891
-Upstream: merged
-
-Commit 4f77da634035 ("kexec-tools: Fix kexec_file_load(2) error
-handling") introduced EFALLBACK for scenarios where fallbacking back
-to kexec_load syscall is likely to work and dropped printing error
-message for these scenarios. But printing error message for other
-failure scenarios was inadvertently dropped. Restore printing error
-message for such cases.
-
-Fixes: 4f77da634035 ("kexec-tools: Fix kexec_file_load(2) error handling")
-Cc: Petr Tesarik <ptesarik@suse.com>
-Reported-by: Nageswara R Sastry <rnsastry@linux.ibm.com>
-Tested-by: Nageswara R Sastry <rnsastry@linux.ibm.com>
-Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
-Reviewed-by: Petr Tesarik <ptesarik@suse.com>
-Signed-off-by: Simon Horman <horms@verge.net.au>
-
----
- kexec/kexec.c |    1 +
- 1 file changed, 1 insertion(+)
-
---- a/kexec/kexec.c
-+++ b/kexec/kexec.c
-@@ -1265,6 +1265,7 @@ static int do_kexec_file_load(int filein
- 		case EMSGSIZE:
- 			/* Reject by default. */
- 		default:
-+			fprintf(stderr, "kexec_file_load failed: %s\n", strerror(errno));
- 			ret = EFAILED;
- 			break;
- 
diff --git a/kexec-tools-reset-getopt-before-falling-back-to-legacy.patch b/kexec-tools-reset-getopt-before-falling-back-to-legacy.patch
deleted file mode 100644
index 71d4f32..0000000
--- a/kexec-tools-reset-getopt-before-falling-back-to-legacy.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From dadafc4664c7b78ea1561ccca33986c9639106ec Mon Sep 17 00:00:00 2001
-From: Petr Tesarik <ptesarik@suse.com>
-Date: Fri, 13 Mar 2020 14:54:00 +0100
-Upstream: not yet, patch sent 2020-03-13
-Subject: Reset getopt before falling back to legacy syscall
-References: bsc#1166105
-
-The modules may need to parse the arguments again after
-kexec_file_load(2) failed, but getopt is not reset.
-
-This change fixes the --initrd option on s390x. Without this patch,
-it will fail to load the initrd on kernels that do not implement
-kexec_file_load(2).
-
-Signed-off-by: Petr Tesarik <ptesarik@suse.com>
----
- kexec/kexec.c | 12 ++++++++++--
- 1 file changed, 10 insertions(+), 2 deletions(-)
-
-diff --git a/kexec/kexec.c b/kexec/kexec.c
-index 33c1b4b..6601f1f 100644
---- a/kexec/kexec.c
-+++ b/kexec/kexec.c
-@@ -1538,8 +1538,12 @@ int main(int argc, char *argv[])
- 	if (do_unload) {
- 		if (do_kexec_file_syscall) {
- 			result = kexec_file_unload(kexec_file_flags);
--			if (result == EFALLBACK && do_kexec_fallback)
-+			if (result == EFALLBACK && do_kexec_fallback) {
-+				/* Reset getopt for fallback */
-+				opterr = 1;
-+				optind = 1;
- 				do_kexec_file_syscall = 0;
-+			}
- 		}
- 		if (!do_kexec_file_syscall)
- 			result = k_unload(kexec_flags);
-@@ -1548,8 +1552,12 @@ int main(int argc, char *argv[])
- 		if (do_kexec_file_syscall) {
- 			result = do_kexec_file_load(fileind, argc, argv,
- 						 kexec_file_flags);
--			if (result == EFALLBACK && do_kexec_fallback)
-+			if (result == EFALLBACK && do_kexec_fallback) {
-+				/* Reset getopt for fallback */
-+				opterr = 1;
-+				optind = 1;
- 				do_kexec_file_syscall = 0;
-+			}
- 		}
- 		if (!do_kexec_file_syscall)
- 			result = my_load(type, fileind, argc, argv,
--- 
-2.16.4
-
diff --git a/kexec-tools-s390-Reset-kernel-command-line-on-syscal.patch b/kexec-tools-s390-Reset-kernel-command-line-on-syscal.patch
deleted file mode 100644
index 9ecea35..0000000
--- a/kexec-tools-s390-Reset-kernel-command-line-on-syscal.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From: Petr Tesarik <ptesarik@suse.com>
-Date: Fri, 3 Apr 2020 13:12:00 +0200
-Subject: kexec-tools: s390: Reset kernel command line on syscall fallback
-References: bsc#1167868
-Upstream: submitted 2020-04-03
-
-The command line is duplicated on s390 if kexec_file_load(2) is not
-implemented. That's because the corresponding variable is not reset
-to an empty string before re-parsing the kexec command line.
-
-Fixes: 9cf721279f6c ("Reset getopt before falling back to legacy syscall")
-Signed-off-by: Petr Tesarik <ptesarik@suse.com>
----
- kexec/arch/s390/kexec-image.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/kexec/arch/s390/kexec-image.c b/kexec/arch/s390/kexec-image.c
-index 8b39566..3c24fdf 100644
---- a/kexec/arch/s390/kexec-image.c
-+++ b/kexec/arch/s390/kexec-image.c
-@@ -112,6 +112,7 @@ image_s390_load(int argc, char **argv, const char *kernel_buf,
- 		};
- 	static const char short_options[] = KEXEC_OPT_STR "";
- 
-+	command_line[0] = 0;
- 	ramdisk = NULL;
- 	ramdisk_len = 0;
- 	ramdisk_origin = 0;
--- 
-2.16.4
-
diff --git a/kexec-tools-video-capability.patch b/kexec-tools-video-capability.patch
deleted file mode 100644
index c11b345..0000000
--- a/kexec-tools-video-capability.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From: Petr Tesarik <ptesarik@suse.com>
-Subject: Make sure VIDEO_CAPABILITY_64BIT_BASE is defined
-Upstream: never, build fix for SLE12
-
-SLE12 did not provide a definition for VIDEO_CAPABILITY_64BIT_BASE
-in <linux/screen_info.h>.
-
-Signed-off-by: Petr Tesarik <ptesarik@suse.com>
----
- kexec/arch/i386/x86-linux-setup.c |    4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/kexec/arch/i386/x86-linux-setup.c
-+++ b/kexec/arch/i386/x86-linux-setup.c
-@@ -37,6 +37,10 @@
- #include "x86-linux-setup.h"
- #include "../../kexec/kexec-syscall.h"
- 
-+#ifndef VIDEO_CAPABILITY_64BIT_BASE
-+#define VIDEO_CAPABILITY_64BIT_BASE     (1 << 1)        /* Frame buffer base is 64-bit */
-+#endif
-+
- void init_linux_parameters(struct x86_linux_param_header *real_mode)
- {
- 	/* Fill in the values that are usually provided by the kernel. */
diff --git a/kexec-tools.spec b/kexec-tools.spec
index ff423cb..2360317 100644
--- a/kexec-tools.spec
+++ b/kexec-tools.spec
@@ -6,28 +6,23 @@
 
 
 Name:           kexec-tools
-Version:        2.0.20
-Release:        150500.18.3
+Version:        2.0.24
+Release:        5
 Summary:        Tools for loading replacement kernels into memory
 License:        GPL-2.0-or-later
 Group:          System/Kernel
-Source:         https://kernel.org/pub/linux/utils/kernel/kexec/%{name}-%{version}.tar.xz
+URL:            https://projects.horms.net/projects/kexec/
+Source:         https://mirrors.ustc.edu.cn/kernel.org/linux/utils/kernel/kexec/%{name}-%{version}.tar.xz
+Source100:      https://mirrors.ustc.edu.cn/kernel.org/linux/utils/kernel/kexec/%{name}-%{version}.tar.sign
+Source101:      kexec-tools.keyring
 Source1:        kexec-bootloader
 Source2:        kexec-bootloader.8
 Source3:        kexec-load.service
 Source4:        %{name}-rpmlintrc
 Patch3:         %{name}-disable-test.patch
 Patch4:         %{name}-vmcoreinfo-in-xen.patch
-Patch5:         %{name}-add-variant-helper-functions.patch
-Patch6:         %{name}-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch
-Patch7:         %{name}-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch
-Patch8:         %{name}-build-multiboot2-for-i386.patch
-Patch9:         %{name}-video-capability.patch
-Patch10:        %{name}-SYS_getrandom.patch
-Patch11:        %{name}-fix-kexec_file_load-error-handling.patch
-Patch12:        %{name}-reset-getopt-before-falling-back-to-legacy.patch
-Patch13:        %{name}-s390-Reset-kernel-command-line-on-syscal.patch
-Patch14:        %{name}-print-error-if-kexec_file_load-fails.patch
+# https://patchwork.kernel.org/project/linux-riscv/patch/20190416123233.4779-1-mick@ics.forth.gr/
+Patch5:         RISC-V-Add-support-for-kexec-on-kexec-tools.patch
 BuildRequires:  autoconf
 BuildRequires:  automake
 BuildRequires:  systemd-rpm-macros
@@ -36,7 +31,7 @@ BuildRequires:  zlib-devel
 #!BuildIgnore:  gcc-PIE
 Requires:       perl-Bootloader
 Requires(post): suse-module-tools
-Requires(postun): suse-module-tools
+Requires(postun):suse-module-tools
 %{?systemd_requires}
 %ifarch         x86_64
 BuildRequires:  pkgconfig
@@ -51,18 +46,7 @@ the loaded kernel after it panics.
 
 %prep
 %setup -q
-%patch3 -p1
-%patch4 -p1
-%patch5 -p1
-%patch6 -p1
-%patch7 -p1
-%patch8 -p1
-%patch9 -p1
-%patch10 -p1
-%patch11 -p1
-%patch12 -p1
-%patch13 -p1
-%patch14 -p1
+%autopatch -p1
 
 %build
 autoreconf -fvi
@@ -70,7 +54,7 @@ export CFLAGS="%{optflags} -fPIC"
 export BUILD_CFLAGS="%{optflags}"
 export LDFLAGS="-pie"
 %configure
-make %{?_smp_mflags}
+%make_build
 
 %install
 %make_install
@@ -80,10 +64,10 @@ install -m 0755 %{SOURCE1} %{buildroot}/%{_sbindir}
 mkdir -p %{buildroot}/%{_unitdir}
 install -m644 %{SOURCE3} %{buildroot}/%{_unitdir}
 ln -s service %{buildroot}%{_sbindir}/rckexec-load
-#UsrMerge
+%if 0%{?suse_version} < 1550
 mkdir -p %{buildroot}/sbin
 ln -s %{_sbindir}/kexec %{buildroot}/sbin
-#EndUsrMerge
+%endif
 
 %post
 %service_add_post kexec-load.service
@@ -102,29 +86,15 @@ ln -s %{_sbindir}/kexec %{buildroot}/sbin
 %posttrans
 %{?regenerate_initrd_posttrans}
 
-# Compatibility cruft
-# there is no %license prior to SLE12
-%if %{undefined _defaultlicensedir}
-%define license %doc
-%else
-# filesystem before SLE12 SP3 lacks /usr/share/licenses
-%if 0%(test ! -d %{_defaultlicensedir} && echo 1)
-%define _defaultlicensedir %_defaultdocdir
-%endif
-%endif
-# End of compatibility cruft
-
 %files
 %license COPYING
 %doc AUTHORS News TODO doc
 %{_mandir}/man*/*
-#UsrMerge
+%if 0%{?suse_version} < 1550
 /sbin/kexec
-#EndUsrMerge
+%endif
 %{_sbindir}/rckexec-load
 %{_sbindir}/kexec
 %{_sbindir}/kexec-bootloader
 %{_sbindir}/vmcore-dmesg
 %{_unitdir}/kexec-load.service
-
-%changelog