From nobody Sun Apr 12 05:56:32 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@amazon.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=amazon.com ARC-Seal: i=1; a=rsa-sha256; t=1772057401; cv=none; d=zohomail.com; s=zohoarc; b=KbdBvlzEQPIwfZHMEGjdNGw+Lq0yGve20O34JRlZiYxNMre341qJl3a+tF4crfWURKJsbYR8HsS3Fb1wQM3GOiQU4TRtFF4G3Hp53TTQKoAWFJpVyd+RYLZ+x4kx8GBki45mSNTpR0TjHzzK8ALu0Ry30bnz0KdN2s96Fs0PVFM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772057401; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=wiFxVcGuOOQDsn9n6nHZt2xgOoJ7CV0tZ9+LBptze6g=; b=C5yaBSnnTy8R0OlmOtPXeq/N34LbVhzYT7At0O9LuOYlgNBR5/XCT8yVejNU86y7mPZRi+12ylDHU062w/Twc+NvORC9BSAU0CHQu2oIqPyK3sEetPyDaL3j63RWFsyJdMvFWjHP31rvyyzueeOT+SH4zwBYOmqLhZBtTaahBPc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@amazon.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1772057401838398.18258056884156; Wed, 25 Feb 2026 14:10:01 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vvN4s-00015E-18; Wed, 25 Feb 2026 17:09:54 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vvN4q-0000qt-1T; Wed, 25 Feb 2026 17:09:52 -0500 Received: from pdx-out-014.esa.us-west-2.outbound.mail-perimeter.amazon.com ([35.83.148.184]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vvN4o-00014c-2j; Wed, 25 Feb 2026 17:09:51 -0500 Received: from ip-10-5-6-203.us-west-2.compute.internal (HELO smtpout.naws.us-west-2.prod.farcaster.email.amazon.dev) ([10.5.6.203]) by internal-pdx-out-014.esa.us-west-2.outbound.mail-perimeter.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Feb 2026 22:09:44 +0000 Received: from EX19MTAUWC002.ant.amazon.com [205.251.233.111:13586] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.20.255:2525] with esmtp (Farcaster) id 22e5ed5e-59ec-4487-9b37-6a15b68f4db4; Wed, 25 Feb 2026 22:09:44 +0000 (UTC) Received: from EX19D020UWC004.ant.amazon.com (10.13.138.149) by EX19MTAUWC002.ant.amazon.com (10.250.64.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.37; Wed, 25 Feb 2026 22:09:42 +0000 Received: from ip-10-253-83-51.amazon.com (172.19.99.218) by EX19D020UWC004.ant.amazon.com (10.13.138.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.2562.37; Wed, 25 Feb 2026 22:09:39 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazoncorp2; t=1772057390; x=1803593390; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wiFxVcGuOOQDsn9n6nHZt2xgOoJ7CV0tZ9+LBptze6g=; b=R1rWZFdakJ9nvTeJ319QzAfcGPuC3n63wnvnKxbDIm9QnCt/XXKOh7Vz C5+wBaaQQ9nBmMxX0kP8dJWJkzAA6Mjn/29yUqtixfR8DkDHTKEoB6Pt9 HDL22bexXaalYUtiGP2pUB1wI5f+JcWAnOSbwjq6uhNQhAlCGBjHMqcRq WDVttR1Ur9+ikTEtqVVllAksDek6UxIgGHWDpiQ2vkWY00AZt0tJ7VEgn lkVvxO6mKHOl4tRcXPYas1v2xt5PyIIQCXqizQB4oNpw4wgJpfDaV/wdv nqehDpfFoEP3Kl+KsDAKHyfkUCpIbdPIMPsBrSzf7GvhIr0dA2orFDkI8 A==; X-CSE-ConnectionGUID: 5yPtR+GmT0GzJ4s147+ndg== X-CSE-MsgGUID: zEBDlhlrStehLaj4rV0JuQ== X-IronPort-AV: E=Sophos;i="6.21,311,1763424000"; d="scan'208";a="13581633" X-Farcaster-Flow-ID: 22e5ed5e-59ec-4487-9b37-6a15b68f4db4 From: Alexander Graf To: CC: , Peter Maydell , "Thomas Huth" , , , , , Cornelia Huck , , Dorjoy Chowdhury , Pierrick Bouvier , Paolo Bonzini , Tyler Fanelli , , Subject: [PATCH v3 10/11] hw/nitro: Enable direct kernel boot Date: Wed, 25 Feb 2026 22:08:04 +0000 Message-ID: <20260225220807.33092-11-graf@amazon.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20260225220807.33092-1-graf@amazon.com> References: <20260225220807.33092-1-graf@amazon.com> MIME-Version: 1.0 X-Originating-IP: [172.19.99.218] X-ClientProxiedBy: EX19D035UWA003.ant.amazon.com (10.13.139.86) To EX19D020UWC004.ant.amazon.com (10.13.138.149) Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=35.83.148.184; envelope-from=prvs=509822c20=graf@amazon.de; helo=pdx-out-014.esa.us-west-2.outbound.mail-perimeter.amazon.com X-Spam_score_int: -1 X-Spam_score: -0.2 X-Spam_bar: / X-Spam_report: (-0.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.734, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.78, SPF_HELO_NONE=0.001, T_SPF_PERMERROR=0.01, UNPARSEABLE_RELAY=0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @amazon.com) X-ZM-MESSAGEID: 1772057422008158500 Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Dorjoy Chowdhury --- 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 =20 #define MAX_SECTIONS 32 +#define EIF_HDR_ARCH_ARM64 0x1 =20 /* members are ordered according to field order in .eif file */ typedef struct EifHeader { @@ -49,6 +50,8 @@ enum EifSectionTypes { EIF_SECTION_MAX =3D 6, }; =20 +#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 e28c8e9bf5..8849959359 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 /* for crc32 */ =20 #define EIF_LOAD_ADDR (8 * 1024 * 1024) =20 +static bool is_eif(char *eif, gsize len) +{ + const char eif_magic[] =3D EIF_MAGIC; + + return len >=3D sizeof(eif_magic) && + !memcmp(eif, eif_magic, sizeof(eif_magic)); +} + +static void build_eif_section(EifHeader *hdr, GByteArray *buf, uint16_t ty= pe, + const char *data, uint64_t size) +{ + uint16_t section =3D be16_to_cpu(hdr->section_cnt); + EifSectionHeader shdr =3D { + .section_type =3D cpu_to_be16(type), + .flags =3D 0, + .section_size =3D cpu_to_be64(size), + }; + + hdr->section_offsets[section] =3D cpu_to_be64(buf->len); + hdr->section_sizes[section] =3D 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 =3D 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 =3D NULL; + static const char metadata[] =3D "{}"; + size_t metadata_len =3D sizeof(metadata) - 1; + gsize initrd_size =3D 0; + GByteArray *buf; + EifHeader hdr; + uint32_t crc =3D 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 =3D g_byte_array_new(); + + cmdline_len =3D cmdline ? strlen(cmdline) : 0; + + hdr =3D (EifHeader) { + .magic =3D EIF_MAGIC, + .version =3D cpu_to_be16(4), + .flags =3D 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_s= ize); + + /* 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 =3D crc32(crc, buf->data, offsetof(EifHeader, eif_crc32)); + crc =3D crc32(crc, &buf->data[sizeof(hdr)], buf->len - sizeof(hdr)); + + /* Finally write the CRC into the in-buffer header */ + ((EifHeader *)buf->data)->eif_crc32 =3D cpu_to_be32(crc); + + *out_size =3D buf->len; + return (char *)g_byte_array_free(buf, false); +} + static void nitro_machine_init(MachineState *machine) { const char *eif_path =3D machine->kernel_filename; @@ -74,6 +169,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 =3D eif_data; + gsize kernel_size =3D eif_size; + Error *err =3D 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 argum= ents, + * so that users can perform a natural direct kernel boot. + */ + eif_data =3D build_eif(kernel_data, kernel_size, machine->initrd_f= ilename, + 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); =20 diff --git a/hw/nitro/meson.build b/hw/nitro/meson.build index e3f1895890..b9bd0d4300 100644 --- a/hw/nitro/meson.build +++ b/hw/nitro/meson.build @@ -1,4 +1,4 @@ system_ss.add(when: 'CONFIG_NITRO_VSOCK_BUS', if_true: files('nitro-vsock-= bus.c')) system_ss.add(when: 'CONFIG_NITRO_SERIAL_VSOCK', if_true: files('serial-vs= ock.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]) --=20 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