[[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

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS