<!doctype linuxdoc system>
<article>
<title>Ext-Rootfs-mini-HOWTO
<author>こじまみつひろ (<tt>isle@st.rim.or.jp</tt>)
<date>v0.4, 1997/05/14

<abstract>
この文書では、NotePC を主な対象に、initrd を使って外付けの SCSI ディス
んクや NFS マウントしたディレクトリにルートファイルシステムを取って 
Linux を起動する方法と 1 枚の FD に最小の Linux システムを組みこむ方法
を解説します。
</abstract>

<!-- 
<toc>
-->

<sect> はじめに<label id="intro">
<p>
Note PC では HDD の容量の問題で、内蔵 HDD に Windows95 を残したまま、
外付けの SCSI ディスクに Linux をインストールしたい、という状況がよく
生じます。しかし、Linux で外付けの SCSI ディスクを使うためには 
pcmcia-cs が必要で、そのためには Linux を起動しなければならない、とい
う「鶏と卵」的な問題がありました。

しかし、Linux 2.0 のシリーズに採用された initrd という機能を利用すれば、
initrd で起動して pcmcia-cs を使えるようにし、外付け SCSI HDD をルート
ファイルシステムにして起動する、ということができるようになりました。同
様に、LAN カードを使って NFS ディレクトリにルートファイルシステムを置
くことも可能です。

この文書では、initrd を使って外付け SCSI HDD や NFS マウントしたディレ
クトリにルートファイルシステムを置き Linux を起動する方法について説明
します。

<sect> initrd とは？ <label id="what">
<p>
Linux 2.0 ではメモリ上にファイルシステムを作る ramdisk やファイルをファ
イルシステムとしてマウントする loopback ファイルシステムがサポートされ、
ファイルシステムをきわめて柔軟に使うことができるようになっています。
initrd はこの 2 つのメカニズムを組みあわせたようなもので、起動時にファ
イルとして用意したファイルシステムを ramdisk 上に展開、そこを暫定的な
ルートファイルシステムとしてカーネルを立ちあげ、必要な処理をしてから実
際のルートファイルシステムを再マウントする、という 2 段ロケット的なブー
トを可能にします。

この機能を使って、initrd 上に pcmcia-cs を置いておけば、initrd で起動
した状態で PC カードを使用できるようになります。そして、ルートファイル
システムを外付けの HDD や NFS サーバに置くと、内蔵 HDD には Linux パー
ティションを置く必要はなくなり、Win95 のディスクの片隅に loadlin.ext 
とカーネルイメージ、圧縮した initrd ファイルを置いておくだけで Linux 
が使えるようになります。(FD に入れれば内蔵 HDD には一切ファイルを置く
必要がなくなります)

容量の問題で内蔵 HDD には Linux をインストールできない人や、Note PC で
も複数のディストリビューション(Slackware, Red Hat, Debian)を切り替えて
使ってみたい人には便利な機能でしょう。試していませんが MO や PD といっ
たメディアをルートパーティションにして起動することも(動きはすごく遅く
なるでしょうが)できるはずです。

ただし、外付け SCSI HDD や NFS ディレクトリをルートパーティションにし
た場合、当然のことですが使用中に PC カードを抜くことはできませんので、
note PC の命である可搬性は大きく損なわれます。

<sect> 外付け HDD をルートファイルシステムにする<label id="HDD">
<p>
外付け HDD にルートファイルシステムを置く方法から説明します。

まず、Win95 の載った Note PC と pcmcia-cs でサポートされている SCSI カー
ド、外付けの HDD ドライブ、それらを接続するための SCSI ケーブル、ター
ミネータ等を用意します。Linux のインストールには CD-ROM を使うため、
CD-ROM ドライブもあった方がいいでしょう。手元では以下のような構成で試
しています。

<itemize>
<item>Note PC         : Toshiba 610CT
<item>CD-ROM ドライブ : Panasonic KXL-D740 4X CD-ROM
<item>SCSI カード     : 上記に付属のカード(Qlogic OEM)
<item>LAN カード      : Accton EN2212
<item>外付け SCSI HDD : iomega jaz 1GB
</itemize>

インストールに使う Linux のディストリビューションはトッパンの「Linux 
入門」の CD-ROM(Slackware 3.1)を使うことにします。

initrd はディストリビューションに依存する機能ではないので、Red Hat や 
Debian を使っても同様のことは実現可能だと思いますが、筆者は Slackware
3.1 でしか試していません。

<enum>
<item> 
まず、Windows 95 を起動して CD-ROM ドライブをシステムに認識させます。
この部分は Linux とは関係ないので、Windows 95 のマニュアルや CD-ROM ド
ライブのマニュアルを読んでください。

<item>
「Linux 入門」の CD-ROM に入っている pxmciax.gz の mount は以下の作業に
必要な loopback デバイスのマウントをサポートしていないので、
<url url="http://www.st.rim.or.jp/~isle/Linux/pcmciax2.gz"
name="http://www.st.rim.or.jp/~isle/pcmciax2.gz"> をダウンロードします。

<item>
「Linux 入門」の 1 枚目の CD-ROM から、
<tt>(D:&bsol;)install&bsol;notepc&bsol;tools&bsol;loadlin&bsol;loadlin.exe</tt> 
と<tt>(D:&bsol;)kernels&bsol;aha1542.s&bsol;zImage</tt> を Windows95 の
領域にコピーします。Linux 用のディレクトリを作ってそこに入れておくのが
いいでしょう。以下ではこれらのファイルは <tt>C:&bsol;linux</tt> に置いてあ
るものとします。上でダウンロードした pcmciax2.gz も同じディレクトリに
移しておきます。

<item>
Win95 をいったん再起動して、&dquot;Starting Windows95&dquot; のメッセージが出
た時に F8 キーを押し、立ち上げモードの選択画面を出します。6 の 
&dquot;Command Prompt Only&dquot; を選び、コマンドプロンプト画面で起動します。

Linux をブートする際、日本語モードでは画面が表示されなくなるので、
&dquot;us&dquot; コマンドを実行して、忘れずに英語モードに切り替えてお
きましょう。

<item>
<tt>cd linux</tt> し、loadlin を使って Linux を起動します。この時、
pcmciax.gz を initrd に指定し、ルートファイルシステムは initrd を
展開して作成される ramdisk(/dev/ram0) を指定します。

<code>
    c:\linux > loadlin zimage initrd=pcmciax2.gz root=/dev/ram0
</code>

<item>
pcmciax2.gz には pcmcia-2.8.22 相当の機能が組みこまれているので、サ
ポートされている SCSI カードはそのまま認識できるはずです。接続して
いる CD-ROM や外付け HDD がきちんと認識されているか確認してください。

<quote>
pcmciax2.gz にはネットワークカードを使って NFS 経由でインストールしたり、
EasyHard、PLIP、 SLIP 経由でもインストールできるようにモジュールを用意
していますので、ヒマと根性のある人は試してみてください(苦笑)。
</quote>

<item>
Slackware のインストール作業そのものは「Linux 入門」に詳しく説明してあ
るので省略します。外付けの HDD を対象に、CD-ROM からインストールするよ
うに指定すれば、その後の設定は「Linux 入門」の記述に沿って進むはずです。
ただし、今回は lilo を使わず loadlin.exe で起動しますので、最後の lilo 
のインストールの部分は飛ばして、内蔵 HDD に lilo をインストールしない
ようにしておきます。

<item>
Slackware のインストールが終了したら、再起動する前に pcmciax2.gz に少し
細工をして、initrd をマウントした時点で一度プロンプトを出すようにして
おきます。

pcmciax2.gz を修正するには、このファイルを loopback ファイルシステムを
使ってマウントしなければなりません。initrd には圧縮ファイルを自動的に
展開する機能がありますが、loopback ファイルシステムには自動展開機能が
ないので、一度 pcmciax2.gz を展開する必要があります。

pcmciax2.gz を展開するために、まず <tt>/dos</tt> のようなディレクトリを
作り、そこに Windows95 のディスク領域をマウントし、gunzip で 
pcmciax2.gz を展開します。

<code>
    # mkdir /dos
    # mount -t msdos /dev/hda1 /dos
    # gunzip < /dos/linux/pcmciax2.gz > /dos/linux/pcmciax2
</code>

pcmciax2 に細工するために、pcmciax2 をマウントするためのディレクトリ
(/workdir)を作り、mount に -o loop オプションを指定して pcmciax2 ファ
イルをファイルシステムとしてマウントします。

<code>
    # mkdir /workdir
    # /mnt/bin/mount /dos/linux/pcmciax2 /workdir -o loop
    # ls /workdir
    bin/     cdrom@   etc/     lib/     proc/    sbin/    usr/
    boot/    dev/     floppy/  mnt/     root/    tmp/     var/
</code>

initrd では、initrd 上に linuxrc というファイルがあればそれをまず起動
することになっています。ですから linuxrc を <tt>bin/sh</tt> にシンボリッ
クリックしておけば、initrd を起動した状態で sh を使って対話的に各種の
設定を行うことが可能になります。

<code>
    # ln -s bin/sh linuxrc
    # ls -l /workdir/linuxrc
    lrwxrwxrwx 1 root root 6 Jan 4 14:39 /workdir/linuxrc -> bin/sh*
</code>

もう一つ、実際のルートファイルシステムになるパーティションに 
<tt>/initrd</tt> というディレクトリを作っておきます。initrd 経由で起動
した時、実際のルートファイルシステムになるパーティションに /initrd と
いうディレクトリがあると、initrd で使った暫定版のルートファイルシステ
ムはこのディレクトリに移して保存されます。

<code>
    # mkdir /workdir/initrd
</code>

これでインストール作業が終了しました。システムを再起動して、再度 Win95 
をコマンドプロンプトモードで起動します。

<item>
今回はルートファイルシステムを対話的に設定したいので loadlin.exe を以
下のように <tt>root=</tt> オプションは指定せずに起動します。initrd の
指定も修正した pcmciax2 にしていることに御注意ください。

<code>
    c:\linux\> loadlin zimage initrd=pcmciax2
</code>

<item>
この状態で起動すると、カーネルを展開した後、initrd 上にある linuxrc を
実行し、プロンプトが出て止まります(linuxrc は sh へのシンボリックリン
クなので、実際には sh が動いています)。この状態ではまだ pcmcia-cs が動
いていないので、まず <tt>/etc/rc</tt> を実行して pcmcia-cs を使えるよ
うにします。

<code>
 # /etc/rc
</code>   

<tt>/etc/rc</tt> が <tt>/rc/rc.d/rc.pcmcia</tt> を実行すると、
pcmcia-cs が機能するようになり、SCSI カードやそれに接続された外部デバ
イスも認識されるようになります。正しく認識しているか、表示されるメッセー
ジを確認してください。

<item>
次にルートファイルシステムを外付けの SCSI ディスクに変更します。
initrd を使っている場合、proc ファイルシステムの 
<tt>/proc/sys/kernel/real-root-dev</tt> というファイルにルートファイルシス
テムのデバイス番号を書きこんでやると、initrd を終了した際、そのデ
バイスをルートファイルシステムとしてマウントします。

ルートファイルシステムのデバイス番号は <tt>/dev/xxx</tt> ファイルを 
<tt>ls -l</tt> すれば表示されます。例えば、外付けの 1 つめの SCSI HDD 
のパーティション 1 をルートファイルシステムにしたい場合、

<code>
    # ls -l /dev/sda1
    brw-r-----   1 root    disk   8,   1 Apr 29  1995 /dev/sda1
</code>

なので、<tt>/dev/sda1</tt> のデバイス番号は major が 8、minor が 1 で
す。この場合、"0x801" を <tt>/proc/sys/kernel/real-root-dev</tt> に書
きこみます。

<code>
    # echo "0x801" > /proc/sys/kernel/real-root-dev
</code>

同様に外付けの 2 つめの SCSI HDD 全体をルートファイルシステムにする場合、

<code>
    # ls -l /dev/sdb1
    brw-r-----   1 root    disk   8,   17 Apr 29  1995 /dev/sda1
</code>

なので、"0x811" を <tt>/proc/sys/kernel/real-root-dev</tt> に書きこみ
ます。2 台目の IDE ドライブの 2 つ目のパーティションならば、

<code>
    # ls -l /dev/hdb2
    brw-r-----   1 root    disk   3,  66 Apr 28  1995 /dev/hdb2
</code>

なので "0x342" を書きこみます。

ls -l /dev/xxx で表示されるデバイス番号は 10 進表記ですが、<tt>echo
"0xaaa"</tt> で書きこむ場合は 16 進表記になっていることに御注意くださ
い。

<item>
実際のルートファイルシステムの設定が終われば exit を入力するか、ctrl-D 
を押して linuxrc(実体は sh)を終了します。すると、
<tt>/proc/sys/kernel-real-root-dev</tt> に設定したルートファイルシステ
ムを新しいルートファイルシステムにしてシステムが起動するはずです。

<item>
Slackwareに標準の起動用スクリプト <tt>/etc/rc.d/rc.S</tt> は通常の
desktop 環境を前提にしているので nfsroot で使用するといろいろと問題が
生じます。具体的にどうすればいいかは現在も試行錯誤中ですが、nfsroot を 
fsck するのはヘンなので、fsck してる回りは全部コメントアウトして、
必要なコマンドを動かしているところだけにしていいように思います。

<item>
新しいルートファイルシステムで起動すると、古いルートファイルシステムは 
<tt>/initrd</tt> 以下に移され read only でマウントされています。initrd 
段階で動いていた各種のプロセスからはこのディレクトリはルートファイルシ
ステムのままに見えるので、例えば cardmgr の見る <tt>/var/run/stab</tt> 
は <tt>/initrd/var/run/stab</tt> になります。

pcmcia-cs では <tt>/var/run/stab</tt> に現在挿入されているカードの状態
を書きこんで監視していますが、<tt>/var/run/stab</tt> が 
<tt>/initrd</tt>以下の read only ファイルシステム
(<tt>/initrd/var/run/stab</tt>)に移動すると、カードを挿し替えた時の情
報の更新が不可能になります。そのため、一旦 cardmgr を終了させてから再
起動し、cardmgr が現在の <tt>/var/run/stab</tt> を参照するようにします。

<code>
    # killall cardmgr
    # /sbin/cardmgr
</code>

このためには、initrd に組みこんだ pcmcia-cs とルートファイルシステ
ムにある pcmcia-cs のバージョンや設定が同じになっている必要があります。

pcmcia-cs が initrd 段階で組みこんだ pcmcia_core.o や i82365.o、ds.o 
の 3 つのモジュールは外付け SCSI HDD をルートファイルシステムにしてい
る限り使用中なので取り除くことはできません。そのため再起動の際には 
"device busy" 等のエラーメッセージがいくつか出ますが、特に気にする必要
はありません(と思う、、)。

<item>
再起動した cardmgr は通常の <tt>/var/run/stab</tt> を見ながらカードの
監視を行うため、新しいカードを挿入しても認識できるはずです。PC カード
が正しく認識されるか、カードを抜き挿しして試してみてください。ただし、
外付けの SCSI をルートファイルシステムにしている場合、SCSI カードを抜
くと確実にハングアップしますので御注意ください。

<!--
initrd は起動時に <tt>root=</tt> オプションでルートファイルシステムを
指定すると linuxrc があっても指定したパーティションをルートファイルシ
ステムにして起動します。この性質を利用して、あらかじめ 
<tt>/etc/rc</tt> を起動して、メニュー画面でルートパーティションを選択
するような linuxrc を組みこんだ pcmciax.gz を用意しました。インターネッ
トにアクセスできる人は <htmlurl
url="ftp://www.st.rim.or.jp/~isle/Linux/initrd/pcmciax.gz"
name="ftp://www.st.rim.or.jp/~isle/Linux/initrd/pcmciax.gz">(注意：ま
だ置いてないです)を持っていってください。

この pcmciax.gz は 

<code>
c:\linux>loadlin zimage initrd=pcmciax.gz root=/dev/ram0 
</code>    

と起動すれば通常のインストール用に、

<code>
 c:\linux> loadlin zimage initrd=pcmciax.gz
</code>   

と起動すれば、ルートファイルシステムの選択画面が出るようになっています。
メニュー画面で選べば、 <tt>/dev/sda[12]</tt>,<tt>/dev/sdb[12]</tt> は
自動的デバイス番号を書きこむようにしていますが、それ以外のデバイスをルー
トファイルシステムにする場合は、あらかじめそのデバイスのデバイス番号を
チェックして、"0x808" 等と書きこんでください。
-->

</enum>

<sect> NFS マウントしたディレクトリにルートファイルシステムを置く<label id="NFS">
<p>

initrd を使えば pcmcia-cs 経由で LAN カードを使い、NFS マウントしたディ
レクトリにルートファイルシステムを置いた diskless Linux を構成すること
も可能です。

NFS マウントしたディレクトリにルートファイルシステムを置く(NFS root)場
合、カーネルの構築時に、NFS オプションと NFS root オプションを共に指定
する必要があります。Slackware に付属のカーネルには NFS root オプション
は指定されていないので、NFS root を使う場合にはカーネルを再構築する必
要があります。カーネルを再構築する際に指定すべきオプションは <ref
id="make" name="「専用のシステムを作る」">節で解説します。

NFS root を利用する場合、NFS サーバとなるマシンに必要なルートファイル
システムを用意する必要があります。そのための方法については 
/usr/src/linux/Documentation/nfsroot.txt や nfs-root-mini-HOWTO を参照
してください。

また、NFS サーバとなるマシンでルートファイルシステムを export する際に
はオプションとして <tt>/etc/exports</tt> ファイルで no_root_squash を
オプションを指定し、ルート権限で NFS ディレクトリにアクセスできるよう
にしておきます。

<code>
/var/nfsroot	cyclone.rider.co.jp(rw,no_root_squash)
</code>

NFS サーバとなるマシンのルートファイルシステムのあるディレクトリ(上記
の例では <tt>/var/nfsroot</tt>)にある <tt>/etc/fstab</tt> も NFS マウ
ント用に修正しておく必要があります。

<code>
172.16.1.1:/var/nfsroot  /    nfs   rw,rsize=8192,wsize=8192,intr
</code>

カーネルを NFS root オプションを指定して再構築し、initrd で起動すると、
<tt>/proc/sys/kernel/nfs-root-name</tt> と 
<tt>/proc/sys/kernel/nfs-root-addrs</tt> というファイルに書きこめるよ
うになります。前者(<tt>nfs-root-name</tt>)にはサーバマシンでの NFS
root のディレクトリを、後者(<tt>nfs-root-addrs</tt>)にはサーバーマシン、
クライアントマシンそれぞれの IP アドレスを指定します。
<tt>/proc/sys/kernel/real-root-dev</tt> には 0xff(255) を指定しておき
ます。

例えば、サーバマシン(hurricane.rider.co.jp)の IP アドレスが 172.16.1.1、
クライアントマシン(cyclone.rider.co.jp)の IP アドレスが 172.16.1.2、ネッ
トマスクが 255.255.255.0 の場合、initrd で起動して、ネットワークカード
が使えることを確認してから、

<code>
# echo "/var/nfsroot" > /proc/sys/kernel/nfs-root-name
# echo "172.16.1.2:172.16.1.1::255.255.255.0:cyclone  \
         > /proc/sys/kernel/nfs-root-addrs
# echo 255 > /proc/sys/kernel/real-root-dev
</code>

と書きこみ、linuxrc を終了すれば、hurricane 上の <tt>/var/nfsroot</tt>
を NFS root にしてシステムが起動します。

<tt>/proc/sys/kernel/nfs-root-addrs</tt>に書きこむ書式は nfsroot.txt 
にあるように、
&lt;client-ip&gt;:&lt;server-ip&gt;:&lt;gw-ip&gt;:&lt;netmask&gt;:&lt;hostname&gt;:&lt;device&gt;:&lt;autoconf&gt; 
という形で、省略した部分にはデフォルト値が使われます。

<quote>
Slackware 標準の <tt>/etc/rc.S</tt> ではルートファイルシステムをいった
ん read-only でマウントして fsck しますが、NFS root の場合、ルートファ
イルシステムはあらかじめマウントされているので、その旨を示すエラーメッ
セージが表示されますが、多分大丈夫です(あまり使ってないので自信ありま
せん。識者の御意見を教えてください。)
</quote>

メモリの少ないマシンで swap 領域も NFS 上に取る必要がある場合、
<url
url="http://sunsite.unc.edu/pub/Linux/Incoming/etherboot-3.0b1.tar.gz" 
name="NFS swap patch"> をあてて、カーネルを再構築してくださ。


<sect> 専用のシステムを作るには<label id="make">
<p>

pcmciax.gz は Slackware 3.1 のカーネルと組みあわせて使うように 
pcmcia-cs も 2.0.0 のカーネル用にコンパイルしていますので、カーネルを
バージョアップする際には pcmcia-cs も再コンパイルが必要です。

initrd 経由で起動している場合、pcmcia-cs が initrd で起動するファイル
システムの中に置かなければならないので、システムをバージョンアップする
際には多少の注意が必要になります。

<sect1> カーネルの再構築
<p>

カーネルの再構築時には 以下の項目に注意して設定してください。これら以
外のオプションはお使いの環境に合わせて設定します。

<itemize>
<item> &dquot;Loadable modules support&dquot; の &dquot;Enable
loadable module support&dquot; と &dquot;Kernel daemon support&dquot; 
を設定。

<item>
&dquot;General Setup&dquot; の &dquot;Kernel Support for a.out
binaries&dquot; と &dquot;Kernel Support for ELF binaries&dquot; を設
定(モジュールではダメ)。

<item>
&dquot;Floppy, IDE, and other block devices&dquot; の &dquot;Loopback
device support&dquot; 、&dquot;RAM disk support&dquot; と 
&dquot;Initial RAM disk(initrd) support&dquot; を設定。

<item>
&dquot;SCSI support&dquot; の &dquot;SCSI support&dquot;、&dquot;SCSI
disk support&dquot; を設定。&dquot;SCSI tape support&dquot;,
&dquot;SCSI CD-ROM support&dquot;, &dquot;SCSI generic support&dquot; 
は設定してもモジュールでも可。必須ではありませんが &dquot;Probe all
LUNs on each SCSI device&dquot; も念のため設定しておきます。

<item> NFS root を使う場合は &dquot;File systems&dquot; 中の 
&dquot;NFS&dquot;と&dquot;NFS root&dquot;オプションも設定します。

</itemize>

カーネルをコンパイルする際には <tt>make zlilo</tt> ではなく、<bf>make
zImage</bf> で <tt>/usr/src/linux/arch/i386/boot/zImage</tt> を作りま
す。この zImage を DOS 領域にコピーして、このカーネルイメージを 
loadlin.exe でロードするようにします。

<code>
# cp /usr/src/linux/arch/i386/booz/zImage /dos/linux/zimage.new
</code>

カーネルのコンパイルが終れば、モジュール類も忘れずコンパイル、インストー
ルしておきます(<tt>make modules; make modules_install</tt>)。

次回に起動するときは loadlin.exe で <tt>zimage.new</tt> を指定します。

<sect1> pcmcia-cs の再構築
<p>


pcmcia-cs はルートファイルシステムと initrd の双方にインストールしてや
る必要があります。pcmciax2 をループバックでマウントして 
<tt>/sbin/{cardmgr, cardctl}</tt> や 
<tt>/lib/modules/2.0.x/pcmcia</tt> 以下を入れ替えるのも一つの方法です
が、この場合、pcmciax には libc-4.7.6 しか入っていないことに注意してく
ださい。すなわち、コマンドである <tt>/sbin/{cardmgr,cardctl}</tt> をコ
ンパイルする場合は a.out 形式でコンパイルする必要があります。

このためには、pcmcia-cs を通常の make でコンパイルしてから、cardmgr ディ
レクトリに移り、Makefile に CC = /usr/i486-linuxaout/bin/gcc を追加し
て make clean; make します。いくつかのコマンドは a.out 形式でうまくコ
ンパイルできないかも知れません。

もう一つの方法は、 ELF 形式のコマンドを集めた新しい initrd を用意する
ことです。新しく initrd を作るには、まず ramdisk 上にファイルシステム
を作って必要なファイルを集め、それをファイルに書き出すのが簡単でしょう。
以下にそのための一つの手順を述べます。

<enum>
<item> ramdisk 上に 4M ほどの ext2 のファイルシステムを構築する。

<code>
# mke2fs /dev/ram0 4000
</code>

initrd 経由で起動したシステムの場合、<tt>/dev/ram0</tt> は使用中の場合
がありますので、その際は <tt>/dev/ram1</tt> 等を使ってください。

<item> ramdisk を適当なディレクトリにマウント。ヒナ型に使うために、pcmciax2
も別のディレクトリにマウントし、いったん pcmciax と同じファイルを 
/workdir 以下にコピーします。

<code>
# mount -t ext2 /dev/ram0 /workdir
# mount /dos/linux/pcmciax /refdir -o loop,ro
# cd /refdir; tar cvf - * | (cd /workdir; tar xf -)
</code>

<item> 
この時点で /workdir 以下は pcmciax2 と同じファイル構成になっているので、
a.out 形式のライブラリやコマンド類を ELF 形式のものに入れかえます。こ
のあたりは面倒ですが、手作業でやるしかないようです。

<item>
pcmcia-cs を /workdir 以下にインストールします。pcmcia-cs のディレクト
リで<tt>make config</tt>すると設定に関する質問が表示されますので、
&dquot;<tt>Alternate target install directory</tt>&dquot; で 
<tt>/workdir</tt> を指定します。

<code>
 # make config

  Linux PCMCIA Configuration Script
  The default responses for each question are correct for most users.
  Consult the PCMCIA-HOWTO for additional info about each option.

  Linux source directory [/usr/src/linux]:
  Alternate target install directory [/]: /workdir
  /workdir
  C compiler name [gcc]: 
  ......

</code>

この状態で make all して make install すれば <tt>/workdir/etc/pcmcia</tt> 
や <tt>/workdir/lib/modules/`uname -r`/pcmcia</tt> に必要なモジュールがイ
ンストールされます。ただし、<tt>/workdir/usr/man</tt> 以下に pcmcia-cs の
マニュアル類もインストールされてしまうので不要ならば削除してください。
 
initrd 以外に、起動後に実行される実際のルートファイルシステムにも 
pcmcia-cs はインストールしておく必要があります。そのためには、
pcmcia-cs を再度 "Alternate target install directory : / " に設定して
インストールしておきましょう。

<item> 
<tt>/dev/ram0</tt> に作成したファイルシステムを通常のファイルに落とし
ます。

<code>
# umount /workdir
# dd if=/dev/ram0 of=initrd bs=1k count=4000
</code>

<item>
これで新しい initrd ができました。<tt>mount initrd /workdir -o
loop</tt> として、正しくファイルシステムとして認識できるか確認しておき
ましょう。

<item>
新しく作った initrd を DOS からアクセスできる領域にコピーします。
initrd は圧縮しておくことも可能です。

<code>
# cp initrd /dos/linux
# gzip /dos/linux/initrd
</code>

<item>
新しいカーネルと initrd の組み合わせで再起動します。

</enum>

手元で試作した initrd を <htmlurl
url="http://www.st.rim.or.jp/~isle/Linux/initrd.gz"
name="http://www.st.rim.or.jp/~isle/Linux/initrd.gz"> に用意しました。
この initrd には、対話的に外付け SCSI をルートファイルシステムにしたり、
NFS root を指定したりする dialog も付けていますので、興味のある方はお
試しください。この initrd に組みこんでいる pcmcia-cs は 2.8.23 でカー
ネル 2.0.27 用にコンパイルしています。

<sect> all-in-one package の作り方
<p>

Slackwareでは色々なデバイスドライバを組みこんだカーネルを用意したファ
イルシステム(ブートデイスク)とインストール用のファイルシステム(ルート
ディスク) 2 枚組でインストールします。また、ルートファイルシステムにト
ラブルが発生した場合などに非常用のツール一式を組みこんだルートファイル
システム(レスキューディスク)も用意されています。

しかし、2 枚のディスクが必要な場合、マーフィの法則の典型例として、必要
な場合にはどちらかのディスクが見当たらなくなるので(単に私に整理能力が
無いためだろうけど、、)、これらの 2 枚分のデータを 1 枚のフロッピーに
詰めこんでしまいたくなります。本節では 1 枚の FD から Linux を起動し、
最小限のシステムが動く環境を構築する方法(all-in-one package)について説
明します。

all-in-one package を作る方法としては、通常の ramdisk を使う方法と 
initrd を使う方法の 2 つがあります。ramdisk を使う場合にはさらに lilo 
を経由する方法と経由しない方法があります。これらの方法を順に説明します。

<sect1> lilo 経由で ramdisk を使う方法
<p>

ramdisk を使う場合、起動用のファイルシステムを書きこんだ FD の空いてい
る部分に ramdisk に組みこむためのルートファイルシステムのイメージを書
きこむことになります。そのためには ルートファイルシステムを圧縮したイ
メージを <tt>/dev/fd0</tt> に書きこむ際に、dd の seek オプションを使っ
てブートファイルシステムの分だけ後ろにずらしてやる必要があります。

この方法の利点は lilo 経由で起動するためにカーネルにコマンドラインオプ
ションを指定したり、複数の設定を切りかえて使えることです。一方、欠点と
しては mount してディスクの中身を確認する際に root fs の分しか内容が表
示されず、root fs として何が入っているかを確認するには起動してみるしか
 ないことがあります。

ここでは Slackware 3.1 に付属の AHA-1542 用ドライバを組みこんだカーネ
ルに rescue disk のイメージ(rescue.gz)を書きこんで、非常用の root/boot 
フロッピーを作ってみます。

<enum>

<item> AHA-1542 用の起動用ディスクイメージを dd を使ってフロッピーディ
スクに書きだします。

<code>
# dd if=/cdrom/slackware/bootdsks.144/aha1542.s of=/dev/fd0 bs=1k
556+0 records in
556+0 records out
</code>

rescue disk のイメージを boot disk のイメージの後ろに書きこみたいため、
"bs=1k" オプションを指定して、boot disk のイメージがフロッピーのどこま
でを占めるかを確認しておきます。この例では 1 ブロック 1k として 556 ブ
ロックまで占めています。

<item> recue disk のルートファイルシステムイメージをフロッピーに追加す
る。

dd の seek オプションを使ってブートディスクのイメージと重ならないよう 
560 ブロック以降に rescue disk のイメージ(rescue.gz)を追記します。

<code>
# dd if=/cdrom/slackware/rootdsks/rescue.gz of=/dev/fd0 bs=1k seek=560
529+1 records in
529+1 records out
</code>

これで 1 枚の FD にブート用のファイルシステムとルート用のファイルシス
テムが入りました。

<item> boot disk の /etc/lilo.conf の修正

次に、起動時に ramdisk を読みこむように boot disk の 
<tt>/etc/lilo.conf</tt> を修正します。このためには <tt>/dev/fd0</tt> 
をどこか適当なディレクトリに mount する必要があります。以下では 
/workdir にマウントしています。

<code>
# mount /dev/fd0 /workdir
# df
Filesystem         1024-blocks  Used Available Capacity Mounted on
/dev/hda3             944303  747325   148191     83%   /
/dev/hda1             308248  267832    40416     87%   /dos
/dev/fd0                 539     490       49     91%   /workdir
#
</code>

この方式で作った all-in-one ディスクをマウントした場合、認識されるのは
このようにブートディスクの部分だけです。

もともとの lilo.conf はこのようになっているはずです。

<code>
# cat /workdir/etc/lilo.conf 
boot = /dev/fd0
message=/boot/message
prompt
image = /vmlinuz
        label = ramdisk
        ramdisk = 49152
        root = /dev/fd0u1440
        vga = normal
image = /vmlinuz
(後略)
#
</code>

この /workdir/etc/lilo.conf を修正して、起動時に自動的に ramdisk を読
みこむようにします。ramdisk 用にカーネルのコマンドラインとして以下のよ
うなパラメータが用意されています。

<itemize>
<item>ramdisk_start

FD 上で ramdisk が開始するブロックを指定します。今回の例では 560 です。

<item>load_ramdisk

ramdisk をロードする(1)かしない(0)かの指定です。今回は 1 を指定して、
ramdisk をロードするようにします。

<item>ramdisk_prompt

ramdisk をロードする際にプロンプトを出す(1)か出さない(0)かの指定です。
FD が 2 枚組になっている場合は FD を入れかえるためにプロンプトを出しま
すが、all-in-one の場合はプロンプトを出す必要はないので 0 を指定します。

<item>ramdisk_size

必要な ramdisk のサイズです。デフォルトでは 4096k になっており、このサ
イズを超える ramdisk を確保したい場合やメモリの少ないマシンで ramdisk 
のサイズを切り詰めたい場合に指定します。今回は特に指定する必要はありま
せん。

</itemize>

以上のことから、今回は lilo.conf に &dquot;ramdisk_start=560
load_ramdisk=1 prompt_ramdisk=1&dquot; という指定を追加すればいいこと
が分ります。これらのオプションは lilo.conf に &dquot;append = &dquot;
という形で記述します。

<code>
boot = /dev/fd0
message=/boot/message
append="ramdisk_start=560 load_ramdisk=1 prompt_ramdisk=0"
prompt
image = /vmlinuz
        label = ramdisk
        root = /dev/fd0u1440
        vga = normal

</code>


<item> /sbin/lilo を実行して、MBR の設定

lilo.conf を修正すると、一度 <tt>/sbin/lilo </tt>を実行して、設定情報
を MBR に反映させる必要があります。lilo は -r オプションでディレクトリ
を指定すると、そのディレクトリに chroot して実行されます。今回の例では 
<tt>/workdir</tt> に <tt>/dev/fd0</tt> がマウントされているので、
<tt>/workdir</tt> を指定して <tt>/workdir/etc/lilo.conf</tt> の設定を
反映するように lilo を実行します。

<code>
# /sbin/lilo -r /workdir
Added ramdisk *
Added big2
Added small2
Added drive2
Added mount
#
</code>

これで all-in-one の boot/rescue ディスクができました。システムを FD 
から立ちあげて、自動的に ramdisk がロードされ、rescue disk が起動する
ことを確認してください。

</enum>
<sect1> zdisk で ramdisk を使う方法
<p>

lilo を使って起動する場合、lilo の出す boot: プロンプトに対して必要な
オプションを指定することができるので、さまざまな状況に対応することがで
きます。一方、この方法では、起動用にファイルシステムが必要となり、使用
するディスクスペースも大きめになります。

一方、Linux の make zImage で作成されるカーネルイメージには FD から自
分自身を起動するためのコードが付いているので、lilo のオプション指定を
する必要がない環境では lilo を使わずに直接 FD からカーネルを起動するこ
とも可能です。ただし、この機能を使って ramdisk をロードするためには 
rdev というコマンドを使ってカーネル自身にルートファイルシステムのデバ
イス名や ramdisk の位置、 ramdisk のロードの有無を書きこんでおく必要が
あります。

この方法の利点は boot disk にファイルシステムが不要でカーネルイメージ
を直書きすればいいだけになるので、FD の使用量が少なくできることです。
一方、欠点としては、カーネルが直接起動してしまうのでコマンドラインオプ
ションを指定できないことです。そのためこの方法で 1FD router を作ること
はできません(ルータを作る場合、複数の ethernet カードを認識させる必要
があるので、カーネルオプションが必須です)

また作成したフロッピーの中身を確認する方法がない(これで作った 
<tt>/dev/fd0</tt> はファイルシステムとしてマウントできません)ことも欠
点と言えるでしょう。

<enum>
<item> AHA-1542 用のカーネルイメージを FD に書きこむ。

前節と同様に AHA-1542 用のドライバを組みこんだカーネルを使いますが、今
回書きこむものはファイルシステムではなくカーネルそれ自身なので、必要な
ファイルは <tt>/cdrom/slackware/kernels/aha1542.s/zImage</tt> になります。

<code>
# dd if=/cdrom/slackware/kernels/aha1542.s/zImage of=/dev/fd0 bs=1k
437+1 records in
437+1 records out
#
</code>

ファイルシステムを書きこんだ場合、530 ブロック必要でしたが、カーネルだ
けを書きだすと 440 ブロックほどで済んでいることが分ります。

<item> rescue disk のイメージを FD に追加する。

カーネルは 440 ブロックぐらいで収まっているので、rescue.gz は 450 ブロッ
ク以降に書きこみましょう。

<code>
# dd if=/cdrom/slackware/rootdsks/rescue.gz of=/dev/fd0 bs=1k seek=450
529+1 records in
529+1 records out
#
</code>

<item> rdev でカーネル自身に必要な情報を設定

lilo の場合、カーネルにコマンドラインパラメータを使って ramdisk に関す
る設定を行えましたが、今回は lilo を経由しないのでカーネル自身に必要な
パラメータを書きこんでしまう必要があります。そのために使うコマンドが 
<tt>rdev</tt> です。まず、rdev コマンドで <tt>/dev/fd0</tt> にあるカー
ネルのルートデバイスを <tt>/dev/fd0</tt> に書きかえておきます。

<code>
# rdev /dev/fd0 /dev/fd0
</code>

rdev ではカーネル内部の 1 word(2 bytes)の領域を直接書き替えることで 
ramdisk のロードの有無や ramdisk の位置を変更できます。

rdev で指定する 2 bytes のうち、下位 11 bit(0 bit -> 10 bit) は 
ramdisk の位置を指定するために使われ(1k 単位のオフセット情報)、14 bit 
目が ramdisk のロードの有無、15 bit 目が ramdisk をロードする際のプロ
ンプトの有無の指定です。

今回の例では、ramdisk をロードし(bit 14 on)、ramdisk をロードする際に
プロンプトは不要(bit 15 off)、ramdisk のオフセットは 440 ブロックにな
りますので、

<tt>2^15*0(prompt) + 2^14*1(ramdisk) + 440(offset) = 16824</tt> を 
rdev で設定します。同時に rdev -R オプションを使ってルートファイルシス
テムを r/w でマウントするように設定します。

<code>
# rdev -r /dev/fd0 16384
# rdev -R /dev/fd0 0
</code>

これで、直接起動用の boot/root フロッピーができました。システムを再起
動して、rescue disk が正しく機能するか確認してください。

</enum>

<sect1> initrd を使う方法
<p>
initrd を使う方法の利点は、ロードする ramdisk のあるファイルシステムを
圧縮ファイルとして直接指定できるので、FD の中に見えない領域が無くなる
ことです。私のように整理能力の無い人間にはどの root fs イメージが入っ
ているのか確認してから起動できるこの方式がもっとも安心できます(笑)。ま
た、FD 全体の使用量が見えるので、あとどれくらいの機能を組みこめるかを
検討する際にも便利です。

一方、この方法の欠点としては、Slackware 3.1 に付属のカーネルイメージに
は initrd 機能は組みこまれていないので、このためのカーネルは手元で 
initrd 機能を組み込んでコンパイルしなければならないことです。また、
rescue.gz もそのままでは initrd として使えないため、少し細工をしてやる
必要があります。

<enum>

<item> 手元でカーネルのコンパイル

必要なオプションを組みこんでカーネルを設定し、make zImage しておきます。
オプションを選ぶ際に、ramdisk 機能と initrd 機能は忘れずにカーネルに組
みこんでください。

ramdisk 機能はモジュール化できますが、モジュールではなくカーネルに組み
こむ必要があります。

<item> 起動用の FD の準備

この方式では FD 1 枚に 1 つのファイルシステムを作って、そこに boot fs 
と initrd 用の圧縮したファイルシステムを置くことになります。FD にファ
イルシステムを作る際は ext2fs よりも minix fs にした方が容量を効率よく
使えます。状況によっては -i オプションを使って i-node を増しておいた方
がいいかも知れません。

<code>
# mkfs.minix /dev/fd0 1440
480 inodes
1440 blocks
Firstdatazone=19 (19)
Zonesize=1024
Maxsize=268966912
#
</code>

<item> FD に必要なファイルのコピー

この FD を起動用に使うには <tt>/dev</tt> や <tt>/etc</tt> 以下のファイ
ルが必要ですが、それらはSlackware のブートディスクのイメージをコピーす
るのが簡単でしょう。そのために <tt>/dev/fd0</tt> を <tt>/workdir</tt> 
に、<tt>/cdrom/slackware/bootdsk.144/aha1542.s</tt> を <tt>/mnt</tt> 
にそれぞれマウントし、tar を使ってブートディスクのイメージを FD にコピー
します

<code>
# mount /dev/fd0 /workdir
# mount /cdrom/slackware/bootdsk.144/aha1542.s /mnt -o loop
# df
Filesystem         1024-blocks  Used Available Capacity Mounted on
/dev/hda3             944303  747372   148144     83%   /
/dev/hda1             308248  267832    40416     87%   /dos
/cdrom/slackware/bootdsk.144/aha1542.s
                         539     490       49     91%   /mnt
/dev/fd0                1404       1     1403      0%   /workdir
#
# cd /mnt
# tar cvf - * |(cd /workdir; tar xf -)
# sync
# df
Filesystem         1024-blocks  Used Available Capacity Mounted on
/dev/hda3             944303  747372   148144     83%   /
/dev/hda1             308248  267832    40416     87%   /dos
/cdrom/slackware/bootdsk.144/aha1542.s
                         539     490       49     91%   /mnt
/dev/fd0                1404     490      914     35%   /workdir
# ls -l /workdir
total 446
drwxr-xr-x   2 root     root          160 Jun 13  1996 boot
drwxr-xr-x   2 root     root         3632 May 20  1996 dev
drwxr-xr-x   2 root     root           48 May  8  1995 etc
drwxr-xr-x   2 root     root           32 Mar 10  1993 proc
-rw-r--r--   1 root     root       448013 Jun 13  1996 vmlinuz
#
</code>

この時点での <tt>/workdir/vmlinuz</tt> は initrd の機能が組みこまれて
いないカーネルなので、手元でコンパイルした zImage(あるいは bzImage) ファ
イルを vmlinuz に置きかえます。

<code>
# cp /usr/src/linux/arch/i386/boot/zImage /workdir/vmlinuz
</code>

<item> initrd の準備

initrd で使うためには rescue.gz に linuxrc というファイルを作る必要が
あります(linuxrc の実体はbin/sh へのシンボリックリンクで構いません)。
このためには一度 rescue.gz を展開してファイルとしてマウントする必要が
あります。

<code>
# gunzip < /cdrom/slackware/rootdsks/rescue.gz > /tmp/rescue
# mount /tmp/rescue /tmpmnt -o loop
# cd /tmpmnt
# ln -s bin/sh linuxrc
# cd /
# umount /tmpmnt
# gzip -9 < /tmp/rescue > /workdir/rescue.gz
</code>

<item> /etc/lilo.conf の設定

<tt>/workdir/etc/lilo.conf</tt> を修正して、initrd として rescue.gz を
使うようにします。initrd を使う場合、lilo.conf に &dquot;initrd =
filename&dquot; というオプションを追加します。私はこういう風にしてみま
した。

<code>
boot = /dev/fd0
message=/boot/message
prompt
image = /vmlinuz
        label = ramdisk
        initrd = /rescue.gz
        vga = normal
</code>

lilo.conf を設定すれば、lilo を再実行して、変更点を反映させます。

<code>
# /sbin/lilo -r /workdir
Added ramdisk *
#
</code>

これで initrd を使った all-in-one disk ができました。システムを再起動
して正しく機能するか確認してみてください。この例では ctrl-D や exit で 
linuxrc を終了させる前に、本文書中で説明した方法で実際のルートファイル
システムを設定しておく必要があることに御注意ください。

</enum>

<sect> 関連文書
<p>

この文書を書く際に参考にした文書は、
<tt>/usr/src/linux/Documentation</tt>ディレクトリにある
<tt>initrd.txt</tt> と <tt>nfsroot.txt</tt> 、<tt>ramdisk.txt</tt>です。
これ以外にも、loadlin16 distribution 中の <tt>docs/manuals.txt</tt> に 
initrd についての説明があり、LDP の HOWTO 集の中にも 
nfs-root-mini-HOWTO があります(邦訳あり)。

<sect> おわりに <label id="closing">
<p>
initrd はここで示した以外にもさまざまな使い方があるシステムだと思いま
す。何かおもしろい活用方法を思いついた方はぜひ教えてください。

例えば、pcmciax.gz と aha1542 用のカーネルを一枚の FD に詰めこんだ 
all-in-one boot/root ディスクと MO なり CD-ROM なりにルートファイルシ
ステムを書きこんだものを用意すれば、SCSI 機器のつながった NotePC を
「お手軽 Linux マシン」に変身させることが可能でしょう。また、NFS 環境
ならば FD 1 枚の「お手軽 Diskless Linux マシン」キットというのも面白い
かも知れません。

多分 RedHat や Debian でも似たようなことはできるはずですが、Red Hat を
少しいじった限りでは、システムとしての完成度が高い分、こういう変ったこ
とをするには自由度が低いようです。もちろん、いったん起動してしまえば、
ルートファイルシステムは Red Hat でも debian でも関係ないはずですが。

間違いや誤字・脱字、改善のアイデアなど、なんでも <htmlurl
url="mailto:kojima@criepi.denken.or.jp" name="筆者">まで御連絡いただけば幸い
です。

</article>
