Warum SWUpdate?
Aktualisierungen im Feld sind unvermeidlich. SWUpdate bietet eine robuste, modulare Lösung für die Aktualisierung von Firmware, Root-Dateisystemen und Anwendungsschichten - alles mit eingebauter Rollback-Funktion.
Es ist Open Source, gut dokumentiert und lässt sich nahtlos in ein A/B-Partitionslayout integrieren.
Überblick über die Architektur
SWUpdate besteht aus mehreren Schlüsselkomponenten:
- Update-Daemon (swupdate) - läuft auf dem Gerät und wendet Aktualisierungen an
- Update-Handler - definieren, was aktualisiert werden soll (rootfs, Dateien, Skripte usw.)
- Client-Schnittstellen - Web-Schnittstelle, REST API oder lokale CLI
- sw-description Datei - definiert die Struktur und Logik des Update-Pakets
Beispiel für den Aktualisierungsablauf
- erstellen Sie ein Update-Paket (.swu), das Folgendes enthält:
- Ein neues Root-Dateisystem-Image
- Die sw-description Datei
- Optionale Skripte (zur Anpassung oder Überprüfung)
2.swupdate schreibt die Aktualisierung auf die definierten Geräte.
3 Ein Skript nach der Aktualisierung bestätigt den Erfolg oder löst ggf. einen Rollback aus.
Beispiel
In diesem Beispiel teilen wir ein offizielles Raspberry Pi OS Trixie-Image in zwei Dateien auf:
- 2025-10-01-raspios-trixie-arm64.boot.vfat
- 2025-10-01-raspios-trixie-arm64.root.ext4
Auf diese Dateien wird in der Datei sw-description Datei referenziert, um das .swu-Paket zu erstellen:
software =
{
version = "0.1.0";
description = "Firmware update for XXXXX Project";
hardware-compatibility: [ "1.0", "1.2", "1.3"];
images: (
{
filename = "2025-10-01-raspios-trixie-arm64.boot.vfat";
device = "/dev/mmcblk0p1";
compressed = "zlib";
installed-directly = true;
},
{
filename = "2025-10-01-raspios-trixie-arm64.root.ext4";
device = "/dev/mmcblk0p2";
compressed = "zlib";
installed-directly = true;
}
);
scripts: (
{
type: "lua",
filename: "repair-disk-uuid.lua"
}
),
}Das folgende Lua-Skript passt die Partitions-UUIDs in cmdline.txt und fstab nach dem Flashen an:
#!/usr/bin/lua
-- helper: run shell command and capture output
function run(cmd)
local f = io.popen(cmd)
local out = f:read("*a")
f:close()
return (out:gsub("%s+$", ""))
end
-- detect PARTUUIDs
local root_part = "/dev/mmcblk0p2"
local boot_part = "/dev/mmcblk0p1"
local root_uuid = run("blkid -s PARTUUID -o value " .. root_part)
local boot_uuid = run("blkid -s PARTUUID -o value " .. boot_part)
print("Rootfs PARTUUID: " .. root_uuid)
print("Boot PARTUUID: " .. boot_uuid)
-- mount points
os.execute("mkdir -p /mnt/root /mnt/boot")
os.execute("mount " .. root_part .. " /mnt/root")
os.execute("mount " .. boot_part .. " /mnt/boot")
-- update cmdline.txt
local cmdline_path = "/mnt/boot/cmdline.txt"
local file = io.open(cmdline_path, "r")
local text = file:read("*a")
file:close()
text = text:gsub("root=PARTUUID=[^ ]+", "root=PARTUUID=" .. root_uuid)
file = io.open(cmdline_path, "w")
file:write(text)
file:close()
-- update /etc/fstab
local fstab_path = "/mnt/root/etc/fstab"
local fstab = io.open(fstab_path, "r")
local content = fstab:read("*a")
fstab:close()
-- replace root line
content = content:gsub("PARTUUID=[^%s]+%s+/%s", "PARTUUID=" .. root_uuid .. " /")
-- replace boot line (/boot or /boot/firmware)
content = content:gsub("PARTUUID=[^%s]+%s+/boot", "PARTUUID=" .. boot_uuid .. " /boot")
fstab = io.open(fstab_path, "w")
fstab:write(content)
fstab:close()
os.execute("sync")
os.execute("umount /mnt/boot")
os.execute("umount /mnt/root")
print("All PARTUUIDs updated successfully.")Verwenden Sie swugenerator um das Update zu bündeln:(https://github.com/sbabic/swugenerator).
Das Update anwenden
So testen Sie die erzeugte .swu-Datei:
- booten Sie den CM5 in das Rettungssystem.
- erstellen Sie einen Einhängepunkt, zum Beispiel:
sudo mkdir -p /mnt/update- hängen Sie eine NFS-Freigabe ein, die die Update-Datei enthält:
sudo mount -t nfs :/path/to/share /mnt/update- wenden Sie das Update an:
sudo swupdate -i /mnt/update/update.swuMöglichkeiten der Integration
Auslösen von Updates über eine lokale Benutzeroberfläche oder eine Backend-API
- Signieren und verifizieren Sie Updates für mehr Sicherheit
- Verwenden Sie SWUpdate’s Webinterface zum Testen oder Debuggen
- Kombinieren Sie mit systemd Services, um Wiederherstellung und Rollbacks zu automatisieren
Warum es in diesen Stapel passt
Zusammen mit rpi-image-gen und rpi-sb-provisioner, SWUpdate vervollständigt das Bild:
- Bauen →. rpi-image-gen (Image-Erstellung)
- Bereitstellen →. rpi-sb-provisioner (Gerätebereitstellung)
- Pflegen → (OTA-Updates und Lifecycle-Management) SWUpdate (OTA-Updates und Lebenszyklusverwaltung)
Das Ergebnis ist eine flexible, offene und wartbare Embedded Linux Plattform - eine Plattform, die sich mit Ihrem Produkt weiterentwickelt, ohne den Overhead von Yocto.
Artikel in dieser Serie
- Building a Production-Ready Linux for Raspberry Pi Compute Module 5
- Vom Stock OS zur Produktionsplattform
- Customizing Raspberry Pi OS with rpi-image-gen
- Systemrobustheit - Entwurf eines A/B Root-Dateisystem-Layouts
- Provisioning — Automating First Boot with rpi-sb-provisioner
- OTA und Lebenszyklus - Software-Updates mit SWUpdate
Quellen
- rpi-image-gen: https://github.com/raspberrypi/rpi-image-gen
- rpi-sb-provisioner: https://github.com/raspberrypi/rpi-sb-provisioner
- SWUpdate: https://github.com/sbabic/swupdate
- swugenerator: https://github.com/sbabic/swugenerator