talos-rpi5/patches/siderolabs/talos/0003-Force-GRUB-bootloader-on-arm64.patch
Mathias Beaulieu-Duncan 4fed64844a
All checks were successful
Build Talos CM5 Image / build (push) Successful in 4m50s
Fix GRUB patch: skip sd-boot probe on arm64 for first upgrade
On fresh SBC images, the EFI partition has sd-boot UKI files but no
GRUB config. During upgrade, Probe() found sd-boot and used it, which
failed because RPi5/CM5 firmware lacks EFI SetVariableRT support.

Add arm64 guard to Probe(): when no GRUB config is found, skip sd-boot
probing and return a fresh GRUB config. This transitions from sd-boot
to GRUB on the first upgrade from a fresh flash.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 13:50:42 -05:00

75 lines
2.7 KiB
Diff

From 1393b3f013e758f6bb52d14006d3a7e7db348930 Mon Sep 17 00:00:00 2001
From: Mathias Beaulieu-Duncan <mathias@svrnty.io>
Date: Fri, 13 Feb 2026 19:08:58 -0500
Subject: [PATCH 3/3] Force GRUB bootloader on arm64
On arm64 platforms like RPi5/CM5, the UEFI firmware (U-Boot) exposes
/sys/firmware/efi but does not support EFI runtime SetVariable. This
causes sd-boot to fail when trying to write EFI variables during
installation/upgrade.
Force GRUB on arm64 in two places:
- NewAuto(): When no existing bootloader is detected, create a GRUB
config instead of sd-boot. This handles fresh installs.
- Probe(): When an existing GRUB config is not found, skip sd-boot
probing and return a fresh GRUB config. This handles the first
upgrade on SBC images that ship with sd-boot UKI files — the
upgrade transitions from sd-boot to GRUB automatically.
Combined with the --no-nvram patch and the SBC EFI-only layout patch,
this enables reliable in-place upgrades via talosctl upgrade on
RPi5/CM5 hardware, including the first upgrade from a fresh flash.
Ref: https://github.com/siderolabs/talos/issues/10859
Ref: https://github.com/talos-rpi5/talos-builder/issues/21
---
.../machined/pkg/runtime/v1alpha1/bootloader/bootloader.go | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/bootloader.go b/internal/app/machined/pkg/runtime/v1alpha1/bootloader/bootloader.go
index f084e09..5c388c1 100644
--- a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/bootloader.go
+++ b/internal/app/machined/pkg/runtime/v1alpha1/bootloader/bootloader.go
@@ -8,6 +8,7 @@ package bootloader
import (
"fmt"
"os"
+ goruntime "runtime"
"github.com/siderolabs/go-blockdevice/v2/block"
"github.com/siderolabs/go-blockdevice/v2/partitioning/gpt"
@@ -56,7 +57,17 @@ func Probe(disk string, options options.ProbeOptions) (Bootloader, error) {
return grubBootloader, nil
}
+ // On arm64, sd-boot requires EFI SetVariable runtime service which is
+ // not available on platforms like RPi5/CM5 (U-Boot). Skip sd-boot
+ // probing and return a fresh GRUB config to transition from sd-boot
+ // to GRUB on the first upgrade.
+ if goruntime.GOARCH == "arm64" {
+ options.Logf("arm64: no GRUB config found, creating new GRUB bootloader (sd-boot not supported)")
+
+ return grub.NewConfig(), nil
+ }
+
sdbootBootloader, err := sdboot.Probe(disk, options)
if err != nil {
return nil, err
@@ -73,6 +84,10 @@ func Probe(disk string, options options.ProbeOptions) (Bootloader, error) {
// NewAuto returns a new bootloader based on auto-detection.
func NewAuto() Bootloader {
+ if goruntime.GOARCH == "arm64" {
+ return grub.NewConfig()
+ }
+
if sdboot.IsUEFIBoot() {
return sdboot.New()
}
--
2.50.1 (Apple Git-155)