GRUB local boot chainloads the disk's signed loader; image sums
CI / go (push) Successful in 45s
CI / agent (push) Successful in 4s
CI / site (push) Successful in 2s

On the Secure Boot lab VM, GRUB's "exit" back to the firmware did not
reach the disk: OVMF went on to its other network boot options and
stopped in its own boot menu. The local-disk entry now finds the
installed OS's signed loader on the EFI partition (shimx64.efi under
EFI/debian, ubuntu, rocky, almalinux, redhat, centos; shim.efi for
SUSE; else EFI/BOOT/BOOTX64.EFI) and chainloads it, as MAAS does.

build-image.sh writes SHA256SUMS next to the image (the old one was
stale after a rebuild; bootstrap.sh --image-url checks it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Ilker ManapandClaude Opus 5.5 committed 2026-10-30 11:28:56 +01:00
1 parent a0df7295ea
commit c494c7b226
3 files changed
+24 -3

No files matched your search

+2
View File
@@ -125,5 +125,7 @@ for f in vmlinuz initrd.img filesystem.squashfs; do
[ -n "$src" ] || { echo "missing $f in binary/live" >&2; exit 1; }
install -m 0644 "$src" "$OUT/$f"
done
# checked by bootstrap.sh --image-url when another region copies this one
(cd "$OUT" && sha256sum vmlinuz initrd.img filesystem.squashfs > SHA256SUMS)
ls -la "$OUT"
echo "=== done $(date)"
+19 -1
View File
@@ -97,7 +97,7 @@ func pxelinuxToGrub(body string) string {
case e.poweroff:
b.WriteString(" halt\n")
case e.local:
b.WriteString(" exit 1\n") // back to the firmware: its next boot option is the disk
b.WriteString(grubLocalBoot)
case e.kernel != "":
fmt.Fprintf(&b, " linux %s", grubQuote("/"+strings.TrimPrefix(e.kernel, "/")))
for _, w := range strings.Fields(e.append) {
@@ -115,6 +115,24 @@ func pxelinuxToGrub(body string) string {
return b.String()
}
// grubLocalBoot starts the installed OS by chainloading its signed loader
// from the disk's EFI partition (shim, which Secure Boot accepts). Handing
// back to the firmware with "exit" is not enough: firmware then tries its
// other network boot options and ends in its own menu (OVMF does).
const grubLocalBoot = ` insmod part_gpt
insmod fat
insmod chain
for f in /EFI/debian/shimx64.efi /EFI/ubuntu/shimx64.efi /EFI/rocky/shimx64.efi /EFI/almalinux/shimx64.efi /EFI/redhat/shimx64.efi /EFI/centos/shimx64.efi /EFI/opensuse/shim.efi /EFI/sles/shim.efi /EFI/BOOT/BOOTX64.EFI; do
if search --no-floppy --set=root --file $f; then
chainloader $f
boot
fi
done
echo "no EFI loader found on the disks"
sleep 10
exit 1
`
var grubPlain = regexp.MustCompile(`^[A-Za-z0-9_./:=,+@%-]+$`)
// grubQuote makes a word safe in GRUB's script language (no $ expansion, no ;).
+3 -2
View File
@@ -15,14 +15,15 @@ func TestPxelinuxToGrub(t *testing.T) {
"menuentry 'Commissioned: power off (default in 15s)' {\n halt\n}",
"menuentry 'Re-run commissioning' {\n linux /rollcall/vmlinuz boot=live components fetch=http://10.213.77.1/rollcall/filesystem.squashfs",
" initrd /rollcall/initrd.img\n",
"menuentry 'Boot from local disk' {\n exit 1\n}",
"menuentry 'Boot from local disk' {\n insmod part_gpt\n",
"chainloader $f",
} {
if !strings.Contains(g, want) {
t.Errorf("missing %q in\n%s", want, g)
}
}
deployed := fmt.Sprintf(deployedTmpl, "now", "m-1", "debian-13", "1", "node01", "debian-13", "m-1", "debian-13", "boot=live")
if g := pxelinuxToGrub(deployed); !strings.Contains(g, "set default=0\n") || !strings.Contains(g, "exit 1") {
if g := pxelinuxToGrub(deployed); !strings.Contains(g, "set default=0\n") || !strings.Contains(g, "/EFI/debian/shimx64.efi") {
t.Errorf("deployed:\n%s", g)
}
// nothing from a cmdline can break out of the menu entry