@@ -122,6 +122,97 @@ menu, system info, power off.
122122
123123---
124124
125+ ## Stage 2b: USB ISO Boot (` kexec-iso-init.sh ` )
126+
127+ When booting from an ISO file on USB media, ` kexec-iso-init.sh ` handles the ISO
128+ boot flow. It is invoked from the "USB ISO Boot" option in the main menu.
129+
130+ ### Flow
131+
132+ 1 . ** Signature verification** : Check for ` .sig ` or ` .asc ` detached signature
133+ 2 . ** Mount ISO** : Mount the ISO file as loopback device at ` /boot `
134+ 3 . ** Layer 1 — initramfs fs compatibility check** (` check_initrd_fs_compat ` ):
135+ Before presenting boot options, verify the ISO's initramfs contains kernel
136+ modules for the USB partition's filesystem (ext4/vfat/exfat). If the initrd
137+ can't read the USB filesystem, the kernel won't find the ISO after kexec.
138+ - Parsing boot configs for initrd paths (instead of searching the whole ISO)
139+ - Unpacking each initrd and checking for required ` .ko ` files and
140+ ` modules.builtin `
141+ - Each initrd gets its own independent ` [OK] ` / ` [!] ` / (blank) marker in
142+ ` /tmp/kexec_initrd_compat.txt ` (the per-initrd flag ` initrd_supports_fs ` is tracked
143+ separately from the global ` any_supported ` flag, so no initrd is silently
144+ skipped)
145+ - ` [OK] ` = initrd has the needed module as ` .ko ` , has it in
146+ ` modules.builtin ` , or has no ` .ko ` files at all (minimal initrd with
147+ everything built into the kernel — nothing to check against).
148+ - ` [!] ` = initrd has loadable kernel modules but none for the USB
149+ filesystem type. No built-in assumption — we report what we find.
150+ - Read-only filesystems (iso9660/squashfs/udf) and unmapped fstypes skip
151+ - All initrds are checked (no early break) so the compat file is complete.
152+ 4 . ** Layer 2 — loopback.cfg fast path** : If the ISO has a ` loopback.cfg ` , parse
153+ it and resolve GRUB variables (` ${iso_path} ` , ` ${isofile} ` ) to extract the
154+ ISO kernel params from loopback entries.
155+ 5 . ** Boot param injection** : When Layer 2 resolves nothing (no GRUB vars found
156+ in loopback.cfg), all common ISO boot methods are injected unconditionally
157+ as kernel ADD params so the ISO initrd can pick whichever it supports:
158+ - ` iso-scan/filename=/$ISO_PATH ` — Ubuntu casper, Fedora dracut
159+ - ` findiso=/$ISO_PATH ` — Debian live-boot, NixOS stage-1
160+ - ` img_dev=/dev/disk/by-uuid/$DEV_UUID ` — block device containing the ISO
161+ - ` img_loop=$ISO_PATH ` — loopback file path (relative)
162+ - ` iso=$DEV_UUID/$ISO_PATH ` — UUID/path alternative
163+ - ` live-media=/dev/disk/by-uuid/$DEV_UUID ` — device filter (casper, live-boot)
164+ The kernel ignores parameters it doesn't understand.
165+ ` fromiso= ` is intentionally not injected because it conflicts with ` findiso= `
166+ in Debian live-boot's ` check_dev() ` — ` fromiso ` mounts the ISO, then ` findiso `
167+ looks for the ISO file inside the mounted ISO (not found), unmounts it,
168+ leaving orphaned loop devices that get re-scanned → infinite loop.
169+ ` findiso= ` alone covers Debian and NixOS.
170+ ` live-media-path= ` is intentionally not injected because the default differs
171+ per distro (` /live ` for Debian, ` /casper ` for Ubuntu/PureOS, ` /LiveOS ` for
172+ Fedora); leaving it unset lets each distro use its own default.
173+ 6 . ** Layer 3 — kexec-select-boot** : Launch the standard boot menu with ` -u `
174+ (unique entries, dedup sorted by name).
175+
176+ ### Initrd compatibility markers in the boot menu
177+
178+ During Layer 1, ` check_initrd_fs_compat ` writes per-initrd results to
179+ ` /tmp/kexec_initrd_compat.txt ` . ` kexec-select-boot ` reads this file and shows
180+ ` [OK] ` or ` [!] ` at the start of each menu line (before the entry name):
181+
182+ | Marker | Meaning | Behavior |
183+ | --------| ---------| ----------|
184+ | ` [OK] ` | Initrd has the USB fs module (as .ko or modules.builtin) | Boot should work |
185+ | ` [!] ` | Initrd has loadable modules but none for the USB fs type | May fail after kexec |
186+ | (blank) | Initrd has zero .ko files — can't verify either way | Assume OK (minimal initrd) |
187+ | (none) | Entry has no initrd (memtest, etc.) | No filesystem dependency |
188+
189+ A ` NOTE ` (3-second sleep, cannot scroll past) is displayed before the menu
190+ explaining the legend. Markers follow ` doc/logging.md ` accessibility rules:
191+ text-based, serial-safe, not color-dependent.
192+
193+ ### Compatibility note for ext4 and vfat
194+
195+ Initrds with no ` .ko ` files at all get no marker at all (blank) — we can't
196+ verify either way, so nothing is displayed.
197+
198+ ### Boot param injection
199+
200+ When Layer 2 (loopback.cfg) resolves no GRUB variables, the following
201+ parameters are injected unconditionally so the ISO initrd can find the USB
202+ partition and the ISO file after kexec, regardless of which distribution's
203+ init system it uses:
204+
205+ | Parameter | Example | Used by |
206+ | -----------| ---------| ---------|
207+ | ` iso-scan/filename= ` | ` /ISOs/foo.iso ` | Ubuntu casper, Fedora dracut |
208+ | ` findiso= ` | ` /ISOs/foo.iso ` | Debian live-boot, NixOS stage-1 |
209+ | ` img_dev= ` | ` /dev/disk/by-uuid/UUID ` | Block device hint |
210+ | ` img_loop= ` | ` ISOs/foo.iso ` | Loopback path |
211+ | ` iso= ` | ` UUID/ISOs/foo.iso ` | Alternative path |
212+ | ` live-media= ` | ` /dev/disk/by-uuid/UUID ` | Device filter (casper, live-boot) |
213+
214+ ---
215+
125216## Stage 3: kexec-select-boot
126217
127218Called from the boot menu. Responsible for final verification and OS handoff.
0 commit comments