From patchwork Thu May 7 22:14:51 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 2284 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778192133; bh=f5Zhn5T7WscJESQwlzkUXc2ONDmMo9XoiW03n9/ek2k=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=cq8SGki+GHxTYfQqoVnysPOLJl/rzuTcgtsKtQJgp9+08Jv8FQM8JyK8GL2hOWPzE AJEavZRD+vgVDCO+ynh8BrBtcS+gGW2NCkQ+8g/6TGa6pJGZJdHATZydnTX30Zs9HW LqO3VWcQ629Ytj7JyiyUihGpFlJdw2/ai97fGxv4= Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 18FC36A9B0 for ; Thu, 7 May 2026 16:15:33 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id v8WcdlfkB4-k for ; Thu, 7 May 2026 16:15:33 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778192132; bh=f5Zhn5T7WscJESQwlzkUXc2ONDmMo9XoiW03n9/ek2k=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=WIsvXK9R8a8V2ctm6OgBy+1SkKWc1c8DRe3yEw3/uastEzhr5H+ByLtJV2kCHZjTw PyG7TdCMB9RgwYnyoX2rFWdg4am99CnW+kNB5eyg2n5DNbqPM0OlUcOLLMmFsiEeQ8 3Z+uu7ZhoYsbV87xhrW5EIhiJZ5sy89BghQG09LY= Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 193CE6A9C0 for ; Thu, 7 May 2026 16:15:32 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778192127; bh=DMAnNksjSET8ynUiW2qG70mpOoQMpBfLbhosdFK9rw0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WvpZSeeYUOu/a/xda/Mf8eTYqZEPIB3+SYHTYPyXK+SxmRd4PDmM6T9cgV8/PqBco E49Jt/vM7jPfIa/5bu4LU6/Rbfa+5nxHgS5TDn8edXVV7fYGD7X5XP2kGt23M5YLHt hrnymRq76TK5rhgCZXU4RWrzmUNfXE/JiEE9vH1g= Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id DEBC76A9A9; Thu, 7 May 2026 16:15:27 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id uk6n5K1LfMwh; Thu, 7 May 2026 16:15:27 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778192127; bh=UvzDL0eGB9JbqyJpd7vq6qtN5yv5cVaupZ+gHy+AUJE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ADV+EvrZzNnjT1XYVabN2MmHgmyxOazM2ab/UPu4BN2tikpbloHFkkP3AfTJDwUOu lDN7P7iTs2VueXZldjnqR3wCjf2rIEiK/D91LroGSSxYrFIwv37un4kDHJT8WoEkjf NDpPcYZ51bQi6nCHf3dzLC3lToqzznxa0TNejB9o= Received: from u-boot.org (unknown [174.51.25.52]) by mail.u-boot.org (Postfix) with ESMTPSA id DC3C26A9A5; Thu, 7 May 2026 16:15:26 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Thu, 7 May 2026 16:14:51 -0600 Message-ID: <20260507221507.505998-7-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260507221507.505998-1-sjg@u-boot.org> References: <20260507221507.505998-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 2TVLB523TUC5CFW2KATH24AMH5UMRPS6 X-Message-ID-Hash: 2TVLB523TUC5CFW2KATH24AMH5UMRPS6 X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 06/13] scripts: ubuntu: Install U-Boot on target ESP List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Once subiquity finishes the install it has written shim and GRUB to the target ESP and registered an 'ubuntu' NVRAM entry pointing at /EFI/ubuntu/shimx64.efi. Firmware prefers that entry over the removable-media fallback, so control leaves U-Boot as soon as the install reboots - and once the live ISO is ejected there is no U-Boot on the installed system at all. Plant u-boot.efi at /usr/lib/u-boot/u-boot.efi inside the modified install squashfs so it rides through the install, then copy it onto the target ESP at two locations: - /EFI/BOOT/BOOTX64.EFI - the firmware fallback path - /EFI/ubuntu/shimx64.efi - what the 'ubuntu' NVRAM entry points at Overwriting both means the installed disk boots U-Boot whichever path firmware takes. BLS then picks up /loader/entries/ on the same ESP and the installed kernel/initrd come up without the ISO. The autoinstall late-commands do the copy via 'curtin in-target' so the first reboot after install lands in U-Boot directly. The interactive first-boot unit does the same from the running installed system. Both paths read u-boot.efi from /usr/lib/u-boot/u-boot.efi inside the running install, so refuse --autoinstall when the squashfs is not being modified (--install-squashfs ''); otherwise the late-commands would silently fail to install U-Boot on the target. Signed-off-by: Simon Glass --- doc/usage/os/ubuntu-live.rst | 40 +++++++++++++++++++++++-------- scripts/ubuntu-iso-to-uboot.py | 44 ++++++++++++++++++++++++++++++---- 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/doc/usage/os/ubuntu-live.rst b/doc/usage/os/ubuntu-live.rst index cfcc5243ca2..34d7b0eb71a 100644 --- a/doc/usage/os/ubuntu-live.rst +++ b/doc/usage/os/ubuntu-live.rst @@ -173,22 +173,42 @@ for the installer's kernel: 2. **Interactive path.** The script unpacks the default install squashfs (``casper/minimal.squashfs``), drops in a ``oneshot`` systemd unit plus its - helper script, and repacks. On first boot of the installed system the unit - runs:: - - apt-get update - apt-get install -y systemd-boot-efi - mkdir -p /boot/loader/entries - for k in /usr/lib/modules/*; do - kernel-install add "$(basename "$k")" "$k/vmlinuz" || true - done - touch /var/lib/ubuntu-iso-to-uboot-bls-setup.done + helper script and a copy of ``u-boot.efi`` at ``/usr/lib/u-boot/u-boot.efi``, + and repacks. On first boot of the installed system the unit runs + ``apt install systemd-boot-efi``, back-fills ``/boot/loader/entries/`` via + ``kernel-install``, and installs ``u-boot.efi`` onto the target ESP (see + :ref:`target-uboot-install` below). The unit is gated on ``ConditionPathExists=!/cdrom`` so it stays dormant inside the live session, and the done-file stops it re-running on subsequent boots. It needs a network on first boot for the apt call; if that is not available it fails gracefully and retries on the next boot. +.. _target-uboot-install: + +Installing U-Boot onto the target ESP +------------------------------------- + +Subiquity writes shim and GRUB to the installed ESP and registers an ``ubuntu`` +NVRAM entry pointing at ``/EFI/ubuntu/shimx64.efi``. Without further action, +firmware prefers that entry over the removable-media fallback, so control leaves +U-Boot as soon as the install reboots. + +Both install paths therefore plant ``u-boot.efi`` on the target ESP at two +locations: + +* ``/EFI/BOOT/BOOTX64.EFI`` -- the firmware fallback, picked up when no NVRAM + entry matches (for example after a CMOS reset). +* ``/EFI/ubuntu/shimx64.efi`` -- the file the ``ubuntu`` NVRAM entry points at, + overwritten in place so the entry boots U-Boot rather than chaining through + shim into GRUB. + +The autoinstall path does the copy in its ``late-commands`` via +``curtin in-target``; the interactive first-boot unit does it from the running +installed system. Either way ``u-boot.efi`` travels through the install inside +the modified squashfs at ``/usr/lib/u-boot/u-boot.efi``, so the installed disk +boots U-Boot + BLS on its own once the live ISO has been ejected. + For interactive installs, every subsequent ``apt install linux-image-*`` on the target updates ``/boot/loader/entries/`` automatically via the ``kernel-install`` hooks, and U-Boot's BLS bootmeth keeps picking up the current diff --git a/scripts/ubuntu-iso-to-uboot.py b/scripts/ubuntu-iso-to-uboot.py index c22bd9423f2..c431e15b9ae 100755 --- a/scripts/ubuntu-iso-to-uboot.py +++ b/scripts/ubuntu-iso-to-uboot.py @@ -90,7 +90,8 @@ MIB = 1024 * 1024 # subsequent boot. FIRST_BOOT_SCRIPT = '''\ #!/bin/sh -# Set up BLS entries for future kernel updates +# Set up BLS entries and install U-Boot on the target ESP so the +# installed system boots via U-Boot + BLS without the live ISO set -e apt-get update apt-get install -y systemd-boot-efi @@ -104,6 +105,15 @@ for k in /usr/lib/modules/*; do v=$(basename "$k") kernel-install add "$v" "/boot/vmlinuz-$v" || true done +# Plant u-boot.efi on the installed ESP. BOOTX64.EFI is the firmware +# fallback; shimx64.efi is what the 'ubuntu' NVRAM entry Subiquity +# registers points at, so overwriting both means the disk boots +# U-Boot whichever path the firmware takes. +UBOOT=/usr/lib/u-boot/u-boot.efi +install -D -m 644 "$UBOOT" /boot/efi/EFI/BOOT/BOOTX64.EFI +if [ -f /boot/efi/EFI/ubuntu/shimx64.efi ]; then + install -m 644 "$UBOOT" /boot/efi/EFI/ubuntu/shimx64.efi +fi touch /var/lib/ubuntu-iso-to-uboot-bls-setup.done ''' @@ -265,10 +275,15 @@ def repack_iso( def inject_first_boot_unit( - iso: Path, sqfs_in_iso: str, work: Path, + iso: Path, sqfs_in_iso: str, uboot_efi: Path, work: Path, ) -> Path: """Unpack the install squashfs, drop in a first-boot BLS-setup unit - plus its helper script, and repack. + plus its helper script and a copy of u-boot.efi, and repack. + + u-boot.efi travels through the install at /usr/lib/u-boot/u-boot.efi + so the first-boot unit (and the autoinstall late-commands, which + also run in-target after the squashfs has been unpacked) can copy + it onto the installed ESP. The whole unpack/modify/repack cycle runs under one fakeroot invocation so ownership survives round-tripping through a regular @@ -303,6 +318,8 @@ install -D -m 755 -o root -g root '{script_src}' \\ '{stage}/usr/local/sbin/ubuntu-iso-to-uboot-bls-setup' install -D -m 644 -o root -g root '{unit_src}' \\ '{stage}/etc/systemd/system/ubuntu-iso-to-uboot-bls-setup.service' +install -D -m 644 -o root -g root '{uboot_efi}' \\ + '{stage}/usr/lib/u-boot/u-boot.efi' mkdir -p '{stage}/etc/systemd/system/multi-user.target.wants' ln -sf ../ubuntu-iso-to-uboot-bls-setup.service \\ '{stage}/etc/systemd/system/multi-user.target.wants/ubuntu-iso-to-uboot-bls-setup.service' @@ -411,6 +428,19 @@ options root=UUID=%s ro console=ttyS0,115200 console=tty0\\n"\ if [ -n "$last_v" ]; then\ cp "$ESP/loader/entries/$last_v.conf" "$ESP/loader/entry.conf";\ fi' +''' + # Plant u-boot.efi on the installed ESP in-target, overwriting + # both the fallback BOOTX64.EFI and the shimx64.efi that the + # 'ubuntu' NVRAM entry points at, so the disk boots U-Boot + # whichever path firmware takes - no need to keep the ISO + # attached after the install reboot. + ''' - curtin in-target -- install -D -m 644\ + /usr/lib/u-boot/u-boot.efi /boot/efi/EFI/BOOT/BOOTX64.EFI + - | + curtin in-target -- sh -c '[ -f\ + /boot/efi/EFI/ubuntu/shimx64.efi ] && install -m 644\ + /usr/lib/u-boot/u-boot.efi\ + /boot/efi/EFI/ubuntu/shimx64.efi; true' ''' ) return head + unattended_block + body @@ -473,6 +503,12 @@ def main() -> None: tout.fatal(f'EFI app not found: {args.uboot}') if args.autoinstall and args.no_target_bls: tout.fatal('--autoinstall requires target-BLS wiring; drop -N') + if args.autoinstall and not args.install_squashfs: + tout.fatal( + '--autoinstall needs --install-squashfs; the autoinstall ' + "late-commands copy u-boot.efi from /usr/lib/u-boot/u-boot.efi, " + 'which is only planted when the install squashfs is modified' + ) check_tools() if args.autoinstall and not shutil.which('openssl'): tout.fatal('openssl is required when --autoinstall is set') @@ -532,7 +568,7 @@ def main() -> None: file_maps.append((ai, '/autoinstall.yaml')) if args.install_squashfs: modified_sqfs = inject_first_boot_unit( - args.iso, args.install_squashfs, work, + args.iso, args.install_squashfs, args.uboot, work, ) file_maps.append( (modified_sqfs, '/' + args.install_squashfs.lstrip('/')),