YoctoとRAUCでアップデート環境を構築してみる
Yoctoのビルドができるようになったので、RAUCでソフトウェアアップデートが行える環境を構築してみました。
環境の準備
今回はRaspberry Pi 4Bで試してみます。
以下の記事に従ってYoctoのビルド環境を構築してください。
※Ubuntu 22.04の環境では、ファイルの取得で先に進まなくなってしまいました。その場合はDockerを使うのが良いと思います。
ディレクトリ構成は以下のようにしています。
|- poky
|
|- pi-build (build directory)
RAUCのレシピを追加
以下のコマンドを実行し、RAUCに関連するレイヤー、レシピを追加します。
bitbake-layers layerindex-fetch meta-rauc
# pokyディレクトリ以下で実行
git clone https://github.com/rauc/meta-rauc-community.git -b kirkstone
cd pi-build
bitbake-layers add-layer ../meta-rauc-community/meta-rauc-raspberrypi
証明書などの作成
必要なレイヤーを取得、追加出来たらRAUCのバンドル作成に使う証明書などを作成します。
以下のコマンドを実行し、生成します。
# pi-build以下で実行
../meta-rauc-community/create-example-keys.sh
このコマンドを実行するとpi-build以下にexample-caというディレクトリが作成され、ここに必要な署名が作成されます。
$ ls -al ./example-ca/
合計 68
drwxr-xr-x 4 kobayashi kobayashi 4096 3月 19 09:30 .
drwxr-xr-x 8 kobayashi kobayashi 4096 3月 19 11:12 ..
-rw-r--r-- 1 kobayashi kobayashi 4387 3月 19 09:30 ca.cert.pem
-rw-r--r-- 1 kobayashi kobayashi 944 3月 19 09:30 ca.csr.pem
drwxr-xr-x 2 kobayashi kobayashi 4096 3月 19 09:30 certs
-rw-r--r-- 1 kobayashi kobayashi 4370 3月 19 09:30 development-1.cert.pem
-rw-r--r-- 1 kobayashi kobayashi 936 3月 19 09:30 development-1.csr.pem
-rw-r--r-- 1 kobayashi kobayashi 142 3月 19 09:30 index.txt
-rw-r--r-- 1 kobayashi kobayashi 21 3月 19 09:30 index.txt.attr
-rw-r--r-- 1 kobayashi kobayashi 21 3月 19 09:30 index.txt.attr.old
-rw-r--r-- 1 kobayashi kobayashi 74 3月 19 09:30 index.txt.old
-rw-r--r-- 1 kobayashi kobayashi 1731 3月 19 09:30 openssl.cnf
drwxr-xr-x 2 kobayashi kobayashi 4096 3月 19 09:30 private
-rw-r--r-- 1 kobayashi kobayashi 3 3月 19 09:30 serial
-rw-r--r-- 1 kobayashi kobayashi 3 3月 19 09:30 serial.old
設定でこれらの署名を指定する必要があります。
RAUCを使う設定
local.confを修正し、RAUCを使えるようにします。
以下local.confの修正部分を記載します。
# Kernel 6.1系列を使う
PREFERRED_VERSION_linux-raspberrypi = "6.1%"
# UARTを使用し、u-bootを使用する(RAUCでu-bootが必要)
ENABLE_UART = "1"
RPI_USE_U_BOOT = "1"
# systemdを使用する
DISTRO_FEATURES:append = " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_initscripts = ""
# Settings for meta-rauc-raspberry-pi
IMAGE_INSTALL:append = " rauc"
IMAGE_FSTYPES:append = " ext4"
WKS_FILE = "sdimage-dual-raspberrypi.wks.in"
DISTRO_FEATURES:append = " rauc"
# 証明書関連の設定
RAUC_KEY_FILE="/build/poky/pi-build/example-ca/private/development-1.key.pem"
RAUC_CERT_FILE="/build/poky/pi-build/example-ca/development-1.cert.pem"
#RAUC_KEYRING_FILE ?= "ca.cert.pem"
#RAUC_KEYRING_URI ?= "file:///build/poky/pi-build/example-ca/${RAUC_KEYRING_FILE}"
この最初の部分はイメージにRAUCを組み込むための設定で、後の証明書関連の設定がバンドルの署名に使われる証明書関連の設定です。パスなどは自分の環境に合わせて適宜修正します。
※最後の2行のコメント抜けていたので修正しました。
レシピの修正
実際に使用するためにはレシピをいくつか修正しないといけません。
以下に修正する内容をまとめます。
ビルド時に使用する証明書
イメージを作成する際に、meta-rauc-community/meta-rauc-raspberrypi/recipes-core/rauc/files/にある証明書(ca.cert.pem)を使います。先ほど生成したモノとは異なるため、アップデートしようとすると証明書のチェックエラーで停止します。このファイルを先ほど作成した/example-ca/ca.cert.pemを使うようにします。
きちんとレシピファイルで対応するのが良いと思いますが、今回は面倒なのでコピーして使っています。
# pi-build上で実行
cp example-ca/ca.cert.pem ../meta-rauc-community/meta-rauc-raspberrypi/recipes-core/rauc/files
レシピファイルの指定の修正
/meta-rauc-community/meta-rauc-raspberrypi/recipes-core/bundles/update-bundle.bbの最後に署名に使うファイルの指定があります。ここの設定をコメントアウトします。
DESCRIPTION = "RAUC bundle generator"
inherit bundle
RAUC_BUNDLE_COMPATIBLE = "RaspberryPi4"
RAUC_BUNDLE_VERSION = "v20200703"
RAUC_BUNDLE_DESCRIPTION = "RAUC Demo Bundle"
RAUC_BUNDLE_SLOTS = "rootfs"
RAUC_SLOT_rootfs = "core-image-minimal"
RAUC_SLOT_rootfs[fstype] = "ext4"
# 以下2行をコメントアウト
#RAUC_KEY_FILE = "${THISDIR}/files/development-1.key.pem"
#RAUC_CERT_FILE = "${THISDIR}/files/development-1.cert.pem"
イメージのビルド
イメージを作成します。今回はcore-image-minimalを指定してビルドします。
bitbake core-image-minimal
./tmp/deploy/images/raspberrypi4-64/core-image-minimal-raspberrypi4-64.wic.bz2にイメージが作成されるので、これをSDカードに書き込みます。
Updaterの作り方
以下のコマンドでアップデートに使うバンドルを作成します。
bitbake update-bundle
正常に実行されると、./tmp/deploy/images/raspberrypi4-64/update-bundle-raspberrypi4-64.raucbというファイルが作成されます。これをアップデートの際に使用します。
動作確認
起動状態の確認
SDカードから起動したら以下のコマンドでRAUCが正常に動作しているか確認します。
rauc status
実行すると以下のように現在の状況が確認できます。
=== System Info ===
Compatible: RaspberryPi4
Variant:
Booted from: rootfs.0 (A)
=== Bootloader ===
Activated: rootfs.0 (A)
=== Slot States ===
o [rootfs.1] (/dev/mmcblk0p3, ext4, inactive)
bootname: B
boot status: good
x [rootfs.0] (/dev/mmcblk0p2, ext4, booted)
bootname: A
mounted: /
boot status: good
今回の例ではBootloaderは1面を持ち、システム領域はA/Bの2面持っています。A面から起動していることがわかります。
Updateの確認
先ほど作成したupdaterのバンドルを使ってOSをアップデートしてみます。
USBメモリに作成したraucbファイルをコピーし、マウント後にアップデートを行います。
# USBメモリを/mntにマウント
mount /dev/sda /mnt
# アップデートファイルをインストール
rauc install /mnt/rauc install /mnt/update-bundle-raspberrypi4-64.raucb
実行すると以下のようにメッセージが出て今起動している面とは別の面にアップデータがインストールされます。
installing
0% Installing
0% Determining slot states
10% Determining slot states done.
10% Checking bundle
10% Verifying signature
20% Verifying signature done.
20% Checking bundle done.
20% Checking manifest contents
30% Checking manifest contents done.
30% Determining target install group
40% Determining target install group done.
40% Updating slots
40% Checking slot rootfs.1
46% Checking slot rootfs.1 done.
46% Copying image to rootfs.1
47% Copying image to rootfs.1
48% Copying image to rootfs.1
49% Copying image to rootfs.1
50% Copying image to rootfs.1
51% Copying image to rootfs.1
52% Copying image to rootfs.1
.
.
.
81% Copying image to rootfs.1
82% Copying image to rootfs.1
83% Copying image to rootfs.1
84% Copying image to rootfs.1
85% Copying image to rootfs.1
86% Copying image to rootfs.1
87% Copying image to rootfs.1
88% Copying image to rootfs.1
89% Copying image to rootfs.1
90% Copying image to rootfs.1
91% Copying image to rootfs.1
92% Copying image to rootfs.1
93% Copying image to rootfs.1
94% Copying image to rootfs.1
95% Copying image to rootfs.1
96% Copying image to rootfs.1
97% Copying image to rootfs.1
98% Copying image to rootfs.1
99% Copying image to rootfs.1
99% Copying image to rootfs.1 done.
99% Updating slots done.
100% Installing done.
idle
Installing `/mnt/update-bundle-raspberrypi4-64.raucb` succeeded
インストールが終わったらリブートして動作を確認します。
=== System Info ===
Compatible: RaspberryPi4
Variant:
Booted from: rootfs.1 (B)
=== Bootloader ===
Activated: rootfs.1 (B)
=== Slot States ===
x [rootfs.1] (/dev/mmcblk0p3, ext4, booted)
bootname: B
mounted: /
boot status: good
o [rootfs.0] (/dev/mmcblk0p2, ext4, inactive)
bootname: A
boot status: good
正常にアップデートが行われたときはB面から起動しています。
アップデートを行うたびにA/B交互に使われてアップデートを行っていきます。
その他の注意事項
bitbakeで指定するイメージについて
updaterのバンドルを作成するrootfsは、./meta-rauc-community/meta-rauc-raspberrypi/recipes-core/bundles/update-bundle.bbに直接記載されています。ほかのイメージを指定した場合はここを適宜修正する必要があります。
DESCRIPTION = "RAUC bundle generator"
inherit bundle
RAUC_BUNDLE_COMPATIBLE = "RaspberryPi4"
RAUC_BUNDLE_VERSION = "v20200703"
RAUC_BUNDLE_DESCRIPTION = "RAUC Demo Bundle"
RAUC_BUNDLE_SLOTS = "rootfs"
# bitbakeのイメージを変えた場合、ここも合わせて変更する
RAUC_SLOT_rootfs = "core-image-minimal"
RAUC_SLOT_rootfs[fstype] = "ext4"
#RAUC_KEY_FILE = "${THISDIR}/files/development-1.key.pem"
#RAUC_CERT_FILE = "${THISDIR}/files/development-1.cert.pem"
Partitionの構成を変更する
./meta-rauc-community/meta-rauc-raspberrypi/wic/にsdimage-dual-raspberrypi.wks.inという設定ファイルがあります。これを必要に応じて修正します。
デフォルトのパーティション構成はこのようになっています。
パーティション番号 | サイズ | FS形式 | 説明 |
---|---|---|---|
Partition 1 | 130MByte | VFAT | 起動用パーティション |
Partition 2 | (可変) | ext4 | システムパーティション(A面) |
Partition 3 | (可変) | ext4 | システムパーティション(B面) |
Partition 4 | (可変) | Extd | 拡張パーティション |
Partition 5 | 100MByte | ext4 | データパーティション |
Partition 6 | (可変) | ext4 | home用パーティション |
データパーティションにはRAUCの起動情報が保存されています。起動時、/dataに自動でマウントされます。各種情報は/data/central.raucsファイルに保存されます。これを壊さないように管理する必要があります。
これでYocto上でソフトウェアアップデートの環境が構築できました。
次はHqwkbitと組み合わせたアップデータの配布システムを構築してみます。
Discussion