Perché SWUpdate?
Gli aggiornamenti sul campo sono inevitabili. SWUpdate offre una soluzione robusta e modulare per l'aggiornamento del firmware, dei filesystem root e dei livelli applicativi, il tutto con capacità di rollback integrata.
È open source, ben documentato, e si integra perfettamente con un layout di partizione A/B.
Panoramica dell'architettura
SWUpdate è composto da diversi componenti chiave:
- Demone di aggiornamento (swupdate) - viene eseguito sul dispositivo e applica gli aggiornamenti
- Gestori di aggiornamenti - definiscono cosa aggiornare (rootfs, file, script, ecc.)
- Interfacce client - interfaccia web, API REST, o CLI locale
- sw-description file - definisce la struttura e la logica del pacchetto di aggiornamento
Esempio di flusso di aggiornamento
- Costruisce un pacchetto di aggiornamento (.swu) che contiene:
- Una nuova immagine del filesystem principale
- Il file sw-description file
- Script opzionali (per la personalizzazione o la verifica)
2.swupdate scrive l'aggiornamento sui dispositivi definiti.
- Uno script post-aggiornamento conferma il successo o attiva un rollback, se necessario.
Esempio
In questo esempio, dividiamo un'immagine ufficiale di Raspberry Pi OS Trixie in due file:
- 2025-10-01-raspios-trixie-arm64.boot.vfat
- 2025-10-01-raspios-trixie-arm64.root.ext4
Questi file sono referenziati nel file sw-description per creare il pacchetto .swu:
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"
}
),
}Il seguente script Lua regola gli UUID delle partizioni in cmdline.txt e fstab dopo il flashing:
#!/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.")Utilizzi swugenerator per raggruppare l'aggiornamento:(https://github.com/sbabic/swugenerator).
Applicare l'aggiornamento
Per testare il file .swu generato:
- Avvii la CM5 nel sistema di ripristino.
- Crei un punto di montaggio, ad esempio:
sudo mkdir -p /mnt/update- Montare una condivisione NFS contenente il file di aggiornamento:
sudo mount -t nfs :/path/to/share /mnt/update- Applichi l'aggiornamento:
sudo swupdate -i /mnt/update/update.swuPossibilità di integrazione
Attivazione degli aggiornamenti da un'interfaccia utente locale o da un'API backend
- Firma e verifica gli aggiornamenti per una maggiore sicurezza
- Utilizza SWUpdate’s l'interfaccia web per i test o il debug
- Combinazione con i servizi di systemd per automatizzare il ripristino e i rollback
Perché è adatto a questa pila
Insieme a rpi-image-gen e rpi-sb-provisioner, SWUpdate completa l'immagine:
- Costruisce → rpi-image-gen (creazione dell'immagine)
- Distribuire → rpi-sb-provisioner (Provisioning del dispositivo)
- Mantenere → SWUpdate (aggiornamenti OTA e gestione del ciclo di vita)
Il risultato è una piattaforma embedded flessibile, aperta e manutenibile. Linux flessibile, aperta e manutenibile, che si evolve con il suo prodotto, senza l'onere di Yocto.
Articoli in questa serie
- Building a Production-Ready Linux for Raspberry Pi Compute Module 5
- Dal sistema operativo stock alla piattaforma di produzione
- Customizing Raspberry Pi OS with rpi-image-gen
- Robustezza del sistema - Progettazione di un layout di file system radice A/B
- Provisioning — Automating First Boot with rpi-sb-provisioner
- OTA e ciclo di vita - Aggiornamenti del software con SWUpdate
Fonti
- 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