All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Björn Töpel" <bjorn@kernel.org>
To: Simon Horman <horms@kernel.org>,
	Simon Horman <horms@verge.net.au>,
	Nick Kossifidis <mick@ics.forth.gr>,
	Song Shuai <songshuaishuai@tinylab.org>,
	Li Zhengyu <lizhengyu3@huawei.com>,
	kexec@lists.infradead.org
Cc: Dave Young <dyoung@redhat.com>, Yixun Lan <yixun.lan@gmail.com>,
	Xianting Tian <xianting.tian@linux.alibaba.com>,
	linux-riscv@lists.infradead.org
Subject: [PATCH 4/4] RISC-V: Support loading Image binary file
Date: Wed,  9 Apr 2025 22:14:26 +0200	[thread overview]
Message-ID: <20250409201428.648717-5-bjorn@kernel.org> (raw)
In-Reply-To: <20250409201428.648717-1-bjorn@kernel.org>

From: Song Shuai <songshuaishuai@tinylab.org>

Add image-riscv file_type to probe/load Image file type,

As for kexec_load, find the pbase aligned text_offset from image header
and prepare segments for this syscall.

for kexec_file_load, setup the related options and let kernel part to
deal with the Image.

Signed-off-by: Song Shuai <songshuaishuai@tinylab.org>
---
 kexec/arch/riscv/Makefile            |  2 +
 kexec/arch/riscv/image-header.h      | 88 ++++++++++++++++++++++++++
 kexec/arch/riscv/kexec-image-riscv.c | 95 ++++++++++++++++++++++++++++
 kexec/arch/riscv/kexec-riscv.c       |  1 +
 kexec/arch/riscv/kexec-riscv.h       |  7 ++
 5 files changed, 193 insertions(+)
 create mode 100644 kexec/arch/riscv/image-header.h
 create mode 100644 kexec/arch/riscv/kexec-image-riscv.c

diff --git a/kexec/arch/riscv/Makefile b/kexec/arch/riscv/Makefile
index f26cc9025e77..37ef7603fc38 100644
--- a/kexec/arch/riscv/Makefile
+++ b/kexec/arch/riscv/Makefile
@@ -3,6 +3,7 @@
 #
 riscv_KEXEC_SRCS =  kexec/arch/riscv/kexec-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/crashdump-riscv.c
 
 riscv_MEM_REGIONS = kexec/mem_regions.c
@@ -15,6 +16,7 @@ riscv_CPPFLAGS += -I $(srcdir)/kexec/
 
 dist += kexec/arch/riscv/Makefile $(riscv_KEXEC_SRCS)			\
 	kexec/arch/riscv/kexec-riscv.h					\
+	kexec/arch/riscv/image-header.h					\
 	kexec/arch/riscv/include/arch/options.h
 
 ifdef HAVE_LIBFDT
diff --git a/kexec/arch/riscv/image-header.h b/kexec/arch/riscv/image-header.h
new file mode 100644
index 000000000000..a6775462358e
--- /dev/null
+++ b/kexec/arch/riscv/image-header.h
@@ -0,0 +1,88 @@
+/*
+ * RISCV64 binary image header.
+ * token from arm64/image-header.h
+ */
+
+#if !defined(__RISCV_IMAGE_HEADER_H)
+#define __RISCV_IMAGE_HEADER_H
+
+#include <endian.h>
+#include <stdint.h>
+
+/**
+ * struct riscv_image_header - riscv kernel image header.
+ *
+ **/
+struct riscv_image_header {
+        uint32_t code0;
+        uint32_t code1;
+        uint64_t text_offset;
+        uint64_t image_size;
+        uint64_t flags;
+        uint32_t version;
+        uint32_t res1;
+        uint64_t res2;
+        uint64_t magic;
+        uint32_t magic2;
+        uint32_t res3;
+};
+
+#define RISCV_IMAGE_MAGIC       0x5643534952
+#define RISCV_IMAGE_MAGIC2      0x05435352
+
+#define RISCV_HEADER_VERSION_MAJOR 0
+#define RISCV_HEADER_VERSION_MINOR 2
+
+#define RISCV_HEADER_VERSION (RISCV_HEADER_VERSION_MAJOR << 16 | \
+		                              RISCV_HEADER_VERSION_MINOR)
+
+
+static const uint64_t riscv_image_flag_be = (1UL << 0);
+
+/**
+ * riscv_header_check_magic - Helper to check the riscv image header.
+ *
+ * Returns non-zero if header is OK.
+ */
+
+static inline int riscv_header_check_magic(const struct riscv_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return (h->version >= RISCV_HEADER_VERSION && h->magic2 == RISCV_IMAGE_MAGIC2);
+}
+
+/**
+ * riscv_header_check_endiannes - Helper to check the riscv image header.
+ *
+ * Returns non-zero if the image was built as big endian.
+ */
+
+static inline int riscv_header_check_endiannes(const struct riscv_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return (le64toh(h->flags) & riscv_image_flag_be) >> 0;
+}
+
+
+
+static inline uint64_t riscv_header_text_offset(const struct riscv_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return le64toh(h->text_offset);
+}
+
+static inline uint64_t riscv_header_image_size(const struct riscv_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return le64toh(h->image_size);
+}
+
+#endif
diff --git a/kexec/arch/riscv/kexec-image-riscv.c b/kexec/arch/riscv/kexec-image-riscv.c
new file mode 100644
index 000000000000..6ae7e579fd16
--- /dev/null
+++ b/kexec/arch/riscv/kexec-image-riscv.c
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * RISC-V kexec binary image support.
+ *
+ * Author: Song Shuai <songhshuaishuai@tinylab.org>
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include "image-header.h"
+#include "kexec.h"
+#include "kexec-riscv.h"
+#include "kexec-syscall.h"
+#include "arch/options.h"
+
+int image_riscv_probe(const char *kernel_buf, off_t kernel_size)
+{
+	const struct riscv_image_header *h;
+
+	if (kernel_size < sizeof(struct riscv_image_header)) {
+		dbgprintf("%s: No riscv image header.\n", __func__);
+		return -1;
+	}
+
+	h = (const struct riscv_image_header *)(kernel_buf);
+
+	if (!riscv_header_check_magic(h)) {
+		dbgprintf("%s: Bad riscv image header.\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+int image_riscv_load(int argc, char **argv, const char *kernel_buf,
+	off_t kernel_size, struct kexec_info *info)
+{
+	const struct riscv_image_header *h;
+	unsigned long text_offset, image_size;
+	off_t new_base_addr = 0;
+
+	int ret;
+
+	if (info->file_mode) {
+		return prepare_kexec_file_options(info);
+	}
+
+	h = (const struct riscv_image_header *)(kernel_buf);
+
+	/* Check header */
+	if (!h->image_size){
+		dbgprintf("Kernel image size is NULL\n");
+		ret = EFAILED;
+		goto exit;
+	}
+
+	if(riscv_header_check_endiannes(h)){
+		dbgprintf("Kernel image was built as big endian\n");
+		ret = EFAILED;
+		goto exit;
+	}
+
+	text_offset = riscv_header_text_offset(h);
+	image_size = riscv_header_image_size(h);
+
+	/* Setup the entry and segments */
+
+	ret = riscv_find_pbase(info, &new_base_addr, image_size, text_offset);
+	if (ret < 0) {
+		fprintf(stderr, "Could not find a memory region for the "
+				"provided Image\n");
+		goto exit;
+	}
+
+	info->entry = (void *) new_base_addr;
+	dbgprintf("Entry point for the Image: 0x%lX\n", new_base_addr);
+
+	add_segment(info, kernel_buf, kernel_size, new_base_addr, image_size);
+
+	ret = load_extra_segments(info, text_offset, image_size, ULONG_MAX);
+exit:
+        if (ret)
+                fprintf(stderr, "kexec: load failed.\n");
+        return ret;
+}
+
+void image_riscv_usage(void)
+{
+	printf(
+"     An RISC-V binary image, uncompressed, little endian.\n"
+"     Typically an Image file.\n\n");
+}
diff --git a/kexec/arch/riscv/kexec-riscv.c b/kexec/arch/riscv/kexec-riscv.c
index 631659301749..f34b46831160 100644
--- a/kexec/arch/riscv/kexec-riscv.c
+++ b/kexec/arch/riscv/kexec-riscv.c
@@ -33,6 +33,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},
 };
 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 618099291117..cfb03779a022 100644
--- a/kexec/arch/riscv/kexec-riscv.h
+++ b/kexec/arch/riscv/kexec-riscv.h
@@ -40,7 +40,14 @@ int load_extra_segments(struct kexec_info *info, uint64_t kernel_base,
 int riscv_find_pbase(struct kexec_info *info, off_t *addr,
 				off_t size, off_t align);
 
+/* kexec-elf-riscv.c */
 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);
+
+/* kexec-image-riscv.c */
+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);
-- 
2.45.2



WARNING: multiple messages have this Message-ID (diff)
From: "Björn Töpel" <bjorn@kernel.org>
To: Simon Horman <horms@kernel.org>,
	Simon Horman <horms@verge.net.au>,
	Nick Kossifidis <mick@ics.forth.gr>,
	Song Shuai <songshuaishuai@tinylab.org>,
	Li Zhengyu <lizhengyu3@huawei.com>,
	kexec@lists.infradead.org
Cc: Dave Young <dyoung@redhat.com>, Yixun Lan <yixun.lan@gmail.com>,
	Xianting Tian <xianting.tian@linux.alibaba.com>,
	linux-riscv@lists.infradead.org
Subject: [PATCH 4/4] RISC-V: Support loading Image binary file
Date: Wed,  9 Apr 2025 22:14:26 +0200	[thread overview]
Message-ID: <20250409201428.648717-5-bjorn@kernel.org> (raw)
In-Reply-To: <20250409201428.648717-1-bjorn@kernel.org>

From: Song Shuai <songshuaishuai@tinylab.org>

Add image-riscv file_type to probe/load Image file type,

As for kexec_load, find the pbase aligned text_offset from image header
and prepare segments for this syscall.

for kexec_file_load, setup the related options and let kernel part to
deal with the Image.

Signed-off-by: Song Shuai <songshuaishuai@tinylab.org>
---
 kexec/arch/riscv/Makefile            |  2 +
 kexec/arch/riscv/image-header.h      | 88 ++++++++++++++++++++++++++
 kexec/arch/riscv/kexec-image-riscv.c | 95 ++++++++++++++++++++++++++++
 kexec/arch/riscv/kexec-riscv.c       |  1 +
 kexec/arch/riscv/kexec-riscv.h       |  7 ++
 5 files changed, 193 insertions(+)
 create mode 100644 kexec/arch/riscv/image-header.h
 create mode 100644 kexec/arch/riscv/kexec-image-riscv.c

diff --git a/kexec/arch/riscv/Makefile b/kexec/arch/riscv/Makefile
index f26cc9025e77..37ef7603fc38 100644
--- a/kexec/arch/riscv/Makefile
+++ b/kexec/arch/riscv/Makefile
@@ -3,6 +3,7 @@
 #
 riscv_KEXEC_SRCS =  kexec/arch/riscv/kexec-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/crashdump-riscv.c
 
 riscv_MEM_REGIONS = kexec/mem_regions.c
@@ -15,6 +16,7 @@ riscv_CPPFLAGS += -I $(srcdir)/kexec/
 
 dist += kexec/arch/riscv/Makefile $(riscv_KEXEC_SRCS)			\
 	kexec/arch/riscv/kexec-riscv.h					\
+	kexec/arch/riscv/image-header.h					\
 	kexec/arch/riscv/include/arch/options.h
 
 ifdef HAVE_LIBFDT
diff --git a/kexec/arch/riscv/image-header.h b/kexec/arch/riscv/image-header.h
new file mode 100644
index 000000000000..a6775462358e
--- /dev/null
+++ b/kexec/arch/riscv/image-header.h
@@ -0,0 +1,88 @@
+/*
+ * RISCV64 binary image header.
+ * token from arm64/image-header.h
+ */
+
+#if !defined(__RISCV_IMAGE_HEADER_H)
+#define __RISCV_IMAGE_HEADER_H
+
+#include <endian.h>
+#include <stdint.h>
+
+/**
+ * struct riscv_image_header - riscv kernel image header.
+ *
+ **/
+struct riscv_image_header {
+        uint32_t code0;
+        uint32_t code1;
+        uint64_t text_offset;
+        uint64_t image_size;
+        uint64_t flags;
+        uint32_t version;
+        uint32_t res1;
+        uint64_t res2;
+        uint64_t magic;
+        uint32_t magic2;
+        uint32_t res3;
+};
+
+#define RISCV_IMAGE_MAGIC       0x5643534952
+#define RISCV_IMAGE_MAGIC2      0x05435352
+
+#define RISCV_HEADER_VERSION_MAJOR 0
+#define RISCV_HEADER_VERSION_MINOR 2
+
+#define RISCV_HEADER_VERSION (RISCV_HEADER_VERSION_MAJOR << 16 | \
+		                              RISCV_HEADER_VERSION_MINOR)
+
+
+static const uint64_t riscv_image_flag_be = (1UL << 0);
+
+/**
+ * riscv_header_check_magic - Helper to check the riscv image header.
+ *
+ * Returns non-zero if header is OK.
+ */
+
+static inline int riscv_header_check_magic(const struct riscv_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return (h->version >= RISCV_HEADER_VERSION && h->magic2 == RISCV_IMAGE_MAGIC2);
+}
+
+/**
+ * riscv_header_check_endiannes - Helper to check the riscv image header.
+ *
+ * Returns non-zero if the image was built as big endian.
+ */
+
+static inline int riscv_header_check_endiannes(const struct riscv_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return (le64toh(h->flags) & riscv_image_flag_be) >> 0;
+}
+
+
+
+static inline uint64_t riscv_header_text_offset(const struct riscv_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return le64toh(h->text_offset);
+}
+
+static inline uint64_t riscv_header_image_size(const struct riscv_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return le64toh(h->image_size);
+}
+
+#endif
diff --git a/kexec/arch/riscv/kexec-image-riscv.c b/kexec/arch/riscv/kexec-image-riscv.c
new file mode 100644
index 000000000000..6ae7e579fd16
--- /dev/null
+++ b/kexec/arch/riscv/kexec-image-riscv.c
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * RISC-V kexec binary image support.
+ *
+ * Author: Song Shuai <songhshuaishuai@tinylab.org>
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include "image-header.h"
+#include "kexec.h"
+#include "kexec-riscv.h"
+#include "kexec-syscall.h"
+#include "arch/options.h"
+
+int image_riscv_probe(const char *kernel_buf, off_t kernel_size)
+{
+	const struct riscv_image_header *h;
+
+	if (kernel_size < sizeof(struct riscv_image_header)) {
+		dbgprintf("%s: No riscv image header.\n", __func__);
+		return -1;
+	}
+
+	h = (const struct riscv_image_header *)(kernel_buf);
+
+	if (!riscv_header_check_magic(h)) {
+		dbgprintf("%s: Bad riscv image header.\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+int image_riscv_load(int argc, char **argv, const char *kernel_buf,
+	off_t kernel_size, struct kexec_info *info)
+{
+	const struct riscv_image_header *h;
+	unsigned long text_offset, image_size;
+	off_t new_base_addr = 0;
+
+	int ret;
+
+	if (info->file_mode) {
+		return prepare_kexec_file_options(info);
+	}
+
+	h = (const struct riscv_image_header *)(kernel_buf);
+
+	/* Check header */
+	if (!h->image_size){
+		dbgprintf("Kernel image size is NULL\n");
+		ret = EFAILED;
+		goto exit;
+	}
+
+	if(riscv_header_check_endiannes(h)){
+		dbgprintf("Kernel image was built as big endian\n");
+		ret = EFAILED;
+		goto exit;
+	}
+
+	text_offset = riscv_header_text_offset(h);
+	image_size = riscv_header_image_size(h);
+
+	/* Setup the entry and segments */
+
+	ret = riscv_find_pbase(info, &new_base_addr, image_size, text_offset);
+	if (ret < 0) {
+		fprintf(stderr, "Could not find a memory region for the "
+				"provided Image\n");
+		goto exit;
+	}
+
+	info->entry = (void *) new_base_addr;
+	dbgprintf("Entry point for the Image: 0x%lX\n", new_base_addr);
+
+	add_segment(info, kernel_buf, kernel_size, new_base_addr, image_size);
+
+	ret = load_extra_segments(info, text_offset, image_size, ULONG_MAX);
+exit:
+        if (ret)
+                fprintf(stderr, "kexec: load failed.\n");
+        return ret;
+}
+
+void image_riscv_usage(void)
+{
+	printf(
+"     An RISC-V binary image, uncompressed, little endian.\n"
+"     Typically an Image file.\n\n");
+}
diff --git a/kexec/arch/riscv/kexec-riscv.c b/kexec/arch/riscv/kexec-riscv.c
index 631659301749..f34b46831160 100644
--- a/kexec/arch/riscv/kexec-riscv.c
+++ b/kexec/arch/riscv/kexec-riscv.c
@@ -33,6 +33,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},
 };
 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 618099291117..cfb03779a022 100644
--- a/kexec/arch/riscv/kexec-riscv.h
+++ b/kexec/arch/riscv/kexec-riscv.h
@@ -40,7 +40,14 @@ int load_extra_segments(struct kexec_info *info, uint64_t kernel_base,
 int riscv_find_pbase(struct kexec_info *info, off_t *addr,
 				off_t size, off_t align);
 
+/* kexec-elf-riscv.c */
 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);
+
+/* kexec-image-riscv.c */
+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);
-- 
2.45.2


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

  parent reply	other threads:[~2025-04-09 20:15 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-09 20:14 [PATCH 0/4] kexec-tools RISC-V port Björn Töpel
2025-04-09 20:14 ` Björn Töpel
2025-04-09 20:14 ` [PATCH 1/4] RISC-V: Add support for riscv kexec/kdump on kexec-tools Björn Töpel
2025-04-09 20:14   ` Björn Töpel
2025-04-22 10:48   ` Simon Horman
2025-04-22 10:48     ` Simon Horman
2025-04-22 12:07     ` Björn Töpel
2025-04-22 12:07       ` Björn Töpel
2025-04-22 13:54       ` Simon Horman
2025-04-22 13:54         ` Simon Horman
2025-04-09 20:14 ` [PATCH 2/4] RISC-V: Enable kexec_file_load syscall Björn Töpel
2025-04-09 20:14   ` Björn Töpel
2025-04-09 20:14 ` [PATCH 3/4] RISC-V: Separate elf_riscv_find_pbase out Björn Töpel
2025-04-09 20:14   ` Björn Töpel
2025-04-09 20:14 ` Björn Töpel [this message]
2025-04-09 20:14   ` [PATCH 4/4] RISC-V: Support loading Image binary file Björn Töpel
2025-04-14  8:40 ` [PATCH 0/4] kexec-tools RISC-V port Simon Horman
2025-04-14  8:40   ` Simon Horman

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=20250409201428.648717-5-bjorn@kernel.org \
    --to=bjorn@kernel.org \
    --cc=dyoung@redhat.com \
    --cc=horms@kernel.org \
    --cc=horms@verge.net.au \
    --cc=kexec@lists.infradead.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=lizhengyu3@huawei.com \
    --cc=mick@ics.forth.gr \
    --cc=songshuaishuai@tinylab.org \
    --cc=xianting.tian@linux.alibaba.com \
    --cc=yixun.lan@gmail.com \
    /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.