OTA 与固件升级

一、OTA 方式

方式 特点
整盘升级 简单、但失败难恢复
A/B 分区 高可靠、可回滚
双系统升级 切换系统启动
软件包升级 OpenWrt/Yocto apt 风格

二、A/B 分区(推荐)

1. 布局

mmcblk0
├── p1: bootloader
├── p2: boot A (kernel + dtb + initramfs)
├── p3: rootfs A
├── p4: boot B
├── p5: rootfs B
└── p6: data (用户数据)

2. 升级流程

1. 下载新镜像到 data 分区
2. 校验签名
3. 写入非活跃分区(B)
4. 标记下次从 B 启动
5. 重启
6. 启动 B,标记 B 为活跃
7. 如果失败,重启回 A

3. U-Boot 控制

# 切换 slot
fw_setenv slot B
# 或
setenv slot B
saveenv

三、SWUpdate

# 安装
sudo apt install swupdate

1. 配置 sw-description

software =
{
    version = "1.0.0";
    hardware-compatibility = [ "1.0" ];

    myboard = {
        stable = {
            copy1 = {
                images = (
                    {
                        filename = "rootfs.ext4.gz";
                        type = "raw";
                        compressed = "zlib";
                        device = "/dev/mmcblk0p3";
                        compressed = "zlib";
                    }
                );
                scripts = (
                    { filename = "switch_slot.sh"; type = "shellscript"; }
                );
            };
        };
    };
}

2. 触发

swupdate -i /tmp/update.swu -e stable,copy1
# 或通过 web、mDNS

四、rauc(推荐)

1. 安装

sudo apt install rauc

2. 配置 /etc/rauc/system.conf

[system]
compatible=myvendor,myboard
bootloader=uboot

[slot.rootfs.0]
device=/dev/mmcblk0p3
type=ext4
bootname=A

[slot.rootfs.1]
device=/dev/mmcblk0p5
type=ext4
bootname=B

[keyring]
path=/etc/rauc/cert/

3. 升级

rauc install /path/to/update.raucb
rauc status
rauc slot set-active B

五、mkimage + U-Boot FIT

1. 创建 ITS(Image Tree Source)

/dts-v1/;
/ {
    description = "MyBoard Firmware";
    #address-cells = <1>;

    images {
        kernel {
            data = /incbin/("zImage");
            type = "kernel";
            arch = "arm";
            os = "linux";
            compression = "gzip";
            load = <0x80008000>;
            entry = <0x80008000>;
            hash {
                algo = "sha256";
            };
        };
        fdt {
            data = /incbin/("myboard.dtb");
            type = "flat_dt";
            arch = "arm";
            compression = "none";
            hash {
                algo = "sha256";
            };
        };
        ramdisk {
            data = /incbin/("rootfs.cpio.gz");
            type = "ramdisk";
            arch = "arm";
            compression = "gzip";
        };
    };
    configurations {
        default = "conf";
        conf {
            kernel = "kernel";
            fdt = "fdt";
            ramdisk = "ramdisk";
            signature {
                algo = "sha256,rsa2048";
                key-name-hint = "dev";
                sign-images = "kernel", "fdt";
            };
        };
    };
};

2. 编译

mkimage -f fit.its fit.itb

3. 启动

bootm ${fit_addr}

六、安全

七、失败恢复