Skip to main content

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.

GUI del browser web per SWUpdate

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

  1. 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.
  2. 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:

  1. Avvii la CM5 nel sistema di ripristino.
  2. Crei un punto di montaggio, ad esempio:
sudo mkdir -p /mnt/update
  1. Montare una condivisione NFS contenente il file di aggiornamento:
sudo mount -t nfs :/path/to/share /mnt/update
  1. Applichi l'aggiornamento:
sudo swupdate -i /mnt/update/update.swu

Possibilità 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.