tshell_blog

ソフトウェアと車輪がついた乗り物のはなし

Raspbian buster-liteでCM3+のeMMCをROM化

前回はRaspberry Pi Compute Module 3+(CM3+)にSDカードを増設しました。 tshell.hatenablog.com

産業用途で使う場合であってもなくても,予期しない電源断によってファイルシステムが飛んで二度と起動しなくなるというのは避けたいところです。
CM3+はeMMCからOSが起動するようになっていますが,今回はeMMCをリードオンリーに設定してみます。

環境

  • Raspberry Pi Compute Module 3+
  • Compute Module IO Board v3.0
  • Raspbian Buster-lite

スワップ領域をSDカードに変更する

メモリが1GBもあるのでスワップなしでもよさそうですが一応スワップありの構成で進めます。以降の作業でeMMCへの書き込みがRAMに保持されるようになるのでスワップファイルがデフォルトの/var/swapのままではスワップの意味をなさなくなります。
前回の記事で増設したSDカード上にスワップファイルを作成し,こちらを使用するようにします。

まずはSDカードをフォーマットして,起動時に/mnt/sdcardにマウントされるようにします。

フォーマット

sudo mkfs -t ext4 /dev/mmcblk1

マウントポイントを作成する

sudo mkdir /mnt/sdcard

UUIDを含む行をfstabに追加しておく

sudo bash
lsblk -f | grep mmcblk1 >> /etc/fstab

fstabを編集する

sudo vi /etc/fstab

以下の行を追加する。(あらかじめUUIDを含む行を追加しているのでそのまま利用する。)

UUID=...    /mnt/sdcard ext4    defaults    0   2

再起動して/mnt/sdcardにlost+foundがあることを確認します。

スワップファイルの作成とdphys-swapfileの設定

SDカード上に256MBのスワップファイルを作成します。

sudo dd if=/dev/zero of=/mnt/sdcard/swap/swap bs=1M count=256
sudo chmod 600 /mnt/sdcard/swap/swap
sudo mkswap /mnt/sdcard/swap/swap

作成したスワップファイルが使えるかテストする

sudo swapoff --all
sudo swapon /mnt/sdcard/swap/swap

free -hを実行してswapのサイズが256MBになっていることを確認します。

/etc/dphys-swapfileを以下のようにコメントアウトを解除して編集します。

CONF_SWAPFILE=/mnt/sdcard/swap/swap
CONF_SWAPSIZE=256

再起動後にfree -hを実行し,swapのサイズが256MBであることを確認します。

以上でスワップファイルを増設したSDカードに移すことができました。

fsprotectをインストールする

続いてeMMCをリードオンリー化していきます。
まずはfsprotectをインストールします。

sudo apt-get install fsprotect

aufs-dkmsのセットアップでエラーが出た場合は,以下のようにpsotinstとpreermを削除してから再度セットアップします。

sudo rm /var/lib/dpkg/info/aufs-dkms.postinst
sudo rm /var/lib/dpkg/info/aufs-dkms.prerm
sudo apt-get install fsprotect

initramfsイメージの作成

以降のステップで編集するhook-functionsなどのファイルを生成するため,update-initramfsを実行します。

sudo update-initramfs -c -k `uname -r`

上記を実行すると/usr/share/initramfs-tools/hooks/fsprotectの処理でコケます。
/usr/bin/touchを読みに行くところで失敗しており,/usr/bin/touchは/bin/touchへのシンボリックリンクなので,/usr/share/initramfs-tools/hooks/fsprotectの最終行を以下のように変更します。

copy_exec /bin/touch "/bin"

再度update-initramfsを実行します。

sudo update-initramfs -c -k `uname -r`

hook-functionsの修正

以下のページを参考に,hook-functionsを修正します。
https://www.raspberrypi.org/forums/viewtopic.php?t=161416

/usr/share/initramfs-tools/hook-functionsの524行目付近を以下のように編集します。
(modulesの最後にoverlayを追加する)

for arg in "$@" ; do
        case "$arg" in
        base)
            modules="$modules btrfs ext2 ext3 ext4 ext4dev overlay"

新しいbootスクリプトを作成する

既存のスクリプトをコピーしてoverlayファイルシステムを使用するように変更します。

cd /usr/share/initramfs-tools/scripts
sudo cp local overlay
sudo cp -rp local-premount overlay-premount
sudo cp -rp local-bottom overlay-bottom

/usr/share/initramfs-tools/scripts/overlayのlocal_mount_root()の中を以下のように修正します。
ここに示した行でlocal_mount_root()が終わるようにします。

#   if [ "${readonly}" = "y" ]; then
        roflag=-r
#   else
#       roflag=-w
#   fi

    # FIXME This has no error checking
    modprobe ${FSTYPE}

    checkfs ${ROOT} root

    # FIXME This has no error checking
    # Mount root
    mkdir /upper /lower
    if [ "${FSTYPE}" != "unknown" ]; then
        mount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} /lower
    else
        mount ${roflag} ${ROOTFLAGS} ${ROOT} /lower
    fi
    modprobe overlay
    mount -t tmpfs tmpfs /upper
    mkdir /upper/data /upper/work
    mount -t overlay \
        -olowerdir=/lower,upperdir=/upper/data,workdir=/upper/work \
        overlay ${rootmnt}

initramfsの作成

以下のコマンドを実行し,initramfsを作成してリネームします。

sudo update-initramfs -c -k `uname -r`
sudo mv /boot/initrd.img-4.19.66-v7+ /boot/initrd7.img

/boot/config.txt,/boot/cmdline.txtの編集

/boot/config.txtに以下を追記します。

kernel=kernel7.img
initramfs initrd7.img

/boot/cmdline.txtの先頭にboot=overlayを追加して再起動します。

動作確認

再起動後,mountを実行し,overlay on / type overlayのような行があればルートファイルシステムがoverlay fs でマウントされています。
適当なファイルを作成して,再起動すると消えることを見てみましょう。

参考にしたページはRaspbian Pixelを使っていましたが,Raspbian busterでも以前と同様にして実現できるようです。