Boot fixes: drop the stock BLS entry, define load_video, set kernel cmdline
All checks were successful
build image / build (push) Successful in 23m57s
All checks were successful
build image / build (push) Successful in 23m57s
First boot on the hardware failed, returning to the GRUB menu with:
can't find command 'load_video'
file '/boot/vmlinuz-7.1.5-200.fc44.aarch64' not found
you need to load the kernel first
The title in that message was the tell: "Fedora Linux (7.1.5-...) 44 (Forty
Four)" is Fedora's stock format, not ours. GRUB was booting an entry we did not
write. Confirmed by unpacking the published image and reading the boot
filesystem — /loader/entries held two files, and the one named after the
machine-id sorts before c630-*, so it won.
kernel-install wrote it during the dnf transaction, from inside the install
root where /boot is an ordinary directory rather than a partition. It was wrong
three ways: paths of /boot/vmlinuz-… that resolve nowhere once /boot is its own
filesystem; an empty options line, so no root= and no command line at all; and
no devicetree, so even had it loaded, the kernel would not have known what
machine it was on. Ours, sitting right beside it, was correct throughout.
So: delete any entry we did not write, and define load_video in grub.cfg —
blscfg emits menuentries that call it, and Fedora's generated config defines it
where a hand-written one must too.
Also write /etc/kernel/cmdline. That empty options line was not a build-time
quirk; it is what kernel-install produces when nothing tells it the command
line. The same gap would have bitten on the device at the first
`dnf update kernel`, writing an entry with no root= and no C630 quirks, and the
laptop would not have come back.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWRjNJMistCy6ngXH5aJLS
This commit is contained in:
@@ -245,6 +245,15 @@ UUID=${BOOT_UUID} /boot ext4 defaults 1 2
|
||||
UUID=${ESP_UUID} /boot/efi vfat umask=0077,shortname=winnt 0 2
|
||||
EOF
|
||||
|
||||
# The entry kernel-install wrote during the transaction had an empty options
|
||||
# line, because nothing told it what the command line should be. That same gap
|
||||
# would bite on the device: the first `dnf update kernel` would write an entry
|
||||
# with no root= and no C630 quirks, and the machine would not come back. This is
|
||||
# where kernel-install looks.
|
||||
mkdir -p "$ROOTFS/etc/kernel"
|
||||
printf 'root=UUID=%s ro %s\n' "$ROOT_UUID" "$DEVICE_CMDLINE" \
|
||||
> "$ROOTFS/etc/kernel/cmdline"
|
||||
|
||||
# Empty (not missing) machine-id marks this as a first boot for systemd, which
|
||||
# then generates a unique one per device rather than cloning the builder's.
|
||||
: > "$ROOTFS/etc/machine-id"
|
||||
@@ -290,9 +299,19 @@ chroot "$ROOTFS" dracut --force --no-hostonly --no-hostonly-cmdline \
|
||||
# ---------------------------------------------------------------------------
|
||||
log "Writing bootloader configuration"
|
||||
# ---------------------------------------------------------------------------
|
||||
mkdir -p "$ROOTFS/boot/loader/entries"
|
||||
|
||||
# kernel-install already wrote an entry during the dnf transaction, from inside
|
||||
# the install root — where /boot is an ordinary directory, not a partition. It
|
||||
# is wrong in three ways: its paths are /boot/vmlinuz-… which resolve nowhere
|
||||
# once /boot is a filesystem in its own right; its options line is empty, so no
|
||||
# root= and no command line; and it has no devicetree, so even if it loaded, the
|
||||
# kernel would not know what machine it was on. Being named after the machine-id
|
||||
# it also sorts before ours, so GRUB picks it. Delete anything we did not write.
|
||||
rm -f "$ROOTFS/boot/loader/entries/"*.conf
|
||||
|
||||
# The bootstrap BLS entry. Subsequent kernels get theirs from kernel-install,
|
||||
# with the devicetree line supplied by 95-c630-devicetree.install.
|
||||
mkdir -p "$ROOTFS/boot/loader/entries"
|
||||
cat > "$ROOTFS/boot/loader/entries/c630-${KVER}.conf" <<EOF
|
||||
title Fedora Linux ${FEDORA_RELEASE} (${KVER}) — ${DEVICE_DESC}
|
||||
version ${KVER}
|
||||
@@ -320,6 +339,19 @@ insmod all_video
|
||||
insmod gzio
|
||||
insmod blscfg
|
||||
|
||||
# blscfg turns each BLS entry into a menuentry that calls load_video before
|
||||
# loading the kernel. Fedora's generated grub.cfg defines it; a hand-written one
|
||||
# has to as well, or every entry fails with "can't find command 'load_video'".
|
||||
function load_video {
|
||||
if [ x\$feature_all_video_module = xy ]; then
|
||||
insmod all_video
|
||||
else
|
||||
insmod efi_gop
|
||||
insmod video_bochs
|
||||
insmod video_cirrus
|
||||
fi
|
||||
}
|
||||
|
||||
search --no-floppy --fs-uuid --set=root ${BOOT_UUID}
|
||||
|
||||
if [ -s \$prefix/grubenv ]; then
|
||||
|
||||
Reference in New Issue
Block a user