From: Alexander Graf <graf@amazon.com>
To: <qemu-devel@nongnu.org>
Cc: <qemu-arm@nongnu.org>, Peter Maydell <peter.maydell@linaro.org>,
"Thomas Huth" <thuth@redhat.com>, <alex.bennee@linaro.org>,
<philmd@linaro.org>, <berrange@redhat.com>,
<marcandre.lureau@redhat.com>, Cornelia Huck <cohuck@redhat.com>,
<mst@redhat.com>, Dorjoy Chowdhury <dorjoychy111@gmail.com>,
Pierrick Bouvier <pierrick.bouvier@linaro.org>,
Paolo Bonzini <pbonzini@redhat.com>,
Tyler Fanelli <tfanelli@redhat.com>, <mknaust@amazon.com>,
<nh-open-source@amazon.com>
Subject: [PATCH 09/10] hw/nitro: Enable direct kernel boot
Date: Wed, 18 Feb 2026 01:51:49 +0000 [thread overview]
Message-ID: <20260218015151.4052-10-graf@amazon.com> (raw)
In-Reply-To: <20260218015151.4052-1-graf@amazon.com>
Nitro Enclaves can only boot EIF files which are a combination of
kernel, initramfs and cmdline in a single file. When the kernel image is
not an EIF, treat it like a kernel image and assemble an EIF image on
the fly. This way, users can call QEMU with a direct
kernel/initrd/cmdline combination and everything "just works".
Signed-off-by: Alexander Graf <graf@amazon.com>
---
hw/core/eif.h | 3 ++
hw/nitro/machine.c | 116 +++++++++++++++++++++++++++++++++++++++++++
hw/nitro/meson.build | 2 +-
3 files changed, 120 insertions(+), 1 deletion(-)
diff --git a/hw/core/eif.h b/hw/core/eif.h
index a3412377a9..0c432dbc2d 100644
--- a/hw/core/eif.h
+++ b/hw/core/eif.h
@@ -12,6 +12,7 @@
#define HW_CORE_EIF_H
#define MAX_SECTIONS 32
+#define EIF_HDR_ARCH_ARM64 0x1
/* members are ordered according to field order in .eif file */
typedef struct EifHeader {
@@ -49,6 +50,8 @@ enum EifSectionTypes {
EIF_SECTION_MAX = 6,
};
+#define EIF_MAGIC { '.', 'e', 'i', 'f' }
+
bool read_eif_file(const char *eif_path, const char *machine_initrd,
char **kernel_path, char **initrd_path,
char **kernel_cmdline, uint8_t *image_sha384,
diff --git a/hw/nitro/machine.c b/hw/nitro/machine.c
index 197adfbdb5..33b0749288 100644
--- a/hw/nitro/machine.c
+++ b/hw/nitro/machine.c
@@ -32,9 +32,104 @@
#include "system/nitro-accel.h"
#include "qemu/accel.h"
#include "hw/arm/machines-qom.h"
+#include "hw/core/eif.h"
+#include <zlib.h> /* for crc32 */
#define EIF_LOAD_ADDR (8 * 1024 * 1024)
+static bool is_eif(char *eif, gsize len)
+{
+ const char eif_magic[] = EIF_MAGIC;
+
+ return len >= sizeof(eif_magic) &&
+ !memcmp(eif, eif_magic, sizeof(eif_magic));
+}
+
+static void build_eif_section(EifHeader *hdr, GByteArray *buf, uint16_t type,
+ const char *data, uint64_t size)
+{
+ uint16_t section = be16_to_cpu(hdr->section_cnt);
+ EifSectionHeader shdr = {
+ .section_type = cpu_to_be16(type),
+ .flags = 0,
+ .section_size = cpu_to_be64(size),
+ };
+
+ hdr->section_offsets[section] = cpu_to_be64(buf->len);
+ hdr->section_sizes[section] = cpu_to_be64(size);
+
+ g_byte_array_append(buf, (const uint8_t *)&shdr, sizeof(shdr));
+ if (size) {
+ g_byte_array_append(buf, (const uint8_t *)data, size);
+ }
+
+ hdr->section_cnt = cpu_to_be16(section + 1);
+}
+
+/*
+ * Nitro Enclaves only support loading EIF files. When the user provides
+ * a Linux kernel, initrd and cmdline, convert them into EIF format.
+ */
+static char *build_eif(const char *kernel_data, gsize kernel_size,
+ const char *initrd_path, const char *cmdline,
+ gsize *out_size, Error **errp)
+{
+ g_autofree char *initrd_data = NULL;
+ static const char metadata[] = "{}";
+ size_t metadata_len = sizeof(metadata) - 1;
+ gsize initrd_size = 0;
+ GByteArray *buf;
+ EifHeader hdr;
+ uint32_t crc = 0;
+ size_t cmdline_len;
+
+ if (initrd_path) {
+ if (!g_file_get_contents(initrd_path, &initrd_data,
+ &initrd_size, NULL)) {
+ error_setg(errp, "Failed to read initrd '%s'", initrd_path);
+ return NULL;
+ }
+ }
+
+ buf = g_byte_array_new();
+
+ cmdline_len = cmdline ? strlen(cmdline) : 0;
+
+ hdr = (EifHeader) {
+ .magic = EIF_MAGIC,
+ .version = cpu_to_be16(4),
+ .flags = cpu_to_be16(target_aarch64() ? EIF_HDR_ARCH_ARM64 : 0),
+ };
+
+ g_byte_array_append(buf, (const uint8_t *)&hdr, sizeof(hdr));
+
+ /* Kernel */
+ build_eif_section(&hdr, buf, EIF_SECTION_KERNEL, kernel_data, kernel_size);
+
+ /* Command line */
+ build_eif_section(&hdr, buf, EIF_SECTION_CMDLINE, cmdline, cmdline_len);
+
+ /* Initramfs */
+ build_eif_section(&hdr, buf, EIF_SECTION_RAMDISK, initrd_data, initrd_size);
+
+ /* Metadata */
+ build_eif_section(&hdr, buf, EIF_SECTION_METADATA, metadata, metadata_len);
+
+ /*
+ * Patch the header into the buffer first (with real section offsets
+ * and sizes), then compute CRC over everything except the CRC field.
+ */
+ memcpy(buf->data, &hdr, sizeof(hdr));
+ crc = crc32(crc, buf->data, offsetof(EifHeader, eif_crc32));
+ crc = crc32(crc, &buf->data[sizeof(hdr)], buf->len - sizeof(hdr));
+
+ /* Finally write the CRC into the in-buffer header */
+ ((EifHeader *)buf->data)->eif_crc32 = cpu_to_be32(crc);
+
+ *out_size = buf->len;
+ return (char *)g_byte_array_free(buf, false);
+}
+
static void nitro_create_cpu(const char *cpu_type, int index)
{
Object *obj = object_new(cpu_type);
@@ -87,6 +182,27 @@ static void nitro_machine_init(MachineState *machine)
error_report("nitro: failed to read EIF '%s'", eif_path);
exit(1);
}
+
+ if (!is_eif(eif_data, eif_size)) {
+ char *kernel_data = eif_data;
+ gsize kernel_size = eif_size;
+ Error *err = NULL;
+
+ /*
+ * The user gave us a non-EIF kernel, likely a Linux kernel image.
+ * Assemble an EIF file from it, the -initrd and the -append arguments,
+ * so that users can perform a natural direct kernel boot.
+ */
+ eif_data = build_eif(kernel_data, kernel_size, machine->initrd_filename,
+ machine->kernel_cmdline, &eif_size, &err);
+ if (!eif_data) {
+ error_report_err(err);
+ exit(1);
+ }
+
+ g_free(kernel_data);
+ }
+
address_space_write(&address_space_memory, EIF_LOAD_ADDR,
MEMTXATTRS_UNSPECIFIED, eif_data, eif_size);
diff --git a/hw/nitro/meson.build b/hw/nitro/meson.build
index 813f5a9c87..7b23f71d5a 100644
--- a/hw/nitro/meson.build
+++ b/hw/nitro/meson.build
@@ -1,3 +1,3 @@
system_ss.add(when: 'CONFIG_NITRO_SERIAL_VSOCK', if_true: files('serial-vsock.c'))
system_ss.add(when: 'CONFIG_NITRO_HEARTBEAT', if_true: files('heartbeat.c'))
-system_ss.add(when: 'CONFIG_NITRO_MACHINE', if_true: files('machine.c'))
+system_ss.add(when: 'CONFIG_NITRO_MACHINE', if_true: [files('machine.c'), zlib])
--
2.47.1
Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christof Hellmis, Andreas Stieger
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597
next prev parent reply other threads:[~2026-02-18 1:54 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-18 1:51 [PATCH 00/10] Native Nitro Enclaves support Alexander Graf
2026-02-18 1:51 ` [PATCH 01/10] scripts/update-linux-headers: Add Nitro Enclaves header Alexander Graf
2026-02-18 1:51 ` [PATCH 02/10] linux-headers: Add nitro_enclaves.h Alexander Graf
2026-02-18 1:51 ` [PATCH 03/10] accel: Add Nitro Enclaves accelerator Alexander Graf
2026-02-24 10:22 ` Paolo Bonzini
2026-02-24 23:16 ` Alexander Graf
2026-02-18 1:51 ` [PATCH 04/10] hw/nitro/nitro-serial-vsock: Nitro Enclaves vsock console Alexander Graf
2026-02-18 1:51 ` [PATCH 05/10] hw/nitro: Introduce Nitro Enclave Heartbeat device Alexander Graf
2026-02-18 1:51 ` [PATCH 06/10] target/arm/cpu64: Allow -host for nitro Alexander Graf
2026-02-18 1:51 ` [PATCH 07/10] hw/nitro: Add nitro machine Alexander Graf
2026-02-18 3:27 ` Mohamed Mediouni
2026-02-18 9:20 ` Alexander Graf
2026-02-20 14:59 ` Michael S. Tsirkin
2026-02-20 15:07 ` Alexander Graf
2026-02-18 1:51 ` [PATCH 08/10] hw/core/eif: Move definitions to header Alexander Graf
2026-02-18 15:12 ` Dorjoy Chowdhury
2026-02-18 1:51 ` Alexander Graf [this message]
2026-02-18 1:51 ` [PATCH 10/10] docs: Add Nitro Enclaves documentation Alexander Graf
2026-02-24 10:26 ` Paolo Bonzini
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=20260218015151.4052-10-graf@amazon.com \
--to=graf@amazon.com \
--cc=alex.bennee@linaro.org \
--cc=berrange@redhat.com \
--cc=cohuck@redhat.com \
--cc=dorjoychy111@gmail.com \
--cc=marcandre.lureau@redhat.com \
--cc=mknaust@amazon.com \
--cc=mst@redhat.com \
--cc=nh-open-source@amazon.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=pierrick.bouvier@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=tfanelli@redhat.com \
--cc=thuth@redhat.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.