From nobody Sat May 30 11:18:26 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=invisiblethingslab.com ARC-Seal: i=1; a=rsa-sha256; t=1779730845; cv=none; d=zohomail.com; s=zohoarc; b=iR/bg3b3rOT2d5L24W2SZfPwQplrNNdVKHBjtK2dVHd2yJCDowpepoN/2GI9NJWzXOtnlHg3gvmbxEpRxt25gqtCVQUraxEcte/A/+gKuZmzp4tEtUl3IqrMXYyQyqX+u/nW+cUVVugXiTeFIz7446Y1DD4I5Exb4u6PTTCIT3I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779730845; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=UN1tCVrzEQOruACyzdmLbvIpTXgXCHXGx+kTPh86tw4=; b=fg+6sLQoJdXdoc+JaNU7D7c8NdHQkgTq/jlZH2fMIM/HxQR6v/sKAalmlRR1yRSfBsRFqcY8Kwb+QbmcoMva2QHdDsyPkIOQIBT//JH///q4yU/+R1ZVWzkOGkFoGGZ2gtH3lv6AY6571G5g14lCFBM/BXt/87wN2dBRgsS/1hA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1779730845785191.4388403958327; Mon, 25 May 2026 10:40:45 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1319382.1587013 (Exim 4.92) (envelope-from ) id 1wRZHe-00020d-PL; Mon, 25 May 2026 17:40:10 +0000 Received: by outflank-mailman (output) from mailman id 1319382.1587013; Mon, 25 May 2026 17:40:10 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wRZHe-00020V-MN; Mon, 25 May 2026 17:40:10 +0000 Received: by outflank-mailman (input) for mailman id 1319382; Mon, 25 May 2026 17:40:09 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wRZHd-00020P-AS for xen-devel@lists.xenproject.org; Mon, 25 May 2026 17:40:09 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wRZHc-0013Iy-Ml for xen-devel@lists.xenproject.org; Mon, 25 May 2026 19:40:08 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a148971-e002-0a2a0a5209dd-0a2a4509abe2-14 for ; Mon, 25 May 2026 19:40:08 +0200 Received: from [103.168.172.156] (helo=fhigh-a5-smtp.messagingengine.com) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.56.1) (envelope-from ) id 6a148976-2497-0a2a45090019-67a8ac9cdfc3-3 for ; Mon, 25 May 2026 19:40:07 +0200 Received: from phl-compute-03.internal (phl-compute-03.internal [10.202.2.43]) by mailfhigh.phl.internal (Postfix) with ESMTP id 6CD6E1400051; Mon, 25 May 2026 13:40:06 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-03.internal (MEProxy); Mon, 25 May 2026 13:40:06 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 25 May 2026 13:40:00 -0400 (EDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=fm3 header.d=invisiblethingslab.com header.i="@invisiblethingslab.com" header.h="Cc:Content-Transfer-Encoding:Content-Type:Date:From:Message-ID:MIME-Version:Subject:To"; dkim=pass header.s=fm3 header.d=messagingengine.com header.i="@messagingengine.com" header.h="Cc:Content-Transfer-Encoding:Content-Type:Date:Feedback-ID:From:Message-ID:MIME-Version:Subject:To:X-ME-Proxy:X-ME-Sender" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:from:from:in-reply-to :message-id:mime-version:reply-to:subject:subject:to:to; s=fm3; t=1779730806; x=1779817206; bh=UN1tCVrzEQOruACyzdmLbvIpTXgXCHXG x+kTPh86tw4=; b=UHiJ+RYRRy1iboOpNy72P7LDLeKbF4h17yI/rCJTDxOEIQd4 fGdUkbAhmzPeWJhXlaROKSe1GnYenNm00LQYwov+eT1z+/KxNlMCsE4U9RnP0R6D +U8SnmPiTPBzNjs9IPSlxE064d/DAYpHPTe3qArkOxkC990niJ+SzTXRp7aNc8un wFGokQwmEIkrIreg4dRIW3zEfQWdwia7bPLrxUGrXlbgjQe1v7WLgBuVI4ul+DU4 yPXsGbmWtW78Ajot4SD+V71nnx2IydoZnPrTYJOrnGZ2ks74AGljTE0r/RoVvPqP wmSxH1tFJQqAOGLkKV4DDO6wXPhjBf5hSZ6zZQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:message-id:mime-version:reply-to:subject :subject:to:to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; t=1779730806; x=1779817206; bh=UN1tCVrzEQOruACyzdmLbvIpTXgX CHXGx+kTPh86tw4=; b=NLEFLWsF9A7x1VxJNam20SycqEhuNDS06p1TX0IF87fl AhIVURoBEfZ2FhP1MGHBY4343ZfKtNJLH5y1ccTsHfxjpjWzy5go4HqiSWT/t28V 2AEQFHtSWmi+3WRwXVunS8vZSrmMgihjvI6zWWhM7+fR3Oe7zEyRPPeNvCSe28m8 4AcHNhZyMsxQ0YBjQnpGPJvprNp193oeeKwKUxXZZ4gd3NBxmLhPOmoX+lw/e/S8 BVG1HNr3FbdCFqucMmU7WzpnHKif4ntYSvNivfeuxK6zvkTz176M64l+clBVQL+N Mcfqt6sNY1t8/WsOXO4qsXF5e5Dk1yq3qf0hRB0+ng== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTGcyCBBM2XUZnPN6jxXYmxu2ix4ilCgvL7cY711i5OPMy4ilzn99AAg3v5bo+w4Yx lclcjZT4HfHWfDkMN4mlfdSd6nGkxkLfFqkUOzhyzXBCTnpvYzX+fYd5Oc+3oa7cHx4oF8 xY1xxCA/j23VMy2LLxhI++RbbspWc1BkzRtwyk7laL6cUpbUl03ZzLDts4RtLMdZyVFRCP rpdY0b5S5U2QuBkyfYbniwu3G5i4gQOG2lTlIkdOSYSgg2yaaLcaByIvEaFzVzdy+TC1bJ hHohUprD21FCeN0UWXTPmkqGZOlcjGRWE50DEorRrr8z/X3kVCXCoZ3fMgMxi/x4TSGqAh s/qIrmXGeUJ9dTkLXX81UgS1cRO3rc5L5UpxlS7ru3JwLQeQHQbGY080QLIvlobyt/p+re g5R1emiRC0XF/i/kAbqL/3r7V1KVXPZKqXlkH3ZYR2uZo69n/l3e7wGQnsPVyZBI9dRPdW 2MoT8w+2o2Qc1LJAYDR0sFHSaHnLPFsZ7us4zKss/s9k5UheVhPuSFnxYC6TdkjuVjJut/ ht5mcyNUAQV19DOdyz1hQbR/DFKdg4W2FVRuizFgsx6RzVB42gMbsiKsJW8LHZUAEfLV2y DmU/kD0wGi/aNhJycs7aZNoTR6yW31tXA3WpHgZ8YnHU1vL/a92j1mq4m1mw X-ME-Proxy: Feedback-ID: i792e4853:Fastmail From: =?UTF-8?q?Szymon=20Aceda=C5=84ski?= To: xen-devel@lists.xenproject.org Cc: oleksii.kurochko@gmail.com, =?UTF-8?q?Szymon=20Aceda=C5=84ski?= , Andrew Cooper , =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , "Daniel P. Smith" , Jan Beulich , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie Subject: [PATCH v3 for-4.22] EFI: Fix boot from a device without a file system Date: Mon, 25 May 2026 19:37:03 +0200 Message-ID: <79d8684ede3bf1e9abe02a2e5ed966a0ecd5949d.1779726979.git.accek@invisiblethingslab.com> X-Mailer: git-send-email 2.53.0 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-bad1c0/1779730808-8A38AA53-637CA9B5/0/0 X-purgate-type: clean X-purgate-size: 10700 X-ZohoMail-DKIM: pass (identity @invisiblethingslab.com) X-ZM-MESSAGEID: 1779730848973154100 When netbooting a unified Xen kernel image (via GRUB chainloader), the resulting loaded_image->DeviceHandle does not support SIMPLE_FILE_SYSTEM_PROTOCOL. Instead of crashing via noreturn PrintErrMesg() in get_parent_handle(), we defer calling this function until filesystem access is needed. This way when booting UKI, get_parent_handle() is not called at all. Suggested-by: Andrew Cooper Suggested-by: Marek Marczykowski-G=C3=B3recki Signed-off-by: Szymon Aceda=C5=84ski Acked-by: Marek Marczykowski-G=C3=B3recki --- Changes in v3: - read_file(): replaced unreachable `if ( !dir_handle )` branch with BUG_ON(!dir_handle), per Marek's suggestion. Changes in v2: - Restructured along the lines Andrew and Marek both suggested on v1: defer get_parent_handle() until the first call site that actually needs a file. This mirrors the existing lazy pattern in ARM's allocate_module_file() in xen/arch/arm/efi/efi-boot.h, which was also changed to use the new ensure_dir_handle() helper. Tested (same as v2): - PXE-loaded GRUB chainloading UKI - failure without patch, success with patch - QEMU boot from EFI partition, with config, kernel and initrd on EFI partition too - success with and without patch - Cross-compiling ARM64 - success xen/arch/arm/efi/efi-boot.h | 12 ++++--- xen/arch/x86/efi/efi-boot.h | 9 +++-- xen/common/efi/boot.c | 66 +++++++++++++++++++++++-------------- 3 files changed, 54 insertions(+), 33 deletions(-) diff --git a/xen/arch/arm/efi/efi-boot.h b/xen/arch/arm/efi/efi-boot.h index ea59de47e7..069cc68b0a 100644 --- a/xen/arch/arm/efi/efi-boot.h +++ b/xen/arch/arm/efi/efi-boot.h @@ -403,7 +403,7 @@ static void __init noreturn efi_arch_post_exit_boot(voi= d) } =20 static void __init efi_arch_cfg_file_early(const EFI_LOADED_IMAGE *image, - EFI_FILE_HANDLE dir_handle, + EFI_FILE_HANDLE *dir_handle, const char *section) { union string name; @@ -419,8 +419,11 @@ static void __init efi_arch_cfg_file_early(const EFI_L= OADED_IMAGE *image, name.s =3D get_value(&cfg, section, "dtb"); if ( name.s ) { + CHAR16 *fname; + split_string(name.s); - read_file(dir_handle, s2w(&name), &dtbfile, NULL); + ensure_dir_handle(image, dir_handle, &fname); + read_file(*dir_handle, s2w(&name), &dtbfile, NULL); efi_bs->FreePool(name.w); } } @@ -430,7 +433,7 @@ static void __init efi_arch_cfg_file_early(const EFI_LO= ADED_IMAGE *image, } =20 static void __init efi_arch_cfg_file_late(const EFI_LOADED_IMAGE *image, - EFI_FILE_HANDLE dir_handle, + EFI_FILE_HANDLE *dir_handle, const char *section) { } @@ -665,8 +668,7 @@ static int __init allocate_module_file(const EFI_LOADED= _IMAGE *loaded_image, file_info->name_len =3D name_len; =20 /* Get the file system interface. */ - if ( !*dir_handle ) - *dir_handle =3D get_parent_handle(loaded_image, &fname); + ensure_dir_handle(loaded_image, dir_handle, &fname); =20 /* Load the binary in memory */ read_file(*dir_handle, s2w(&module_name), &module_binary, NULL); diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h index 42a2c46b5e..d738b839ee 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -284,13 +284,13 @@ static void __init noreturn efi_arch_post_exit_boot(v= oid) } =20 static void __init efi_arch_cfg_file_early(const EFI_LOADED_IMAGE *image, - EFI_FILE_HANDLE dir_handle, + EFI_FILE_HANDLE *dir_handle, const char *section) { } =20 static void __init efi_arch_cfg_file_late(const EFI_LOADED_IMAGE *image, - EFI_FILE_HANDLE dir_handle, + EFI_FILE_HANDLE *dir_handle, const char *section) { union string name; @@ -304,9 +304,12 @@ static void __init efi_arch_cfg_file_late(const EFI_LO= ADED_IMAGE *image, name.s =3D get_value(&cfg, "global", "ucode"); if ( name.s ) { + CHAR16 *fname; + microcode_set_module(mbi.mods_count); split_string(name.s); - read_file(dir_handle, s2w(&name), &ucode, NULL); + ensure_dir_handle(image, dir_handle, &fname); + read_file(*dir_handle, s2w(&name), &ucode, NULL); efi_bs->FreePool(name.w); } } diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 9ea2183c0b..2971ea8696 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -547,6 +547,17 @@ static EFI_FILE_HANDLE __init get_parent_handle(const = EFI_LOADED_IMAGE *loaded_i return dir_handle; } =20 +static void __init ensure_dir_handle(const EFI_LOADED_IMAGE *loaded_image, + EFI_FILE_HANDLE *dir_handle, + CHAR16 **file_name) +{ + if ( *dir_handle ) + return; + *dir_handle =3D get_parent_handle(loaded_image, file_name); + if ( !*dir_handle ) + blexit(L"Cannot load files without a usable file system"); +} + static CHAR16 *__init point_tail(CHAR16 *fn) { CHAR16 *tail =3D NULL; @@ -838,12 +849,11 @@ static bool __init read_file(EFI_FILE_HANDLE dir_hand= le, CHAR16 *name, if ( !name ) PrintErrMesg(L"No filename", EFI_OUT_OF_RESOURCES); =20 + BUG_ON(!dir_handle); + what =3D L"Open"; - if ( dir_handle ) - ret =3D dir_handle->Open(dir_handle, &FileHandle, name, - EFI_FILE_MODE_READ, 0); - else - ret =3D EFI_NOT_FOUND; + ret =3D dir_handle->Open(dir_handle, &FileHandle, name, + EFI_FILE_MODE_READ, 0); if ( file =3D=3D &cfg && ret =3D=3D EFI_NOT_FOUND ) return false; if ( EFI_ERROR(ret) ) @@ -1514,7 +1524,7 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE Imag= eHandle, =20 if ( use_cfg_file ) { - EFI_FILE_HANDLE dir_handle; + EFI_FILE_HANDLE dir_handle =3D NULL; EFI_HANDLE gop_handle; UINTN depth, cols, rows; =20 @@ -1526,31 +1536,33 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE Im= ageHandle, =20 gop =3D efi_get_gop(&gop_handle); =20 - /* Get the file system interface. */ - dir_handle =3D get_parent_handle(loaded_image, &file_name); - /* Read and parse the config file. */ if ( read_section(loaded_image, L"config", &cfg, NULL) ) PrintStr(L"Using builtin config file\r\n"); - else if ( !cfg_file_name && file_name ) + else { - CHAR16 *tail; + ensure_dir_handle(loaded_image, &dir_handle, &file_name); =20 - while ( (tail =3D point_tail(file_name)) !=3D NULL ) + if ( !cfg_file_name ) { - wstrcpy(tail, L".cfg"); - if ( read_file(dir_handle, file_name, &cfg, NULL) ) - break; - *tail =3D 0; + CHAR16 *tail; + + while ( (tail =3D point_tail(file_name)) !=3D NULL ) + { + wstrcpy(tail, L".cfg"); + if ( read_file(dir_handle, file_name, &cfg, NULL) ) + break; + *tail =3D 0; + } + if ( !tail ) + blexit(L"No configuration file found."); + PrintStr(L"Using configuration file '"); + PrintStr(file_name); + PrintStr(L"'\r\n"); } - if ( !tail ) - blexit(L"No configuration file found."); - PrintStr(L"Using configuration file '"); - PrintStr(file_name); - PrintStr(L"'\r\n"); + else if ( !read_file(dir_handle, cfg_file_name, &cfg, NULL) ) + blexit(L"Configuration file not found."); } - else if ( !read_file(dir_handle, cfg_file_name, &cfg, NULL) ) - blexit(L"Configuration file not found."); pre_parse(&cfg); =20 if ( section.w ) @@ -1567,6 +1579,7 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE Imag= eHandle, if ( !name.s ) break; free_cfg(); + ensure_dir_handle(loaded_image, &dir_handle, &file_name); if ( !read_file(dir_handle, s2w(&name), &cfg, NULL) ) { PrintStr(L"Chained configuration file '"); @@ -1578,13 +1591,14 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE Im= ageHandle, efi_bs->FreePool(name.w); } =20 - efi_arch_cfg_file_early(loaded_image, dir_handle, section.s); + efi_arch_cfg_file_early(loaded_image, &dir_handle, section.s); =20 option_str =3D name.s ? split_string(name.s) : NULL; =20 if ( !read_section(loaded_image, L"kernel", &kernel, option_str) && name.s ) { + ensure_dir_handle(loaded_image, &dir_handle, &file_name); read_file(dir_handle, s2w(&name), &kernel, option_str); efi_bs->FreePool(name.w); } @@ -1599,6 +1613,7 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE Imag= eHandle, name.s =3D get_value(&cfg, section.s, "ramdisk"); if ( name.s ) { + ensure_dir_handle(loaded_image, &dir_handle, &file_name); read_file(dir_handle, s2w(&name), &ramdisk, NULL); efi_bs->FreePool(name.w); } @@ -1609,6 +1624,7 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE Imag= eHandle, name.s =3D get_value(&cfg, section.s, "xsm"); if ( name.s ) { + ensure_dir_handle(loaded_image, &dir_handle, &file_name); read_file(dir_handle, s2w(&name), &xsm, NULL); efi_bs->FreePool(name.w); } @@ -1634,7 +1650,7 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE Imag= eHandle, } } =20 - efi_arch_cfg_file_late(loaded_image, dir_handle, section.s); + efi_arch_cfg_file_late(loaded_image, &dir_handle, section.s); =20 free_cfg(); =20 --=20 2.53.0