はじめに
YoctoProjectではbitbakeで生成された成果物をもとに、SDカードなどに直接書き込むことができるディスクイメージを作成するため、 wicというコマンドを提供している。ヘルプにwicは次のようなものだという記載がある。
The 'wic' command generates partitioned images from existing OpenEmbedded build artifacts.
ここでいうOpenEmbedded build artifacts
とはbitbakeで生成されたもののことで、下記のようなものを指す。
Image generation is driven by partitioning commands contained in an 'Openembedded kickstart' (.wks) file (see 'wic help kickstart')
イメージはwks
ファイルに記述されているパーティション情報に基づいて生成される。
the functionality of those scripts is implemented by a general-purpose partitioning 'language' based on Red Hat kickstart syntax
Red Hat kickstartの構文をベースにしているとのこと。
YoctoProject LICHEE RV DOCKを動かすでwksを調べる必要があったので、この際入門してみる。今回はサンプルとして国内に流通していないであろうLICHEE RV DOCKではなく、Raspberry Pi4を扱う。
meta-raspberrypiとwic
wksファイル
wicコマンドは、パーティション構成が定義されているwksファイルを参照する。meta-raspberrypiにはwic/sdimage-raspberrypi.wks
というwksファイルが含まれている。
sdimage-raspberrypi.wksは次のようになっている。
# short-description: Create Raspberry Pi SD card image # long-description: Creates a partitioned SD card image for use with # Raspberry Pi. Boot files are located in the first vfat partition. 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
このwksからは下記のようなパーティション構成のイメージが作成される。
No | マウントポイント | FSタイプ | ラベル | サイズ | その他 |
---|---|---|---|---|---|
1 | /boot | vfat | boot | 20MiB | active |
2 | / | ext4 | root |
1つ目のパーティションにはactiveの指定がついている。アクティブパーティションによると、この領域からOSが起動される。
wicイメージ
bitbakeを実行するとRaspberry Pi向けのwicイメージが作成されるが、どのようにしてsdimage-raspberrypi.wksが参照されるかを確認する。
$ grep -r 'sdimage-raspberrypi.wks' ./poky/meta-raspberrypi ./conf/machine/include/rpi-base.inc:WKS_FILE ?= "sdimage-raspberrypi.wks"
実装の詳細までは調査していないのだが、IMAGE_FSTYPES
変数にwic
が設定されている場合にdo_image_wicタスクが実行され、
WKS_FILE
変数で指定されたwksファイルがwicコマンドに渡されるという流れになっていると推測される。
meta-raspberrypiのWKS_FILE変数は?=
で代入されているためlocal.confで上書き可能となっている。
WKS_FILEに指定されるwksファイルは、レイヤのwicディレクトリに配置されることを期待している。
meta-raspberrypiの場合はsdimage-raspberrypi.wks
はmeta-raspberrypi/wic
に配置されている。
これらのことから自前のwksを適用するためには、下記の手順が必要になることがわかる。
wicコマンドの実行
bitbakeと同様にoe-init-build-env
で環境設定を実行することで、wicコマンドを単体で実行することができる。
その場合は、任意のwksファイルを指定することができる。
下記のような内容でtest.wksファイルを作成してみる。
include sdimage-raspberrypi.wks part /opt --ondisk mmcblk0 --fstype=ext4 --label opt --align 4096 --size 512
wksファイルの記述に関しては後述するが、このwksファイルではsdimage-raspberrypi.wksの内容に加え、新たに512MiBのパーティションを作成し、
/opt
にマウントされるようにする。ただしマウントポイントは自動的に作成されないため、予めrootfs上にディレクトリを作成しておく必要がある。
part --fstype=ext4 --label opt --align 4096 --size 512
下記のように実行する。
$ wic create ./test.wks -e core-image-base -o output
wicコマンドはビルド済みの成果物を参照するため、先にbitbakeでイメージをビルドしておく必要がある(この例ではcore-image-base)。
outputディレクトリに下記のものが生成されている。
ファイル | 内容 |
---|---|
debugfs_script | |
fstab | wksの内容を反映するためのfstab |
test-202205280913-mmcblk0.direct | ディスクイメージ |
test-202205280913-mmcblk0.direct.p1 | 第1パーティションのイメージ |
test-202205280913-mmcblk0.direct.p2 | 第2パーティションのイメージ |
test-202205280913-mmcblk0.direct.p3 | 第3パーティションのイメージ |
test-202205280913-mmcblk0.directが生成されたwicイメージで、それ以外のファイルは中間生成物となる。
fstabはルートFSの/etc/fstabと差し替えることで、wksで記述されたパーティション構成をルートFSに反映する。
fstabの差し替えを行いたくない場合には--no-fstab-update
をwicコマンドに渡す。
fstab
wicコマンドで生成されたfstabの内容を見てみる。
# stock fstab - you probably want to override this with a machine specific one /dev/root / auto defaults 1 1 proc /proc proc defaults 0 0 devpts /dev/pts devpts mode=0620,ptmxmode=0666,gid=5 0 0 tmpfs /run tmpfs mode=0755,nodev,nosuid,strictatime 0 0 tmpfs /var/volatile tmpfs defaults 0 0 # uncomment this if your device has a SD/MMC/Transflash slot #/dev/mmcblk0p1 /media/card auto defaults,sync,noauto 0 0 /dev/mmcblk0p1 /boot vfat defaults 0 0 /dev/mmcblk0p3 /opt ext4 defaults 0 0
/dev/root
はカーネルパラメータのroot=
に指定されたものを指す。
ファイルシステム上に/dev/root
存在しない点に注意。
動作モード
wicコマンドには次の2つの動作モードがある。
- Raw mode
- Cooked mode
wicコマンドは内部的に下記のディレクトリを示す変数を参照する。
変数 | ディレクトリの概要 |
---|---|
ROOTFS_DIR | ルートFSを含むディレクトリ(/rootfs) |
BOOTIMG_DIR | ブート関連ファイルを含むディレクトリ(/EFI、/syslinuxなど) |
KERNEL_DIR | カーネルを含むディレクトリ |
NATIVE_SYSROOT | ホスト上で実行するツールを含むディレクトリ |
Raw modeはこれらの変数を全て手動で指定するモードで、自由度が高い代わりに若干手間がかかる。
Cooked modeは-e
で指定したイメージ名から自動的にこれらの変数を設定するモードとなる。
基本的にはCooced modeを使用することになる。
wksファイルの内容
8 OpenEmbedded Kickstart (.wks) Referenceによると、パーティションコマンドは、本家のkickstartが持っている機能のうちの
partition(part)
とbootloaderしか実装されていない。
先述のsdimage-raspberrypi.wksではpartコマンドしか使用されていない。
bootloaderコマンド
あまり使用されないの省略する。
partitionコマンド
実のところ、partitionコマンドの基本的な構文は下記のバリエーションしかない。
part [moutnpoint] partition [mountpoint]
[mountpoint]
は省略可能で/path
の形式以外ではswap
が使用可能。
swapはそのままスワップとして使用される領域となる。
それ以外のオプションについては8.2 Command: part or partitionを参照のこと。
--sourceについて
--sourceオプションは若干特殊となっている。下記の例を取り上げる。
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
これらはパーティションにどのようなファイルを含めるかを指定する。--source rootfs
を指定した場合はそのパーティションにルートFSが含まれる。
--source bootimg-partition
を指定した場合は、IMAGE_BOOT_FILES
変数に指定されたファイルが含まれる。IMAGE_BOOT_FILESにはブートに必要なファイル群が指定される。
このsource
は単なるオプションではなく、実際にはpluginの指定となる。つまり、各パーティションへのコピー処理はpluginとして実装されていることになる。
これらのプラグインはSource pluginと呼ばれ、poky/scripts/lib/wic/plugins/source
に格納されているpythonスクリプトで実装されている。
標準では下記のプラグインが提供されている。
- bootimg-biosplusefi.py
- bootimg-efi.py
- bootimg-partition.py
- bootimg-pcbios.py
- empty.py
- isoimage-isohybrid.py
- rawcopy.py
- rootfs.py
partコマンドで指定可能とされるオプションの一部は、実行されるSource pluginによっては作用しない。例えば--source rawcopy
の場合は対象のパーティションにファイルシステムを作成しないため--fstype
は作用しない。
Source pluginの処理内容はそれぞれソースコードを確認するのが一番確実だと考える。
Sourcde pluginは必要に応じて自分で実装することもできる。その際は自分のレイヤのscripts/lib/wic/plugins/source/
もしくはlib/wic/plugins/source
に配置しておくと、wicコマンドがプラグインとして認識することができる。
Source pluginの実装について
先述の通りSource pluginは必要に応じて自分で実装することができる。
Source pluginの条件は下記の通り。
- SourcePluginクラスのサブクラスとして実装されている
- name変数にユニークな名前が設定されている
まずこの条件を満たせばプラグインとして認識される。
Source pluginはTemplate Methodパターンで実装されているようで、下記のクラスメソッドをサブクラスで一部もしくは全部を実装することで機能を実現する。
メソッド | 機能 |
---|---|
do_configure_partition | ブートローダの設定ファイルの生成など |
do_stage_partition | 通常は空実装 |
do_prepare_partition | パーティションへのファイルのコピー |
do_post_partition | パーティションへの署名など |
do_install_disk | MBRへの書き込みなど |
Source pluginの本体は、コピーを実施するdo_prepare_partition
と言っても過言ではない。
どのSource pluginもdo_prepare_partitionは実装することになる。
それ以外のメソッドはブートローダに関連する処理が多く、ブートローダに関連しない場合は実装されないことがある。
これらのクラスメソッドは下記の順序で呼び出される。
この図ではSource pluginで実装されるメソッドの呼び出し順序のざっくりとしたイメージがつかめれば良い。
Source pluginを実装する
KERNEL_DIRに存在するファイルをパーティションにコピーするだけのSource pluginを実装してみる。 rawcopyとは異なり、指定のファイルをファイルシステム上に単純にコピーする。
書式には下記のようになる。
part barebox --source simplecopy --sourceparams="file=vmlinuz" --ondisk mmcblk --fstype=vfat
--sourceparams
の部分をfiles=
にしてスペース区切りで複数のファイルをコピーすることもできる。
rootfsプラグインをベースにdo_prepare_partition
メソッドのみ実装している。コピー後のファイルのオーナーに整合性を持たせるために、
__get_pseudo
をまるっと借用している。
コメント含めて69行程度でSource pluginが実装できた。
まとめ
wicについて調査した。
wicはRed Hat kickstartをベースにしたwksファイルをもとにパーティション情報を持ったディスクイメージファイルを生成する。 bitbakeで生成されたファイルを扱うことに特化しており、本家のkickstartと比較すると機能は限定的である。
wicはコマンド単体でも実行可能となっており、bitbakeでイメージを生成したあとであれば独自のwksファイルで独自の構成のイメージファイルを生成することも可能となっている。
SourcePluginクラスを継承し、必要なメソッドを実装することで独自のSource pluginを追加することも可能。
wicコマンドのhelpが充実しているので、よく読んでみるといろいろと知らなかった機能が発見できたりする。