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: [PATCHv6 4/5] arm64: Add ZBOOT PE containing compressed image support
Date: Mon, 24 Jul 2023 10:21:41 +0800 [thread overview]
Message-ID: <20230724022142.6425-5-piliu@redhat.com> (raw)
In-Reply-To: <20230724022142.6425-1-piliu@redhat.com>
From: Jeremy Linton <jeremy.linton@arm.com>
The kernel EFI stub ZBOOT feature creates a PE that
contains a compressed linux kernel image. The stub
when run in a valid UEFI environment then decompresses
the resulting image and executes it.
Support these image formats with kexec as well to avoid
having to keep an alternate kernel image around.
This patch adds a the _probe(), _load() and usage() routines needed for
kexec to understand this format.
Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
[Modified by Pingfan to export kernel fd with load method]
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
---
| 1 +
kexec/arch/arm64/kexec-vmlinuz-arm64.c | 110 +++++++++++++++++++++++++
2 files changed, 111 insertions(+)
create mode 100644 kexec/arch/arm64/kexec-vmlinuz-arm64.c
--git a/kexec/arch/arm64/image-header.h b/kexec/arch/arm64/image-header.h
index 158d411..26bb02f 100644
--- a/kexec/arch/arm64/image-header.h
+++ b/kexec/arch/arm64/image-header.h
@@ -37,6 +37,7 @@ struct arm64_image_header {
static const uint8_t arm64_image_magic[4] = {'A', 'R', 'M', 0x64U};
static const uint8_t arm64_image_pe_sig[2] = {'M', 'Z'};
+static const uint8_t arm64_pe_machtype[6] = {'P','E', 0x0, 0x0, 0x64, 0xAA};
static const uint64_t arm64_image_flag_be = (1UL << 0);
static const uint64_t arm64_image_flag_page_size = (3UL << 1);
static const uint64_t arm64_image_flag_placement = (1UL << 3);
diff --git a/kexec/arch/arm64/kexec-vmlinuz-arm64.c b/kexec/arch/arm64/kexec-vmlinuz-arm64.c
new file mode 100644
index 0000000..c0ee47c
--- /dev/null
+++ b/kexec/arch/arm64/kexec-vmlinuz-arm64.c
@@ -0,0 +1,110 @@
+/*
+ * ARM64 PE compressed Image (vmlinuz, ZBOOT) support.
+ *
+ * Several distros use 'make zinstall' rule inside
+ * 'arch/arm64/boot/Makefile' to install the arm64
+ * ZBOOT compressed file inside the boot destination
+ * directory (for e.g. /boot).
+ *
+ * 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.
+ *
+ * Note this, module doesn't provide a _load() function instead
+ * relying on image_arm64_load() to load the resulting decompressed
+ * image.
+ *
+ * So basically the kernel space still gets a decompressed
+ * kernel image to load via kexec-tools.
+ */
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "kexec-arm64.h"
+#include <kexec-pe-zboot.h>
+#include "arch/options.h"
+
+static int kernel_fd = -1;
+
+/* Returns:
+ * -1 : in case of error/invalid format (not a valid PE+compressed ZBOOT format.
+ */
+int pez_arm64_probe(const char *kernel_buf, off_t kernel_size)
+{
+ int ret = -1;
+ const struct arm64_image_header *h;
+ char *buf;
+ off_t buf_sz;
+
+ buf = (char *)kernel_buf;
+ buf_sz = kernel_size;
+ if (!buf)
+ return -1;
+ h = (const struct arm64_image_header *)buf;
+
+ dbgprintf("%s: PROBE.\n", __func__);
+ if (buf_sz < sizeof(struct arm64_image_header)) {
+ dbgprintf("%s: Not large enough to be a PE image.\n", __func__);
+ return -1;
+ }
+ if (!arm64_header_check_pe_sig(h)) {
+ dbgprintf("%s: Not an PE image.\n", __func__);
+ return -1;
+ }
+
+ if (buf_sz < sizeof(struct arm64_image_header) + h->pe_header) {
+ dbgprintf("%s: PE image offset larger than image.\n", __func__);
+ return -1;
+ }
+
+ if (memcmp(&buf[h->pe_header],
+ arm64_pe_machtype, sizeof(arm64_pe_machtype))) {
+ dbgprintf("%s: PE header doesn't match machine type.\n", __func__);
+ return -1;
+ }
+
+ ret = pez_prepare(buf, buf_sz, &kernel_fd);
+
+ if (!ret) {
+ /* validate the arm64 specific header */
+ struct arm64_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 (!arm64_header_check_magic(&hdr_check)) {
+ dbgprintf("%s: Bad arm64 image header.\n", __func__);
+ goto bad_header;
+ }
+ }
+
+ return ret;
+bad_header:
+ close(kernel_fd);
+ free(buf);
+ return -1;
+}
+
+int pez_arm64_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ info->kernel_fd = kernel_fd;
+ return image_arm64_load(argc, argv, buf, len, info);
+}
+
+void pez_arm64_usage(void)
+{
+ printf(
+" An ARM64 vmlinuz, PE image of a compressed, little endian.\n"
+" kernel, built with ZBOOT enabled.\n\n");
+}
--
2.31.1
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
next prev parent reply other threads:[~2023-07-24 2:22 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-24 2:21 [PATCHv6 0/5] arm64: zboot support Pingfan Liu
2023-07-24 2:21 ` [PATCHv6 1/5] kexec/arm64: Simplify the code for zImage Pingfan Liu
2023-07-24 2:21 ` [PATCHv6 2/5] kexec: Introduce a member kernel_fd in kexec_info Pingfan Liu
2023-07-24 2:21 ` [PATCHv6 3/5] kexec/zboot: Add arch independent zboot support Pingfan Liu
2023-08-01 7:00 ` Simon Horman
2023-08-02 9:53 ` Pingfan Liu
2023-08-02 12:16 ` Simon Horman
2023-08-02 12:17 ` Simon Horman
2023-08-02 12:33 ` Simon Horman
2023-08-03 2:37 ` Pingfan Liu
2023-08-03 8:04 ` Simon Horman
2023-07-24 2:21 ` Pingfan Liu [this message]
2023-07-24 2:21 ` [PATCHv6 5/5] 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=20230724022142.6425-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox