From: Pingfan Liu <piliu@redhat.com>
To: kexec@lists.infradead.org
Cc: Jeremy Linton <jeremy.linton@arm.com>,
Pingfan Liu <piliu@redhat.com>,
horms@verge.net.au, ardb@kernel.org
Subject: [PATCHv2 4/6] kexec/zboot: Add arch independent zboot support
Date: Tue, 16 May 2023 15:31:22 +0800 [thread overview]
Message-ID: <20230516073124.23531-5-piliu@redhat.com> (raw)
In-Reply-To: <20230516073124.23531-1-piliu@redhat.com>
From: Jeremy Linton <jeremy.linton@arm.com>
The linux kernel CONFIG_ZBOOT option creates
self decompressing PE kernel images. So this means
that kexec should have a generic understanding of
the format which may be used by multiple arches.
So lets add an arch independent validation
and decompression routine.
Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
[Modified by Pingfan to adapt the new probe interface]
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
---
include/kexec-pe-zboot.h | 15 +++++
kexec/Makefile | 1 +
kexec/kexec-pe-zboot.c | 134 +++++++++++++++++++++++++++++++++++++++
3 files changed, 150 insertions(+)
create mode 100644 include/kexec-pe-zboot.h
create mode 100644 kexec/kexec-pe-zboot.c
diff --git a/include/kexec-pe-zboot.h b/include/kexec-pe-zboot.h
new file mode 100644
index 0000000..6381485
--- /dev/null
+++ b/include/kexec-pe-zboot.h
@@ -0,0 +1,15 @@
+#ifndef __KEXEC_PE_ZBOOT_H__
+#define __KEXEC_PE_ZBOOT_H__
+
+/* see drivers/firmware/efi/libstub/zboot-header.S */
+struct linux_pe_zboot_header {
+ uint32_t mz_magic;
+ uint32_t image_type;
+ uint32_t payload_offset;
+ uint32_t payload_size;
+ uint32_t reserved[2];
+ uint32_t compress_type;
+};
+
+int pez_prepare(const char *crude_buf, off_t kernel_size, struct kexec_info *info);
+#endif
diff --git a/kexec/Makefile b/kexec/Makefile
index 8a52e8d..11682bf 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -17,6 +17,7 @@ KEXEC_SRCS_base += kexec/kexec-elf-exec.c
KEXEC_SRCS_base += kexec/kexec-elf-core.c
KEXEC_SRCS_base += kexec/kexec-elf-rel.c
KEXEC_SRCS_base += kexec/kexec-elf-boot.c
+KEXEC_SRCS_base += kexec/kexec-pe-zboot.c
KEXEC_SRCS_base += kexec/kexec-iomem.c
KEXEC_SRCS_base += kexec/firmware_memmap.c
KEXEC_SRCS_base += kexec/crashdump.c
diff --git a/kexec/kexec-pe-zboot.c b/kexec/kexec-pe-zboot.c
new file mode 100644
index 0000000..24330a1
--- /dev/null
+++ b/kexec/kexec-pe-zboot.c
@@ -0,0 +1,134 @@
+/*
+ * Generic PE compressed Image (vmlinuz, ZBOOT) support.
+ *
+ * Several distros use 'make zinstall' with CONFIG_ZBOOT
+ * enabled to create UEFI PE images that contain
+ * a decompressor and a compressed kernel image.
+ *
+ * Currently we cannot use kexec_file_load() to load vmlinuz
+ * PE images that self decompress.
+ *
+ * To support ZBOOT, we should:
+ * a). Copy the compressed contents of vmlinuz to a temporary file.
+ * b). Decompress (gunzip-decompress) the contents inside the
+ * temporary file.
+ * c). Validate the resulting image and write it back to the
+ * temporary file.
+ * d). Pass the 'fd' of the temporary file to the kernel space.
+ *
+ * This module contains the arch independent code for the above,
+ * arch specific PE and image checks should wrap calls
+ * to functions in this module.
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "kexec.h"
+#include <kexec-pe-zboot.h>
+
+#define FILENAME_IMAGE "/tmp/ImageXXXXXX"
+
+/*
+ * Returns -1 : in case of error/invalid format (not a valid PE+compressed ZBOOT format.
+ *
+ * crude_buf: the content, which is read from the kernel file without any processing
+ */
+int pez_prepare(const char *crude_buf, off_t kernel_size, struct kexec_info *info)
+{
+ int ret = -1;
+ int fd = 0;
+ int kernel_fd = 0;
+ char *fname = NULL;
+ char *kernel_uncompressed_buf = NULL;
+ off_t decompressed_size = 0;
+ const struct linux_pe_zboot_header *z;
+
+ z = (const struct linux_pe_zboot_header *)(crude_buf);
+
+ if (memcmp(&z->image_type, "zimg", sizeof(z->image_type))) {
+ dbgprintf("%s: PE doesn't contain a compressed kernel.\n", __func__);
+ return -1;
+ }
+
+ /*
+ * At the moment its possible to create images with more compression
+ * algorithms than are supported here, error out if we detect that.
+ */
+ if (memcmp(&z->compress_type, "gzip", 4) &&
+ memcmp(&z->compress_type, "lzma", 4)) {
+ dbgprintf("%s: kexec can only decompress gziped and lzma images.\n", __func__);
+ return -1;
+ }
+
+ if (kernel_size < z->payload_offset + z->payload_size) {
+ dbgprintf("%s: PE too small to contain complete payload.\n", __func__);
+ return -1;
+ }
+
+ if (!(fname = strdup(FILENAME_IMAGE))) {
+ dbgprintf("%s: Can't duplicate strings\n", __func__);
+ return -1;
+ }
+
+ if ((fd = mkstemp(fname)) < 0) {
+ dbgprintf("%s: Can't open file %s\n", __func__, fname);
+ ret = -1;
+ goto fail_mkstemp;
+ }
+
+ if (write(fd, &crude_buf[z->payload_offset],
+ z->payload_size) != z->payload_size) {
+ dbgprintf("%s: Can't write the compressed file %s\n",
+ __func__, fname);
+ ret = -1;
+ goto fail_write;
+ }
+
+ kernel_uncompressed_buf = slurp_decompress_file(fname,
+ &decompressed_size);
+
+ dbgprintf("%s: decompressed size %ld\n", __func__, decompressed_size);
+
+ lseek(fd, 0, SEEK_SET);
+
+ if (write(fd, kernel_uncompressed_buf,
+ decompressed_size) != decompressed_size) {
+ dbgprintf("%s: Can't write the decompressed file %s\n",
+ __func__, fname);
+ ret = -1;
+ goto fail_bad_header;
+ }
+
+ kernel_fd = open(fname, O_RDONLY);
+ if (kernel_fd == -1) {
+ dbgprintf("%s: Failed to open file %s\n",
+ __func__, fname);
+ ret = -1;
+ goto fail_bad_header;
+ }
+
+ dbgprintf("%s: ", __func__);
+
+ info->kernel_fd = kernel_fd;
+ info->kernel_buf = kernel_uncompressed_buf;
+ ret = 0;
+ goto fail_write;
+
+fail_bad_header:
+ free(kernel_uncompressed_buf);
+
+fail_write:
+ if (fd >= 0)
+ close(fd);
+
+ unlink(fname);
+
+fail_mkstemp:
+ free(fname);
+
+ return ret;
+}
--
2.31.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
next prev parent reply other threads:[~2023-05-16 7:32 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 ` [PATCHv2 3/6] arm64: Scatter the logic of reading of kernel file into each probe Pingfan Liu
2023-05-16 7:31 ` Pingfan Liu [this message]
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-5-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 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.