Kexec Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Pingfan Liu <piliu@redhat.com>
To: kexec@lists.infradead.org
Cc: Pingfan Liu <piliu@redhat.com>,
	horms@verge.net.au, ardb@kernel.org, jeremy.linton@arm.com
Subject: [PATCHv2 3/6] arm64: Scatter the logic of reading of kernel file into each probe
Date: Tue, 16 May 2023 15:31:21 +0800	[thread overview]
Message-ID: <20230516073124.23531-4-piliu@redhat.com> (raw)
In-Reply-To: <20230516073124.23531-1-piliu@redhat.com>

As more complicated capsule kernel format ,such as zboot, emerge, where
the compressed kernel is stored as a payload. The straight forward
decompression can not meet the demand.

Therefore, let a probe method read in the kernel file and decide how to
unfold the content by the method itself.

Since other arches still read the kernel image before probe method,
the purpose of the first argument differs from that in aarch64.

Signed-off-by: Pingfan Liu <piliu@redhat.com>
To: kexec@lists.infradead.org
Cc: horms@verge.net.au
Cc: ardb@kernel.org
Cc: jeremy.linton@arm.com
---
 kexec/arch/arm64/kexec-arm64.h        |  6 ++--
 kexec/arch/arm64/kexec-elf-arm64.c    |  7 +++-
 kexec/arch/arm64/kexec-image-arm64.c  |  6 +++-
 kexec/arch/arm64/kexec-uImage-arm64.c | 17 ++++++---
 kexec/arch/arm64/kexec-zImage-arm64.c | 18 +++-------
 kexec/kexec.c                         | 50 +++++++++++++++++----------
 kexec/kexec.h                         |  2 ++
 7 files changed, 66 insertions(+), 40 deletions(-)

diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
index 2825c46..bce93a1 100644
--- a/kexec/arch/arm64/kexec-arm64.h
+++ b/kexec/arch/arm64/kexec-arm64.h
@@ -29,14 +29,14 @@
 #define NOT_KV_ADDR	(0x0)
 #define NOT_PADDR	(ULONGLONG_MAX)
 
-int elf_arm64_probe(const char *kernel_buf, off_t kernel_size,
+int elf_arm64_probe(const char *kern_fname, off_t kernel_size,
 		    struct kexec_info *info);
 
 int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
 	off_t kernel_size, struct kexec_info *info);
 void elf_arm64_usage(void);
 
-int image_arm64_probe(const char *kernel_buf, off_t kernel_size,
+int image_arm64_probe(const char *kern_fname, off_t kernel_size,
 		      struct kexec_info *info);
 
 int image_arm64_load(int argc, char **argv, const char *kernel_buf,
@@ -49,7 +49,7 @@ int uImage_arm64_load(int argc, char **argv, const char *buf, off_t len,
 		      struct kexec_info *info);
 void uImage_arm64_usage(void);
 
-int zImage_arm64_probe(const char *kernel_buf, off_t kernel_size,
+int zImage_arm64_probe(const char *kern_fname, off_t kernel_size,
 		       struct kexec_info *info);
 
 int zImage_arm64_load(int argc, char **argv, const char *kernel_buf,
diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
index 0299349..38afecf 100644
--- a/kexec/arch/arm64/kexec-elf-arm64.c
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
@@ -16,12 +16,14 @@
 #include "kexec-elf.h"
 #include "kexec-syscall.h"
 
-int elf_arm64_probe(const char *kernel_buf, off_t kernel_size,
+int elf_arm64_probe(const char *kern_fname, off_t kernel_size,
 		    struct kexec_info *info)
 {
 	struct mem_ehdr ehdr;
+	char *kernel_buf;
 	int result;
 
+	kernel_buf = slurp_file(kern_fname, &kernel_size);
 	result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0);
 
 	if (result < 0) {
@@ -35,8 +37,11 @@ int elf_arm64_probe(const char *kernel_buf, off_t kernel_size,
 		goto on_exit;
 	}
 
+	info->kernel_fd = open(kern_fname, O_RDONLY);
+	info->kernel_buf = kernel_buf;
 	result = 0;
 on_exit:
+	free(kernel_buf);
 	free_elf_info(&ehdr);
 	return result;
 }
diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
index e8b72f9..668091f 100644
--- a/kexec/arch/arm64/kexec-image-arm64.c
+++ b/kexec/arch/arm64/kexec-image-arm64.c
@@ -14,11 +14,13 @@
 #include "kexec-syscall.h"
 #include "arch/options.h"
 
-int image_arm64_probe(const char *kernel_buf, off_t kernel_size,
+int image_arm64_probe(const char *kern_fname, off_t kernel_size,
 		      struct kexec_info *info)
 {
 	const struct arm64_image_header *h;
+	char *kernel_buf;
 
+	kernel_buf = slurp_file(kern_fname, &kernel_size);
 	if (kernel_size < sizeof(struct arm64_image_header)) {
 		dbgprintf("%s: No arm64 image header.\n", __func__);
 		return -1;
@@ -30,6 +32,8 @@ int image_arm64_probe(const char *kernel_buf, off_t kernel_size,
 		dbgprintf("%s: Bad arm64 image header.\n", __func__);
 		return -1;
 	}
+	info->kernel_fd = open(kern_fname, O_RDONLY);
+	info->kernel_buf = kernel_buf;
 
 	return 0;
 }
diff --git a/kexec/arch/arm64/kexec-uImage-arm64.c b/kexec/arch/arm64/kexec-uImage-arm64.c
index f5b94c8..cce1c76 100644
--- a/kexec/arch/arm64/kexec-uImage-arm64.c
+++ b/kexec/arch/arm64/kexec-uImage-arm64.c
@@ -3,26 +3,35 @@
  */
 #include <stdint.h>
 #include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <image.h>
 #include <kexec-uImage.h>
 #include "../../kexec.h"
 #include "kexec-arm64.h"
 
-int uImage_arm64_probe(const char *buf, off_t len, struct kexec_info *info)
+int uImage_arm64_probe(const char *kern_fname, off_t len, struct kexec_info *info)
 {
 	int ret;
+	char *kernel_buf;
 
-	ret = uImage_probe_kernel(buf, len, IH_ARCH_ARM64);
+	kernel_buf = slurp_file(kern_fname, &len);
+	ret = uImage_probe_kernel(kernel_buf, len, IH_ARCH_ARM64);
 
 	/*  0 - valid uImage.
 	 * -1 - uImage is corrupted.
 	 *  1 - image is not a uImage.
 	 */
-	if (!ret)
+	if (!ret) {
+		info->kernel_fd = open(kern_fname, O_RDONLY);
+		info->kernel_buf = kernel_buf;
 		return 0;
-	else
+	}
+	else {
+		free(kernel_buf);
 		return -1;
+	}
 }
 
 int uImage_arm64_load(int argc, char **argv, const char *buf, off_t len,
diff --git a/kexec/arch/arm64/kexec-zImage-arm64.c b/kexec/arch/arm64/kexec-zImage-arm64.c
index 8a23dea..1c32275 100644
--- a/kexec/arch/arm64/kexec-zImage-arm64.c
+++ b/kexec/arch/arm64/kexec-zImage-arm64.c
@@ -37,10 +37,8 @@
 
 /* Returns:
  * -1 : in case of error/invalid format (not a valid Image.gz format.
- * fd : File descriptor of the temp file containing the decompressed
- *      Image.
  */
-int zImage_arm64_probe(const char *kernel_buf, off_t kernel_size,
+int zImage_arm64_probe(const char *kern_fname, off_t kernel_size,
 		       struct kexec_info *info)
 {
 	int ret = -1;
@@ -50,11 +48,6 @@ int zImage_arm64_probe(const char *kernel_buf, off_t kernel_size,
 	char *kernel_uncompressed_buf = NULL;
 	const struct arm64_image_header *h;
 
-	if (!is_zlib_file(kernel_buf, &kernel_size)) {
-		dbgprintf("%s: Not an zImage file (Image.gz).\n", __func__);
-		return -1;
-	}
-
 	if (!(fname = strdup(FILENAME_IMAGE))) {
 		dbgprintf("%s: Can't duplicate strings\n", __func__);
 		return -1;
@@ -69,7 +62,7 @@ int zImage_arm64_probe(const char *kernel_buf, off_t kernel_size,
 
 	/* slurp in the input kernel */
 	dbgprintf("%s: ", __func__);
-	kernel_uncompressed_buf = slurp_decompress_file(kernel_buf,
+	kernel_uncompressed_buf = slurp_decompress_file(kern_fname,
 							&kernel_size);
 
 	/* check for correct header magic */
@@ -108,13 +101,12 @@ int zImage_arm64_probe(const char *kernel_buf, off_t kernel_size,
 		ret = -1;
 		goto fail_bad_header;
 	}
-
+	info->kernel_fd = kernel_fd;
+	info->kernel_buf = kernel_uncompressed_buf;
 	unlink(fname);
-
-	free(kernel_uncompressed_buf);
 	free(fname);
 
-	return kernel_fd;
+	return 0;
 
 fail_bad_header:
 	free(kernel_uncompressed_buf);
diff --git a/kexec/kexec.c b/kexec/kexec.c
index f5ea73c..767b173 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -701,7 +701,7 @@ static int my_load(const char *type, int fileind, int argc, char **argv,
 		   unsigned long kexec_flags, int skip_checks, void *entry)
 {
 	char *kernel;
-	char *kernel_buf;
+	char *kernel_buf, *probe_buf;
 	off_t kernel_size;
 	int i = 0;
 	int result;
@@ -720,11 +720,15 @@ static int my_load(const char *type, int fileind, int argc, char **argv,
 		return -1;
 	}
 	kernel = argv[fileind];
+#ifndef __aarch64__
 	/* slurp in the input kernel */
-	kernel_buf = slurp_decompress_file(kernel, &kernel_size);
+	probe_buf = kernel_buf = slurp_decompress_file(kernel, &kernel_size);
 
 	dbgprintf("kernel: %p kernel_size: %#llx\n",
 		  kernel_buf, (unsigned long long)kernel_size);
+#else
+	probe_buf = kernel;
+#endif
 
 	if (get_memory_ranges(&info.memory_range, &info.memory_ranges,
 		info.kexec_flags) < 0 || info.memory_ranges == 0) {
@@ -742,14 +746,21 @@ static int my_load(const char *type, int fileind, int argc, char **argv,
 			return -1;
 		} else {
 			/* make sure our file is really of that type */
-			if (file_type[i].probe(kernel_buf, kernel_size, NULL) < 0)
+			if (file_type[i].probe(probe_buf, kernel_size, &info) < 0) {
 				guess_only = 1;
+			} else {
+				if (info.kernel_buf != NULL)
+					kernel_buf = info.kernel_buf;
+			}
 		}
 	}
 	if (!type || guess_only) {
 		for (i = 0; i < file_types; i++) {
-			if (file_type[i].probe(kernel_buf, kernel_size, NULL) == 0)
+			if (file_type[i].probe(probe_buf, kernel_size, &info) == 0) {
+				if (info.kernel_buf != NULL)
+					kernel_buf = info.kernel_buf;
 				break;
+			}
 		}
 		if (i == file_types) {
 			fprintf(stderr, "Cannot determine the file type "
@@ -1266,7 +1277,7 @@ static int do_kexec_file_load(int fileind, int argc, char **argv,
 	int kernel_fd, i;
 	struct kexec_info info;
 	int ret = 0;
-	char *kernel_buf;
+	char *kernel_buf, *probe_buf;
 	off_t kernel_size;
 
 	memset(&info, 0, sizeof(info));
@@ -1278,6 +1289,8 @@ static int do_kexec_file_load(int fileind, int argc, char **argv,
 
 	info.file_mode = 1;
 	info.initrd_fd = -1;
+	info.kernel_fd = -1;
+	info.kernel_buf = NULL;
 
 	if (!is_kexec_file_load_implemented())
 		return EFALLBACK;
@@ -1290,6 +1303,7 @@ static int do_kexec_file_load(int fileind, int argc, char **argv,
 
 	kernel = argv[fileind];
 
+#ifndef __aarch64__
 	kernel_fd = open(kernel, O_RDONLY);
 	if (kernel_fd == -1) {
 		fprintf(stderr, "Failed to open file %s:%s\n", kernel,
@@ -1298,23 +1312,23 @@ static int do_kexec_file_load(int fileind, int argc, char **argv,
 	}
 
 	/* slurp in the input kernel */
-	kernel_buf = slurp_decompress_file(kernel, &kernel_size);
+	probe_buf = kernel_buf = slurp_decompress_file(kernel, &kernel_size);
+#else
+	probe_buf = kernel;
+#endif
 
 	for (i = 0; i < file_types; i++) {
-#ifdef __aarch64__
-		/* handle Image.gz like cases */
-		if (is_zlib_file(kernel, &kernel_size)) {
-			if ((ret = file_type[i].probe(kernel, kernel_size, NULL)) >= 0) {
-				kernel_fd = ret;
-				break;
+		if (file_type[i].probe(probe_buf, kernel_size, &info) >= 0) {
+			if (info.kernel_fd != -1) {
+				close(kernel_fd);
+				kernel_fd = info.kernel_fd;
+			}
+			if (info.kernel_buf != NULL) {
+				free(kernel_buf);
+				kernel_buf = info.kernel_buf;
 			}
-		} else
-			if (file_type[i].probe(kernel_buf, kernel_size, NULL) >= 0)
-				break;
-#else
-		if (file_type[i].probe(kernel_buf, kernel_size, NULL) >= 0)
 			break;
-#endif
+		}
 	}
 
 	if (i == file_types) {
diff --git a/kexec/kexec.h b/kexec/kexec.h
index 0706e46..2dca917 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -164,7 +164,9 @@ struct kexec_info {
 	unsigned long file_mode :1;
 
 	/* Filled by kernel image processing code */
+	int kernel_fd;
 	int initrd_fd;
+	char *kernel_buf;
 	char *command_line;
 	int command_line_len;
 
-- 
2.31.1


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

  parent reply	other threads:[~2023-05-16  7:31 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-16  7:31 [PATCHv2 0/6] arm64: zboot support Pingfan Liu
2023-05-16  7:31 ` [PATCHv2 1/6] kexec: Change the image probe's prototype Pingfan Liu
2023-05-24 11:52   ` Simon Horman
2023-05-25  3:32     ` Pingfan Liu
2023-06-01  1:45       ` Pingfan Liu
2023-06-29  3:57         ` Pingfan Liu
2023-05-16  7:31 ` [PATCHv2 2/6] arm64: Fix some issues with zImage _probe() Pingfan Liu
2023-05-16  7:31 ` Pingfan Liu [this message]
2023-05-16  7:31 ` [PATCHv2 4/6] kexec/zboot: Add arch independent zboot support Pingfan Liu
2023-05-16  7:31 ` [PATCHv2 5/6] arm64: Add ZBOOT PE containing compressed image support Pingfan Liu
2023-05-16  7:31 ` [PATCHv2 6/6] arm64: Hook up the ZBOOT support as vmlinuz Pingfan 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=20230516073124.23531-4-piliu@redhat.com \
    --to=piliu@redhat.com \
    --cc=ardb@kernel.org \
    --cc=horms@verge.net.au \
    --cc=jeremy.linton@arm.com \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox