GRUB local boot chainloads the disk's signed loader; image sums
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:
1 parent
a0df7295ea
commit
c494c7b226
3 files changed
+24
-3
No files matched your search
@@ -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
@@ -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 ;).
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user