[[diary/Kojima]]
・P-Plamo の内部構造(その3)
P-Plamo の初期化処理を行う[[init ファイル:ftp://plamo.linet.gr.jp/pub/P-Plamo/initramfs/init]]の
内容を簡単に紹介します.
なお、ここに紹介するのは2009 3/3 版の必要最小限な init で、今後、さまざまな改造を追加していく予定で、
内容は適宜変更されますがあしからず。
実際のファイルには試行錯誤的にやってみた形跡をコメントアウトで多数残していますが,それらは略します.
#/bin/sh
export PATH=/bin:.
mount -t proc proc /proc
mount -t sysfs sys /sys
for i in aufs.ko unlzma.ko sqlzma.ko squashfs.ko ; do
insmod /lib/modules/$i
done
# nls_euc-jp.ko needs vfat.ko
for i in nls_iso8859-1.ko nls_ascii.ko nls_cp932.ko cdrom.ko ide-cd_mod.ko loop.ko sr_mod.ko \
sg.ko fat.ko vfat.ko nls_euc-jp.ko ; do
insmod /lib/modules/$i
done
# this wait is needed for detecting USB CD-ROM via sr_mod.ko
sleep 10
まず,PATH変数を設定してから、proc-fs, sys-fs をマウントしてカーネルの各種機能が利用できるようにします.
次に union mount 用の aufs.ko ドライバモジュール,lzma 圧縮に対応した squash-fs 用の unlzma.ko,
sqlma.ko モジュールをロードし,最後に squashfs.ko モジュールをロードします.squashfs.ko は unlzma.ko
や sqlzma.ko の機能を必要とするので,先に unlama.ko, sqlzma.ko をロードしておかないとエラーになります.
次に iso9660 形式の DVD か VFAT 形式の USB メモリをマウントする際に必要となるモジュール類をロードします.
これらも依存関係があるので,順番を違えるとエラーになってきちんとロードしてくれないので注意してください.
# modprobe を使えば自動的に処理してくれるのですが,わざわざ modules.dep 等を作るほどのこともないと思うので
モジュールドライバをロードすると,それらのドライバによってカーネルが新しく認識できるようになった周辺機器を
チェックするので,そのためにしばらく時間を置きます.
mount_ok=0
# check CD device
for i in hdc hda hdb hdd sr0 sr1 sr2 ; do
echo "trying CD device"
mount -t iso9660 /dev/$i /cdrom -o ro
if [ $? = "0" ]; then
if [ -f /cdrom/isolinux/rootimg.squash ]; then
echo "found cdrom on /dev/$i"
mount_ok=1
break
else
umount /cdrom
fi
fi
done
# check /dev/sdXX for USB CD device
if [ "$mount_ok" == "0" ]; then
partitions=`cat /proc/partitions | cut -b23-28 | grep sd`
for i in $partitions ; do
mount /dev/$i /cdrom
if [ $? = "0" ]; then
if [ -f /cdrom/isolinux/rootimg.squash ]; then
echo "found cdrom on /dev/$i"
mount_ok=1
break
else
umount /cdrom
fi
fi
done
fi
# cannot find any CD device
if [ "$mount_ok" == "0" ]; then
echo "cannot find partition include squashfs. cannot continue booting. exit"
exec /bin/sh
fi
DVD あるいは USB メモリを /cdrom にチェックするためのループです.指定したデバイスが /cdrom にマウントでき,
そこの isolinux ディレクトリに rootimg.squash があるかで正しい DVD かをチェックしています.
最初のループで IDE の hdc, hda, hdb, hdd,SCSI(SATA) の sr0, sr1, sr2 の順に DVD をチェックし,
見つかれば $mount_ok を 1 にして次のループを飛し,見つからなければ次のループで /proc/partitions にある
sd デバイス(USBメモリは sd デバイスとして認識される)を順にマウントして rootimg.squash の有無を調べます.
見つからなければ以後の処理を打ちきって /bin/sh を起動して終了します.
一応,対話的な操作は可能なので busybox の限られたコマンドを使って原因をチェックしてみてください.
# mount squashfs'ed rootfs image into /loop
losetup /dev/loop0 /cdrom/isolinux/rootimg.squash
mount -t squashfs /cdrom/isolinux/rootimg.squash /loop
mount -t tmpfs none /loop/tmp
mkdir -p /loop/tmp/ow/var
mount -t aufs -o br:/loop/tmp/ow/var:/loop/var none /loop/var
mkdir -p /loop/tmp/ow/usr
mount -t aufs -o br:/loop/tmp/ow/usr:/loop/usr none /loop/usr
mkdir -p /loop/tmp/ow/etc
mount -t aufs -o br:/loop/tmp/ow/etc:/loop/etc none /loop/etc
echo "copyinng modified rc.S and rc.M to /etc/rc.d/"
cp /etc/rc.S.modified /loop/etc/rc.d/rc.S
cp /etc/rc.M.modified /loop/etc/rc.d/rc.M
cp /etc/rc.4.modified /loop/etc/rc.d/rc.4
cp /etc/csh.login /loop/etc/csh.login
for i in inittab fstab passwd shadow ; do
echo "copying modified $i to /etc/$i"
cp /etc/$i /loop/etc/$i
done
rootimg.squash が見つかれば,それを /dev/loop0 に結びつけて,/loop に squash-fs でマウントします.
この時点で,/loop の下に(squash-fs 上に構築した)ルートファイルシステムが見えるようになります.
この squash-fs 上のルートファイルシステムの /tmp に tmpfs をマウントして読み書きできるようにして,
/var や /us,/etc 等,書き替えが必要となる部分のディレクトリを /tmp 上に取ってから union mount で被せていき,
修正が必要な設定ファイル類を initramfs/etc の下からコピーしています.
union mount したディレクトリに書き込んだファイルは /loop/tmp/ow の下の各ディレクトリに書き込まれ,
元の RO なファイルは見えなくなります.以下,同様の union mount + cp の処理が続くので少し省略します.
mount -t tmpfs tmpfs /loop/dev
cp -a /dev/console /loop/dev
/loop に root partition を切り替えた際に使うことになる /loop/dev ディレクトリを書き込み可能にして,
現在使っている /dev/console を使い続けるために /loop/dev にコピーしています.
こうしておかないと root partition を切り替えた際にコンソールへのメッセージが出力されなくなります.
mount --move /proc /loop/proc
mount --move /sys /loop/sys
/proc と /sys を使い続けるために /loop 以下に移動させ,
# exec /bin/sh
echo "switch_root to /loop"
sleep 5
cd /loop
exec /bin/switch_root -c /dev/console . /sbin/init
"switch_root to /loop" のメッセージを出力して 5 秒後に cd /loop してから
/bin/switch_root コマンドを発行し,現在のディレクトリ(/loop)を新しい root partition にして,
/sbin/init を実行します.以後の処理は通常の Plamo 同様,/sbin/init が /etc/inittab を元に
sysinit に該当する /etc/rc.d/rc.S を起動して,rc.S が udev を起動し,,と進んでいきます.
コメントアウトしている exec /bin/sh を有効にすれば、必要な処理を行った上で対話的な shell が起動されるので、
必要な設定等が行われているかを調べることができます。対話的なshellからも、switch_root コマンドを発行すれば、
squash_fs 上のファイルシステムに切り替えることが可能です。
#comment