Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
3d1ede6
kexec-iso-init: improve hybrid ISO detection and boot param handling
tlaurion Apr 13, 2026
16b9805
kexec-iso-init: resolve GRUB variable references in boot params
tlaurion Apr 13, 2026
c43589f
kexec-boot.sh: add DEBUG traces for cmdline and cmdadd
tlaurion Apr 13, 2026
e46bfe8
kexec-parse-boot: strip unresolved ${iso_path} from GRUB append params
tlaurion Apr 13, 2026
2a4e187
kexec-iso-init: fix hybrid ISO detection (MBR sig at offset 510)
tlaurion Apr 13, 2026
3ed54cb
kexec-iso-init: check both MBR sig and EFI PART magic for hybrid dete…
tlaurion Apr 13, 2026
3fb0108
kexec: fix hybrid ISO detection, strip unresolved vars, add DEBUG traces
tlaurion Apr 13, 2026
390c642
kexec-iso-init: simplify hybrid detection to MBR sig only, add DEBUG …
tlaurion Apr 13, 2026
21bcbfb
kexec-select-boot: revert DEBUG traces that corrupted terminal in raw…
tlaurion Apr 13, 2026
5206592
kexec-parse-boot: revert strip_unresolved_iso_vars
tlaurion Apr 13, 2026
694ad08
kexec-parse-boot: strip unresolved ${iso_path} from GRUB append params
tlaurion Apr 13, 2026
4caa8b1
kexec-iso-init: simplify - remove GRUB config parsing, keep initrd de…
tlaurion Apr 13, 2026
53dd083
kexec-iso-init: add hybrid ISO detection, remove unreliable initrd sc…
tlaurion Apr 13, 2026
55c6952
kexec-iso-init: add initrd boot support detection with GRUB config fa…
tlaurion Apr 13, 2026
662b5ab
fix: extract_boot_params_from_cfg scans *.cfg not just grub.cfg
tlaurion Apr 13, 2026
772d6b2
doc: update boot-process.md with ISO boot knowledge
tlaurion Apr 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions doc/boot-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,99 @@ menu, system info, power off.

---

## Stage 2b: USB ISO Boot (`kexec-iso-init.sh`)

When booting from an ISO file on USB media, `kexec-iso-init.sh` handles:

1. **Signature verification**: Check for `.sig` or `.asc` detached signature
2. **Hybrid detection**: Check MBR signature at offset 510 (0x55AA = hybrid)
3. **Mount ISO**: Mount the ISO file as loopback device
4. **Initrd scanning**: Unpack ISO initrd and scan for filesystem support
(ext4, vfat, exfat modules) and boot method support (iso-scan, findiso,
live-media, boot=live, boot=casper, nixos, anaconda)
5. **Config scanning**: Grep all `*.cfg` files in the mounted ISO for boot
params as a fallback when initrd detection fails (covers GRUB, syslinux,
ISOLINUX configs)
6. **Warning dialog**: If no supported boot method is detected, warn the user
and suggest alternative USB creation methods

### Boot methods

ISOs use different initramfs boot systems. Detection checks for known patterns:

| Boot system | Detection patterns | Notes |
|------------|---------------------|-------|
| Dracut (iso-scan) | `iso-scan/filename=`, `findiso=` | Ubuntu, Debian Live, Tails, PureOS |
| Dracut (live-media) | `live-media=` | Tails |
| Dracut (boot=live) | `boot=live`, `rd.live.image`, `rd.live.squashimg=` | Debian Live, Fedora Workstation, Kicksecure |
| Dracut (casper) | `boot=casper` | Ubuntu, PureOS |
| NixOS | `nixos` | NixOS |
| Anaconda | `inst.stage2=`, `inst.repo=` | Fedora, Qubes OS — requires block device (CD-ROM or dd'd USB) |
| Unknown | (no pattern matched) | May still work — try anyway |

### ISO filesystem support

The ISO initrd must support the USB stick filesystem. Detection unpacks the ISO
initrd and looks for kernel module files (ext4.ko, vfat.ko, exfat.ko) to
determine if the USB fs is supported.

Known supported filesystems: **ext4**, **vfat**, **exfat** (detected in kernel module paths).

### Boot parameter flow

1. `kexec-iso-init.sh` passes standard boot params via kexec:
- `iso-scan/filename=/${ISO_PATH}` — Dracut standard
- `fromiso=`, `img_loop=`, `img_dev=` — additional Dracut variants
2. `kexec-select-boot.sh` parses the ISO's GRUB/syslinux config to build the
boot menu
3. `kexec-parse-boot.sh` strips unresolved `${iso_path}` variables from parsed
entries (prevents malformed params like `iso-scan/filename=` with orphaned paths)
4. `kexec-boot.sh` adds parsed entries and executes kexec

### Known compatible ISOs (tested 2026-04)

| Distribution | MBR | Boot method | Config source | USB FS | Status |
|---|---|---|---|---|---|
| Ubuntu Desktop | hybrid | iso-scan/filename | grub.cfg | ext4/vfat/exfat | works |
| Debian Live kde/xfce | hybrid | boot=live, rd.live.image | grub.cfg | ext4/vfat/exfat | works |
| Tails 7.6 | hybrid | boot=live | grub.cfg | ext4/vfat | works |
| Tails (exfat-support) | hybrid | boot=live | grub.cfg | exfat | works |
| Fedora Workstation Live | hybrid | boot=live, rd.live.image | grub.cfg | ext4/vfat | works |
| NixOS | hybrid | findiso, nixos | grub.cfg | ext4/vfat/exfat | works |
| PureOS | hybrid | boot=casper | grub.cfg | ext4/vfat/exfat | works |
| Kicksecure | hybrid | boot=live, rd.live.image | grub.cfg | ext4/vfat/exfat | works |

### Known limited ISOs

| Distribution | Boot method | Limitation |
|---|---|---|
| Fedora Silverblue | anaconda (inst.stage2=) | Requires block device or matching LABEL. Not USB file boot without extra config. |
| Qubes OS R4.3 | anaconda (inst.repo=hd:LABEL=) | Requires block device or matching LABEL. Installer only. |
| Debian DVD | none (installer) | No live boot params — installer ISO only. Use netinst or dd. |
| TinyCore/CorePlus | unknown (cde, iso=) | Boot method not detected. May work but unverified. |

### On unknown boot methods

If no known boot method is detected, the boot still proceeds with a warning.
Some ISOs use custom boot mechanisms not covered by detection patterns. Examples:

- **TinyCore/CorePlus**: Uses `cde` (from CD) and `iso=` kernel parameter.
The `fromISOfile` script mounts ISO as `/mnt/cdrom`. May work despite
no detection pattern match.

The detection approach is best-effort. Users with unsupported ISOs should:
- Try Ventoy, Rufus, or distribution USB creation tools
- Report to upstream that the ISO should support USB file boot
- Use `dd` to write ISO directly to USB if all else fails

### References

- [GRUB2 loopback ISO boot](https://a1ive.github.io/grub2_loopback.html)
- [Arch Linux ISO Boot](https://wiki.archlinux.org/title/ISO_Spring_(%27Loop%27_device))
- [Debian USB creation](https://wiki.debian.org/DebianInstaller/CreateUSBMedia)

---

## Stage 3: kexec-select-boot

Called from the boot menu. Responsible for final verification and OS handoff.
Expand Down
56 changes: 34 additions & 22 deletions initrd/bin/kexec-boot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ printfiles="n"
printinitrd="n"
while getopts "b:e:r:a:o:fi" arg; do
case $arg in
b) bootdir="$OPTARG" ;;
e) entry="$OPTARG" ;;
r) cmdremove="$OPTARG" ;;
a) cmdadd="$OPTARG" ;;
o) override_initrd="$OPTARG" ;;
f) dryrun="y"; printfiles="y" ;;
i) dryrun="y"; printinitrd="y" ;;
b) bootdir="$OPTARG" ;;
e) entry="$OPTARG" ;;
r) cmdremove="$OPTARG" ;;
a) cmdadd="$OPTARG" ;;
o) override_initrd="$OPTARG" ;;
f)
dryrun="y"
printfiles="y"
;;
i)
dryrun="y"
printinitrd="y"
;;
esac
done

Expand All @@ -27,10 +33,15 @@ fi

bootdir="${bootdir%%/}"

kexectype=`echo $entry | cut -d\| -f2`
kexecparams=`echo $entry | cut -d\| -f3- | tr '|' '\n'`
kexectype=$(echo $entry | cut -d\| -f2)
kexecparams=$(echo $entry | cut -d\| -f3- | tr '|' '\n')
kexeccmd="kexec"

DEBUG "kexec-boot.sh: entry='$entry'"
DEBUG "kexec-boot.sh: kexectype='$kexectype'"
DEBUG "kexec-boot.sh: kexecparams='$kexecparams'"
DEBUG "kexec-boot.sh: cmdadd='$cmdadd'"

cmdadd="$CONFIG_BOOT_KERNEL_ADD $cmdadd"
cmdremove="$CONFIG_BOOT_KERNEL_REMOVE $cmdremove"

Expand All @@ -53,29 +64,31 @@ fix_file_path() {

adjusted_cmd_line="n"
adjust_cmd_line() {
DEBUG "adjust_cmd_line: original cmdline='$cmdline'"
if [ -n "$cmdremove" ]; then
for i in $cmdremove; do
cmdline=$(echo $cmdline | sed "s/\b$i\b//g")
done
fi

if [ -n "$cmdadd" ]; then
DEBUG "adjust_cmd_line: cmdadd='$cmdadd'"
cmdline="$cmdline $cmdadd"
DEBUG "adjust_cmd_line: final cmdline='$cmdline'"
fi
adjusted_cmd_line="y"
}

if [ "$CONFIG_DEBUG_OUTPUT" = "y" ];then
if [ "$CONFIG_DEBUG_OUTPUT" = "y" ]; then
#If expecting debug output, have kexec load (-l) output debug info
kexeccmd="$kexeccmd -d"
fi

module_number="1"
while read line
do
key=`echo $line | cut -d\ -f1`
firstval=`echo $line | cut -d\ -f2`
restval=`echo $line | cut -d\ -f3-`
while read line; do
key=$(echo $line | cut -d\ -f1)
firstval=$(echo $line | cut -d\ -f2)
restval=$(echo $line | cut -d\ -f3-)
if [ "$key" = "kernel" ]; then
fix_file_path
if [ "$kexectype" = "xen" ]; then
Expand Down Expand Up @@ -112,7 +125,7 @@ do
fi
fi
fi
module_number=`expr $module_number + 1`
module_number=$(expr $module_number + 1)
kexeccmd="$kexeccmd --module \"$filepath $cmdline\""
fi
if [ "$key" = "initrd" ]; then
Expand All @@ -135,7 +148,7 @@ do
adjust_cmd_line
kexeccmd="$kexeccmd --append=\"$cmdline\""
fi
done << EOF
done <<EOF
$kexecparams
EOF

Expand All @@ -151,12 +164,11 @@ if [ "$dryrun" = "y" ]; then exit 0; fi

STATUS "Loading the new kernel"
DEBUG "kexec command: $kexeccmd"
# DO_WITH_DEBUG captures the debug output from stderr to the log, we don't need
# it on the console as well
DO_WITH_DEBUG eval "$kexeccmd" 2>/dev/null \
|| DIE "Failed to load the new kernel"
DEBUG "kexec-boot: executing kexec with adjusted_cmd_line=$adjusted_cmd_line kexectype=$kexectype"
DO_WITH_DEBUG eval "$kexeccmd" 2>/dev/null ||
DIE "Failed to load the new kernel"

if [ "$CONFIG_DEBUG_OUTPUT" = "y" ];then
if [ "$CONFIG_DEBUG_OUTPUT" = "y" ]; then
#Ask user if they want to continue booting without echoing back the input (-s)
INPUT "[DEBUG] Continue booting? [Y/n]:" -s -n 1 debug_boot_confirm
if [ "${debug_boot_confirm^^}" = N ]; then
Expand Down
Loading