From: Tao Liu <ltao@redhat.com>
To: kexec@lists.infradead.org
Cc: horms@kernel.org, Tao Liu <ltao@redhat.com>
Subject: [kexec-tools][PATCH] RISC-V: add kexec_load support for vmlinuz
Date: Tue, 26 May 2026 16:58:07 +1200 [thread overview]
Message-ID: <20260526045806.23933-2-ltao@redhat.com> (raw)
Copy arm64 code and change for riscv so that the kexec -c can load
a vmlinuz image.
Signed-off-by: Tao Liu <ltao@redhat.com>
---
kexec/arch/riscv/Makefile | 1 +
| 12 +++
kexec/arch/riscv/kexec-riscv.c | 1 +
kexec/arch/riscv/kexec-riscv.h | 6 ++
kexec/arch/riscv/kexec-vmlinuz-riscv.c | 112 +++++++++++++++++++++++++
5 files changed, 132 insertions(+)
create mode 100644 kexec/arch/riscv/kexec-vmlinuz-riscv.c
diff --git a/kexec/arch/riscv/Makefile b/kexec/arch/riscv/Makefile
index 18a997b..6ba8976 100644
--- a/kexec/arch/riscv/Makefile
+++ b/kexec/arch/riscv/Makefile
@@ -4,6 +4,7 @@
riscv_KEXEC_SRCS = kexec/arch/riscv/crashdump-riscv.c
riscv_KEXEC_SRCS += kexec/arch/riscv/kexec-elf-riscv.c
riscv_KEXEC_SRCS += kexec/arch/riscv/kexec-image-riscv.c
+riscv_KEXEC_SRCS += kexec/arch/riscv/kexec-vmlinuz-riscv.c
riscv_KEXEC_SRCS += kexec/arch/riscv/kexec-riscv.c
riscv_DT_OPS += kexec/dt-ops.c
--git a/kexec/arch/riscv/image-header.h b/kexec/arch/riscv/image-header.h
index a677546..7e950ee 100644
--- a/kexec/arch/riscv/image-header.h
+++ b/kexec/arch/riscv/image-header.h
@@ -85,4 +85,16 @@ static inline uint64_t riscv_header_image_size(const struct riscv_image_header *
return le64toh(h->image_size);
}
+static const uint8_t riscv_image_pe_sig[2] = {'M', 'Z'};
+static const uint8_t riscv_pe_machtype[6] = {'P','E', 0x0, 0x0, 0x64, 0x50};
+
+static inline int riscv_header_check_pe_sig(const struct riscv_image_header *h)
+{
+ if (!h)
+ return 0;
+
+ return (*((char *)&(h->code0)) == riscv_image_pe_sig[0] &&
+ *((char *)&(h->code0) + 1) == riscv_image_pe_sig[1]);
+}
+
#endif
diff --git a/kexec/arch/riscv/kexec-riscv.c b/kexec/arch/riscv/kexec-riscv.c
index a5a12a0..a7188ac 100644
--- a/kexec/arch/riscv/kexec-riscv.c
+++ b/kexec/arch/riscv/kexec-riscv.c
@@ -34,6 +34,7 @@ const struct arch_map_entry arches[] = {
struct file_type file_type[] = {
{"elf-riscv", elf_riscv_probe, elf_riscv_load, elf_riscv_usage},
{"image-riscv", image_riscv_probe, image_riscv_load, image_riscv_usage},
+ {"vmlinuz-riscv", pez_riscv_probe, pez_riscv_load, pez_riscv_usage},
};
int file_types = sizeof(file_type) / sizeof(file_type[0]);
diff --git a/kexec/arch/riscv/kexec-riscv.h b/kexec/arch/riscv/kexec-riscv.h
index cfb0377..f487b27 100644
--- a/kexec/arch/riscv/kexec-riscv.h
+++ b/kexec/arch/riscv/kexec-riscv.h
@@ -51,3 +51,9 @@ int image_riscv_probe(const char *buf, off_t len);
void image_riscv_usage(void);
int image_riscv_load(int argc, char **argv, const char *buf, off_t len,
struct kexec_info *info);
+
+/* kexec-vmlinuz-riscv.c */
+int pez_riscv_probe(const char *buf, off_t len);
+void pez_riscv_usage(void);
+int pez_riscv_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
diff --git a/kexec/arch/riscv/kexec-vmlinuz-riscv.c b/kexec/arch/riscv/kexec-vmlinuz-riscv.c
new file mode 100644
index 0000000..6430e37
--- /dev/null
+++ b/kexec/arch/riscv/kexec-vmlinuz-riscv.c
@@ -0,0 +1,112 @@
+/*
+ * RISC-V PE compressed Image (vmlinuz, ZBOOT) support.
+ * Based on arm64 code
+ */
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "kexec.h"
+#include "kexec-riscv.h"
+#include "image-header.h"
+#include <kexec-pe-zboot.h>
+#include "arch/options.h"
+
+static int kernel_fd = -1;
+static off_t decompressed_size;
+
+/* Returns:
+ * -1 : in case of error/invalid format (not a valid PE+compressed ZBOOT format.
+ */
+int pez_riscv_probe(const char *kernel_buf, off_t kernel_size)
+{
+ int ret = -1;
+ const struct riscv_image_header *h;
+ char *buf;
+ off_t buf_sz;
+
+ buf = (char *)kernel_buf;
+ buf_sz = kernel_size;
+ if (!buf)
+ return -1;
+ h = (const struct riscv_image_header *)buf;
+
+ dbgprintf("%s: PROBE.\n", __func__);
+ if (buf_sz < sizeof(struct riscv_image_header)) {
+ dbgprintf("%s: Not large enough to be a PE image.\n", __func__);
+ return -1;
+ }
+ if (!riscv_header_check_pe_sig(h)) {
+ dbgprintf("%s: Not an PE image.\n", __func__);
+ return -1;
+ }
+
+ if (buf_sz < sizeof(struct riscv_image_header) + h->res3) {
+ dbgprintf("%s: PE image offset larger than image.\n", __func__);
+ return -1;
+ }
+
+ if (memcmp(&buf[h->res3],
+ riscv_pe_machtype, sizeof(riscv_pe_machtype))) {
+ dbgprintf("%s: PE header doesn't match machine type.\n", __func__);
+ return -1;
+ }
+
+ ret = pez_prepare(buf, buf_sz, &kernel_fd, &decompressed_size);
+
+ if (!ret) {
+ /* validate the riscv specific header */
+ struct riscv_image_header hdr_check;
+ if (read(kernel_fd, &hdr_check, sizeof(hdr_check)) != sizeof(hdr_check))
+ goto bad_header;
+
+ lseek(kernel_fd, 0, SEEK_SET);
+
+ if (!riscv_header_check_magic(&hdr_check)) {
+ dbgprintf("%s: Bad riscv image header.\n", __func__);
+ goto bad_header;
+ }
+ }
+
+ return ret;
+bad_header:
+ close(kernel_fd);
+ free(buf);
+ return -1;
+}
+
+int pez_riscv_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ if (kernel_fd > 0 && decompressed_size > 0) {
+ char *kbuf;
+ off_t nread;
+ int fd;
+
+ if (info->kernel_fd > 0)
+ close(info->kernel_fd);
+ info->kernel_fd = kernel_fd;
+ fd = dup(kernel_fd);
+ if (fd < 0) {
+ dbgprintf("%s: dup fd failed.\n", __func__);
+ return -1;
+ }
+ kbuf = slurp_fd(fd, NULL, decompressed_size, &nread);
+ if (!kbuf || nread != decompressed_size) {
+ dbgprintf("%s: slurp_fd failed.\n", __func__);
+ return -1;
+ }
+ return image_riscv_load(argc, argv, kbuf, decompressed_size, info);
+ }
+
+ dbgprintf("%s: wrong kernel file descriptor.\n", __func__);
+ return -1;
+}
+
+void pez_riscv_usage(void)
+{
+ printf(
+" An RISC-V vmlinuz, PE image of a compressed, little endian.\n"
+" kernel, built with ZBOOT enabled.\n\n");
+}
--
2.47.0
next reply other threads:[~2026-05-26 5:05 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-26 4:58 Tao Liu [this message]
2026-05-27 7:41 ` [kexec-tools][PATCH] RISC-V: add kexec_load support for vmlinuz Simon Horman
2026-05-27 7:42 ` Simon Horman
2026-05-27 7:52 ` Tao Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260526045806.23933-2-ltao@redhat.com \
--to=ltao@redhat.com \
--cc=horms@kernel.org \
--cc=kexec@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.