みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

YoctoProject kirkstoneでリードオンリーのファイルシステム

はじめに

2021-03-25 Yocto リードオンリーなルートファイルシステムを構築するでリードオンリーなシステムの構築方法をまとめたが、情報が古くなってきたのでまとめ直す。

ターゲットボードはラズベリーパイ4、使用するYoctoProjectのバージョンはkirkstone(4.0)とする。

環境構築

作業環境

$ mkdir -p ~/yocto/rpi-kirkstone
$ cd ~/yocto/rpi-kirkstone

pokyの取得

$ git clone -b kirkstone git://git.yoctoproject.org/poky.git

環境変数の設定

$ source poky/oe-init-build-env

レイヤの取得

$ bitbake-layers layerindex-fetch meta-raspberrypi

local.confを編集

conf/local.confに下記の部分を追加

MACHINE = "raspberrypi4-64"
DL_DIR = "${TOPDIR}/../downloads"

# systemd
DISTRO_FEATURES:append = " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_initscripts = ""

# enable uart
ENABLE_UART = "1"

overlayfs.bbclassとoverlayfs-etc.bbclassはinitがsystemdでないと使用できない。

リードオンリーなルートFS

local.confなどのconfファイルで指定する場合は下記のようにする。

EXTRA_IMAGE_FEATURES += "read-only-rootfs"

core-image-minimal.bbappendなどを作成してレシピから指定する場合は下記のようにする。

IMAGE_FEATURES += "read-only-rootfs"

書き込み可能ディレクトリの追加

kirkstoneからoverlayfs.bbclassoverlayfs-etc.bbclassが追加されており、簡単に書き込み可能ディレクトリを定義できるようになっている。

下記の2つで使用するクラスが異なる。

  • /etc以外の任意の場所を書き込み可能にしたい場合
  • /etcを書き込み可能にしたい場合

書き込みパーティションの追加

wksの作成

既存のwksファイルをベースに新しくwksを作成し書き込み可能なパーティションを追加する。

$ bitbake-layers create-layer meta-work
$ bitbake-layers add-layer meta-work
$ mkdir meta-work/wic

meta-work/wic/sdimg-raspberrypi-overlay.wksを次の内容で作成する。

part /boot --source bootimg-partition --ondisk mmcblk0 --fstype=vfat --label boot --active --align 4096 --size 20
part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --label root --align 4096 --size 2048
part /data --ondisk mmcblk0 --fstype=ext4 --label data --fixed-size 20

local.confに下記を追加

WKS_FILE="sdimg-raspberrypi-overlay.wks"

マウントポイントの作成

$ recipetool newappend meta-work core-image-base

作成されたmeta-work/recipes-core/images/core-image-base.bbappendに下記の内容を記述する。

create_data_dir() {
   mkdir -p ${IMAGE_ROOTFS}/data
}

ROOTFS_PREPROCESS_COMMAND += "create_data_dir;"

/etc以外の任意の場所を書き込み可能にしたい場合

overlayfs.bbclassを使用する。

overlayfs使用のためのレシピ

レシピ格納用のディレクトリを作成

$ mkdir meta-work/recipes-example/overlay

meta-work/recipes-example/overlay/overlay-dirs.bbを下記の内容で作成する。

inherit features_check overlayfs

REQUIRED_DISTRO_FEATURES = "systemd overlayfs"

OVERLAYFS_WRITABLE_PATHS[data] += "/home/root"
OVERLAYFS_WRITABLE_PATHS[data] += "/usr/share/my-application"

do_install() {
    install -d ${D}/home/root
    install -d ${D}/usr/share/my-application
}

FILES:${PN} += "/home"
FILES:${PN} += "/usr"

1つのマウントポイントに対して複数のディレクトリ指定できる。

local.confの設定

local.conf に下記の内容を追記する。

DISTRO_FEATURES:append = " overlayfs"

# This has to be done in your machine configuration:
OVERLAYFS_MOUNT_POINT[data] = "/data"
OVERLAYFS_QA_SKIP[data] = "mount-configured"

IMAGE_INSTALL:append = "overlay-dirs"

OVERLAYFS_MOUNT_POINTは本来、MACHINE定義のconfファイルで定義するべきらしい。

マウントポイントのQAチェック(mountユニットとfstabを確認している)はdo_rootfsで実行されるが、 今回ので手順では/dataがマウントポイントであることがfstabに反映されるタイミングがdo_image_wicタスク実行後なので、 OVERLAYFS_QA_SKIPが必要となる。

overlay-dirsパッケージをイメージに追加し、overlayするディレクトリをルートFSに反映する。

データが揮発してもOKな場合

confに下記のように追記して、揮発する領域を指すこともできる。

OVERLAYFS_MOUNT_POINT[var-volatile] = "/var/volatile"

この場合、meta-work/recipes-example/overlay/overlay-dirs.bbを 下記のようにすると保存したデータが電源をオフする毎に消えるようになる。

inherit features_check overlayfs

REQUIRED_DISTRO_FEATURES = "systemd overlayfs"

OVERLAYFS_WRITABLE_PATHS[var-volatile] += "/home/root"
OVERLAYFS_WRITABLE_PATHS[var-volatile] += "/usr/share/my-application"

do_install() {
    install -d ${D}/home/root
    install -d ${D}/usr/share/my-application
}

FILES:${PN} += "/home"
FILES:${PN} += "/usr"

このレシピを変更した場合は下記のように一度cleansstateしないとルートFSに反映されないことがある。。

$ bitbake overlay-dirs -c cleansstate
$ bitbake core-image-base -c cleansstate
$ bitbake core-image-base

/etcを書き込み可能にしたい場合

overlayfs-etc.bbclassを使用する。

overlayfs-etcの使い方

overlayfs-etc.bbclassは直接inheritしてはダメで、イメージレシピの中でIMAGE_FEATURESにoverlayfs-etcを追加する。

具体的には、core-image-minimal.bbappendなどを作成して下記のようにする。

IMAGE_FEATURES += "overlayfs-etc"

local.confなどでEXTRA_IMAGE_FEATURESに追加することもできない。

local.confの設定

これらは本来、MACHINE定義のconfファイルで定義するべきらしい。

OVERLAYFS_ETC_MOUNT_POINT = "/data"
OVERLAYFS_ETC_DEVICE = "/dev/mmcblk0p3"
OVERLAYFS_ETC_FSTYPE = "ext4"

OVERLAYFS_ETC_DEVICEOVERLAYFS_ETC_MOUNT_POINTとしてマウントされる読み書き可能なパーティションを設定する。 今回の手順では、sdimg-raspberrypi-overlay.wksで定義した第3パーティションの情報を設定すればOKとなる。

ちなみに、OVERLAYFS_ETC_MOUNT_POINTとOVERLAYFS_MOUNT_POINTは同じ場所を指しても問題ない。今回はどちらも/dataを指している。

こちらはoverlayfs.bbclassと異なりtmpfsなどの揮発する領域を指すことはできないようだ。

まとめ

kirkstoneからはoverlayfs.bbclass、overlayfs-etc.bbclassが導入された。 どちらもsystemdに依存するため、sysvinitでは使用できない。

使い方については、マニュアルも言葉足らずだし、実例の紹介などが少ないため若干解りづらい気がした。 しかし一度、理解できると柔軟にいろいろなケースで書き込み領域をオーバーレイすることができるため、便利。

組み込み機器では求められがちなリードオンリーなルートFSとは切っても切れないオーバーレイについては、 かなり利便性は向上したのではないだろうか。