みつきんのメモ

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

YoctoProject イメージの初回起動時に実行される処理を実装する

はじめに

YoctoProjectでストレージに書き込んだイメージの初回起動時にのみ実行される処理を記述する。

実際にはイメージ作成処理のPostProcessを起動時まで遅延させているだけなのだが、 以前に実装した「YoctoProject 最後のパーティションを目一杯まで広げる」を応用できそうなので試してみる。

# 環境構築

作業環境

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

pokyの取得

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

環境変数の設定

$ source poky/oe-init-build-env

meta-raspberrypiの取得

$ bitbake-layers layerindex-fetch meta-raspberrypi

local.confを編集

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

# systemd
INIT_MANAGER = "systemd"

# enable uart
ENABLE_UART = "1"

レイヤを作成

meta-workを作成

$ bitbake-layers create-layer meta-work
$ rm -rf ./meta-work/recipes-example
$ mkdir -p ./meta-work/recipes-support/repart/files ./meta-work/wic
$ bitbake-layers add-layer ./meta-work

レシピ作成

repart.bb

meta-work/recipes-support/repart/repart.bbを以下の内容で作成する。

SUMMARY = "resize partition for data"
DESCRIPTION = "Recipe for resizin the partition and filesystem"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

REPART_DEV ??= ""
REPART_NO ??= ""
REPART_MOUNTPOINT ??= ""

ALLOW_EMPTY:${PN} = "1"

RDEPENDS:${PN} = "parted"

inherit features_check
REQUIRED_DISTRO_FEATURES += "systemd"

S = "${WORKDIR}"

do_compile[noexec] = "1"

do_install() {
    if [ -z "${REPART_DEV}" ]; then
        bbfatal "REPART_DEV should be set."
    fi
    if [ -z "${REPART_NO}" ]; then
        bbfatal "REPART_NO should be set."
    fi
    if [ -z "${REPART_LABEL}" ]; then
        bbfatal "REPART_LABEL should be set."
    fi
    if [ -z "${REPART_MOUNTPOINT}" ]; then
        bbfatal "REPART_MOUNTPOINT should be set."
    fi
}

pkg_postinst_ontarget:${PN}() {
    if [ ! -d "${REPART_MOUNTPOINT}" ]; then
        install -d ${REPART_MOUNTPOINT}
        echo "${REPART_MOUNTPOINT} is created"
    fi
    echo "unmounting ..."
    umount ${REPART_MOUNTPOINT}

    echo "resizing ..."
    /usr/sbin/parted --script ${REPART_DEV} resizepart ${REPART_NO} 100%

    echo "re-mounting ..."
    mount -L ${REPART_LABEL} -o "x-systemd.growfs" ${REPART_MOUNTPOINT}
}

下記の3つの変数は、必要に応じてlocal.confなどで設定する。

REPART_DEV ??= ""
REPART_NO ??= ""
REPART_LABEL ??= ""
REPART_MOUNTPOINT ??= ""

wksファイルを作成

meta-work/wic/sdimage-raspberrypi-growfs.wks.inを下記の内容で作成し、/homeにx-systemd.growfsを指定することにより、システム起動時にパーティションジいっぱいに拡張されるようにする。

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
part ${REPART_MOUNTPOINT} --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home --ondisk mmcblk0 --fstype=ext4 --label ${REPART_LABEL} --align 1024 --size 500 --fsoptions "x-systemd.growfs"

拡張子をwksではなくwks.inとすることで、wksファイルの中でbitbakeの変数を使用することができる。

local.confの修正

local.confに下記を追加する。

# re-partitioning
IMAGE_INSTALL:append = " repart"
REPART_DEV ?= "/dev/mmcblk0"
REPART_NO ?= "3"
REPART_LABEL ?= "homefs"
REPART_MOUNTPOINT ?= "/home"
WKS_FILE = "sdimage-raspberrypi-growfs.wks.in"

今回は下記の4つの変数を設定する様に設計した。REPART_MOUNTPOINTに関しては、wksファイルと連動するようにしたため、 既存のディレクトリであってもこの変数を設定する必要がある。

  • REPART_DEV
  • REPART_NO
  • REPART_LABEL
  • REPART_MOUNTPOINT

動作確認

root@raspberrypi4-64:~# fdisk -l
Disk /dev/mmcblk0: 59 GB, 63831015424 bytes, 124669952 sectors
1947968 cylinders, 4 heads, 16 sectors/track
Units: sectors of 1 * 512 = 512 bytes

Device       Boot StartCHS    EndCHS        StartLBA     EndLBA    Sectors  Size Id Type
/dev/mmcblk0p1 *  64,0,1      1023,3,32         8192     149679     141488 69.0M  c Win95 FAT32 (LBA)
/dev/mmcblk0p2    1023,3,32   1023,3,32       155648     624229     468582  228M 83 Linux
/dev/mmcblk0p3    1023,3,32   1023,7,32       624640  124669951  124045312 59.1G 83 Linux

初回起動時のdmesg

root@raspberrypi4-64:~# dmesg | grep -i filesystem
[    2.808849] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
[    2.819970] VFS: Mounted root (ext4 filesystem) readonly on device 179:2.
[    6.271483] EXT4-fs (mmcblk0p3): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
[    6.384369] EXT4-fs (mmcblk0p3): resizing filesystem from 166400 to 166400 blocks
[    7.207984] EXT4-fs (mmcblk0p3): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
[    7.239674] EXT4-fs (mmcblk0p3): resizing filesystem from 166400 to 15505664 blocks
[    7.860898] EXT4-fs (mmcblk0p3): resized filesystem to 15505664

2回目起動時のdmesg

root@raspberrypi4-64:~# dmesg | grep -i filesystem
[    2.738405] EXT4-fs (mmcblk0p2): INFO: recovery required on readonly filesystem
[    2.951263] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
[    2.961224] VFS: Mounted root (ext4 filesystem) readonly on device 179:2.
[    6.408181] EXT4-fs (mmcblk0p3): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
[    6.454720] EXT4-fs (mmcblk0p3): resizing filesystem from 15505664 to 15505664 blocks

まとめ

イメージ書き込み後初回起動時にのみ実行される処理を実装してみた。 濫用は避けるべきだと思うが、この機能の存在を認識しておくことで、 設計がきれいになることもあると思う。