Linux on ThinkPad

中古の ThinkPad X21 を入手しました。手持ちのPCでは2番目に速いマシンになり バリバリです。 さっそく Debian GNU/Linux をインストールするのですが、その失敗と成功の物語? をレポートします。
インストール |  無線LAN |  ネットワーク・ブート |  FreeBSD
インストール
  ありがたいことに当機は Windows 2000 が入っていて、D2D (Disk to Disk) リカバリもできるようであった。
手持ちのUSB接続のCDRドライブを繋ぎ KnoppixのCDを入れて起動する。 USB1.1なので遅いが、CUIモードにすればそこそこ使える。

まず、 parted を使って Windowsパーティションを縮小し、Linux パーティションを確保する。 が、Windowsが起動しなくなった。 (-_-)

敗因: parted はHDDパラメータをカーネルから取得し、その値を元にパーティション テーブルを書き込む。 HDDのBIOSパラメータは 2584(1024)/240/63 であったが、カーネルは ATAインターフェイスで取得した値 41344/15/63 で認識していた。 そのためパーティションテーブルが 1024/15/63 を元にした値で書き込まれ BIOSパラメータと異なるため Windowsが起動できなくなった。

対策: Knoppixの起動時に knoppix 2 hda=2584,240,63 と入力して 立ち上げ、 parted でWindowsパーティションを縮小する。

注意: D2Dでリカバリするとパーティションテーブルも書き換えられる。 Windowsパーティションを縮小後、後ろに空きがある状態でD2Dすると、 Windowsパーティションが目一杯広げられる。

気を取り直し、D2Dでリカバリ後、 parted でWindowsパーティションを 縮小し、 fdisk でLinuxパーティション(hda5:ext2, hda6:swap, hda7:予備)を確保しファイルシステムを作成する。
そして、 debootstrap でDebianをネットワークインストールする。 (etch を入れた)

ここで ブートローダをどうするか悩む。 D2DはMBRとその後の数セクタを使用しているため、MBRにGRUBをインストールするのは ためらわれた。 熟考の末、GRUBのstage1は拡張パーティション(hda3)の 先頭にインストールし、stage2はHDD末尾の空き領域にインストール することにした。 fdiskで hda3 に起動フラグを立てればGRUBが動くはずだ。
まず、HDD末尾領域のLBAを fdisk -lu で調べ、コピーするLBAを決めて、 ddstage2 をHDD末尾にコピーする。
# dd if=/mnt/hda5/lib/grub/i386-pc/stage2 of=/dev/hda seek=39069828   
211+1 records と表示されるので stage2212 セクタ使用したことになる。
次に、 /sbin/grub を起動して、 (/mnt/hda5/sbin/grub だったか?) GRUBをインストールする。
grub> install (hd0,4)/lib/grub/i386-pc/stage1 d (hd0,2) (hd0)39069828+212 p (hd0,4)/boot/grub-menu   
そして、
/mnt/hda5/boot/grub-menu を以下のように書き込む。
title Windows 2000
root (hd0,0)
chainloader +1

title Debian GNU/Linux etch
root (hd0,4)
kernel /vmlinuz root=/dev/hda5 ro vga=0x0305    

Knoppixを終了して、起動してみる。うまく WindowsとLinuxのデュアルブートが できるようになった。
参考までにパーティション情報 (fdisk -l /dev/hda) は以下の通り。
Disk /dev/hda: 20.0 GB, 20003880960 bytes
240 heads, 63 sectors/track, 2584 cylinders
Units = cylinders of 15120 * 512 = 7741440 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hda1               1        1000     7559968+   7  HPFS/NTFS
/dev/hda2            2422        2583     1224720   1c  Hidden W95 FAT32 (LBA)  
/dev/hda3   *        1001        2385    10470600    5  Extended
/dev/hda5            1001        2024     7741408+  83  Linux
/dev/hda6            2025        2064      302368+  82  Linux swap / Solaris
/dev/hda7            2065        2385     2426728+  a5  FreeBSD

 

無線LAN
  安い無線LANカード Buffalo WLI2-CB-G54Lを買った。一応 Windowsで自宅内の どこでもInternetできるようになった。 Linuxではあまり期待はしていなかったのだが、少し調べると ndiswrapper を使えばできるようであった。
まず、我が家最速のデスクトップ機にLinuxソース(素の2.6.13.4)と ndiswrapper-source (etchのdeb)をダウンロード、展開して debian パッケージのbuildをする。
$ cd /hoge/src
$ tar jxf linux-2.6.13.4.tar.bz2
$ tar jxf /usr/src/ndiswrapper-source.tar.bz2
$ cd linux-2.6.13.4
$ make menuconfig
$ MODULE_LOC=/hoge/src/modules make-kpkg --rootcmd fakeroot --revision 0.1.thnkpd kernel_image modules_image 
カーネルconfig では忘れずに CONFIG_NET_RADIO=y にすること。 私は最初忘れていたのだが、buildは正常にできて dpkg -i でinstallした 後、 modprobe するとエラーが発生してモジュールロード不可であった。

ThinkPadに kernel-imagendiswrapper-modulesdeb を転送し、 dpkg -i でinstallする。 合わせて ndiswrapper-utilsapt-get でinstallする。
次に、
 http://ndiswrapper.sourceforge.net/mediawiki/index.php/List#B
を見ると以下のドライバーのありかが出ていたので
 ftp://ftp.support.acer-euro.com/notebook/TravelMate_4000_4500/driver/a802.zip
をダウンロードし、 unzip で展開し ndiswrapper に設定する。
$ unzip a802.zip
$ su
# cd A802/Winxp
# ndiswrapper -i neti2220.inf
# ndiswrapper -m

# ndiswrapper -l
Installed ndis drivers:
neti2220        driver present        
modprobe ndiswrapper してLANカードを差し込むと wlan0 というインターフェイスが出来る。 !(^o^)!

次に、自宅無線APのセキュリティ設定は WPA-PSK AES を使用しているのだが、 wpa_supplicant で設定できるらしい。 apt-get install wpasupplicant した後、
/etc/wpa_supplicant.conf の下の方を編集する。
network={
    ssid="0123456789ABCDEF"            
    psk="hogehoge"
    key_mgmt=WPA-PSK
    proto=WPA
}
そして、
/etc/default/wpasupplicant を編集する。
ENABLE=1
OPTIONS="-w -i wlan0 -D ndiswrapper -c /etc/wpa_supplicant.conf"   
/etc/init.d/wpasupplicant start してLANカードを差し込むと、 すんなりAPとつながったようだ。
ifconfig wlan0 192.168.11.21 して ping 192.168.11.1 するとちゃんと通信できた。

次は、自動でIPアドレスが付いて通信できるようにする。 DHCPは使ってないので /etc/network/interfaces に以下を追加編集する。
allow-hotplug wlan0
iface wlan0 inet static
    address 192.168.11.21
    netmask 255.255.255.0
    network 192.168.11.0
    broadcast 192.168.11.255
    gateway 192.168.11.1
    up ln -sf /etc/resolv.conf.wlan /etc/resolv.conf
    down ln -sf /etc/resolv.conf.null /etc/resolv.conf   
/etc/resolv.conf.null は空ファイル、 /etc/resolv.conf.wlan は適切に書いておく。  これでバッチリ!!
wgetで大きいファイルをダウンロードしてみる。 APが10baseT でつながっているので、速度は 1.07MB/s であった。

 

ネットワーク・ブート
  ThinkPad内蔵のEthernetはネットワーク・ブートできるはずなので 起動できるか試してみた。

まずはブートローダだが、GRUBでネットワーク・ブートできそうなので、Tryする。
grub-0.97.tar.gz をダウンロードして展開後、
$ cd grub-0.97
$ CC=gcc-3.3 ./configure --enable-diskless --enable-eepro100  
$ make
Linuxカーネル側では e100ドライバを使っているが、GRUBでは e100 がないので類似の eepro100 を指定してみた。
makeが終わると、stage2ディレクトリ内に pxegrub が出来ているので、それを tftpddhcpパッケージを インストール済のサーバ機の /srv/tftp/ ディレクトリにコピーする。

次に、DHCPサーバの設定をする。
/etc/dhcpd.conf を以下のように編集する。
option domain-name "homelan";
option domain-name-servers 192.168.100.1;
option subnet-mask 255.255.255.0;

subnet 192.168.100.0 netmask 255.255.255.0 {
  option broadcast-address 192.168.100.255;
  option routers 192.168.100.1;
  range 192.168.100.4 192.168.100.7;
}

host thnkpd {
  hardware ethernet 01:23:45:67:89:ab;
  fixed-address 192.168.100.4;
  filename "pxegrub";
  server-name "srv1.homelan";
  option root-path "/srv/tftp/thnkpd";
  option option-150 "/srv/tftp/grub.conf";  # (20 Nov. 05 追加)
}
 option root-path は後程、カーネルが参照する。
/etc/init.d/dhcp restart して、Etherケーブルを接続して、 ThinkPadの電源を入れ F12 を押し、 Intel(R) Boot Agent を選択すると 見事にGRUBが起動された。
(追記) dhcpd.confoption-150 を追加すると GRUB menu.lst のパスを指定できる。よって以下は Obsolete 。
ところで、GRUBのメニューのデフォルトは /boot/grub/menu.lst なのでメニューは出ず、コマンドモードになる。
メニューを出したいので以下のパッチをあて、再度 pxegrub をbuildする。
--- grub-0.97/stage2/asm.S.orig            
+++ grub-0.97/stage2/asm.S
@@ -98,7 +98,7 @@
        .string VERSION
 VARIABLE(config_file)
 #ifndef STAGE1_5
-       .string "/boot/grub/menu.lst"
+       .string "/srv/tftp/grub.conf"
 #else   /* STAGE1_5 */
        .long   0xffffffff
        .string "/boot/grub/stage2"
別の方法として、あらかじめメニューファイルを作っておいて、それを configure--enable-preset-menu=MENUFILE オプション を指定してpxegrubに取り込んでしまう手もある。

次に、ネットワーク・ブート用のカーネルのbuildをする。
通常カーネルから変更する .config は以下のとおり。
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y       
CONFIG_E100=y
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
make-kpkg でbuildしてカーネルdebを作る。

次に、母機の tftp/nfsサーバにクライアント用OS、Debian sarge を debootstrap でインストールする。
カーネルのdebとmodule-init-toolsのdebは別にコピーしておいて インストールする。
そしてクライアント用の環境も整える。
# mkdir /srv/tftp/thnkpd
# cp kernel-image-2.6.13.4_0.2.netboot_i386.deb /srv/tftp/thnkpd/
# cp module-init-tools_3.2-pre1-2_i386.deb /srv/tftp/thnkpd/
# debootstrap sarge /srv/tftp/thnkpd http://debianサーバ
# chroot /srv/tftp/thnkpd
# dpkg -i module-init-tools_3.2-pre1-2_i386.deb
# dpkg -i kernel-image-2.6.13.4_0.2.netboot_i386.deb
# base-config
# exit

# mknod /srv/tftp/thnkpd/dev/nfs b 0 255

# vi /srv/tftp/thnkpd/etc/fstab
内容
srv1:/srv/tftp/thnkpd  /      nfs   defaults  0  0
proc                   /proc  proc  defaults  0  0

# vi /srv/tftp/thnkpd/etc/hosts
適当に編集

# vi /srv/tftp/thnkpd/etc/network/interfaces
内容
auto lo eth0
iface lo inet loopback
iface eth0 inet dhcp

# vi /srv/tftp/grub.conf
内容
title Debian sarge NFSroot
root (nd)
kernel /srv/tftp/thnkpd/vmlinuz root=/dev/nfs rw ip=dhcp vga=0x305  

# vi /etc/exports
内容
/srv/tftp/thnkpd  192.168.100.4/30(rw,sync,no_root_squash)
/etc/init.d/nfs-kernel-server restart して、ThinkPad をネットワーク・ブートするとGRUBのメニューが出て、さらに選択したカーネルを 起動させると無事にDebianが起動した。 これは、Knoppixの他にもう1つのレスキューOSとして使えると思った。

(注意) tftpサーバに netkitのtftpdではなくtftpd-hpaを インストールしていて、in.tftpdの引数に -s オプションを指定している場合 (デフォルト) は、指定したパスがtftpクライアントから見るとルートディレクトリに なる(普通の感覚)ので、 GRUB menu.lstのパスの指定やGRUB kernel コマンドに指定するパスは上記の例から /srv/tftp を取り除いたものになる。
 

FreeBSD
  FreeBSD 6.0R も出ていることだしインストールしてみることにしたが、私のThinkPad でブートできるデバイスはUSB-CDRとEthernetブートの2つである。CDRを焼かずに何とか ネットワークからインストーラーを起動できないかとググってみると以下があった。
http://www.freebsd.org/doc/en_US.ISO8859-1/articles/pxe/

まず、pxebootを入手しなければならないのだが、ネットのどこかにないか 少し探してみたが見あたらないので自前でビルドすることにする。
幸いお古のマシンにFreeBSD 4.6Rが入っていたので、ひさびさに起動する。
cd /usr/src/sys/bootmake しても何もおこらない。 /usr/obj以下にターゲットが出来ていたためであった。
rm /usr/obj/usr/src/sys/boot/i386/{libi386,loader,pxeldr}/* して make -DLOADER_TFTP_SUPPORT すると /usr/obj/usr/src/sys/boot/i386/pxeldr/pxeboot が出来ていた。
これをtftpdサーバにコピーする。

次に、 boot.flp, kern1.flp, kern2.flp を配布元からダウンロード してきた。
mount boot.flp /mnt -t ufs -o loop,ufstype=44bsd,ro
でマウントしてみると、kernel.gz.bootmfsroot.gz があった。 同様に kern1.flp をマウントしてみると kernel.gz.aa, kern2.flpにはkernel.gz.ab があった。
cat kernel.gz.boot kernel.gz.aa kernel.gz.ab > kernel.gz
こんな感じでインストーラーのカーネルをつくる。 インストーラーのルートファイルシステムは mfsroot.gz そのまま。

/etc/dhcpd.conf の中で filename "pxeboot"; と指定して 起動してみると絶対パス /boot/loader.rc で tftpサーバに 取得しに行っていた。netkitの tftpd はこんなパスには対応していない。
pxebootを修正するかtftpdを直すかのどちらかであるが、 ここで絶対パス対応の tftpd-hpa を使うことにした。 ( in.tftpd の引数は -s /srv/tftp )
tftpサーバ上の関係ファイルリスト
/srv/tftp/pxeboot
/srv/tftp/boot/loader.rc
/srv/tftp/freebsd/kernel.gz
/srv/tftp/freebsd/mfsroot.gz
/srv/tftp/boot/loader.rc の内容
echo Loading Kernel...
load freebsd/kernel
echo Loading mfsroot...
load -t mfs_root freebsd/mfsroot
echo booting...
echo \007
echo initializing magic...
set vfs.root.mountfrom="ufs:/dev/md0c"
boot
ThinkPadをネットワークブートするとFreeBSDのインストーラーが立ち上がった。 40分ほどでインストールを終え、リブート。

ここで悲劇におそわれた。
いくら待っても起動しない。電源をOFFして再度ONしてもロゴ画面から進まない。 F1を押してもBIOS画面にならない。HDDを抜いて電源ONしてもだめだ。 Linuxをネットワークブートしてみても途中でカーネルパニックした。 ボタン電池も抜いてみたがだめだった。 BIOSがイッてしまった〜 orz
観念して、オークションでシステムボードを探し始める。

翌日、ThinkPadとFreeBSD 相性が悪いのかな〜 と思いググってみると、あるわあるわ。 BIOSバグってる。
IBMのサイトのBIOS更新プログラムの説明文には

−パーティションIDが n5h (n: 1以上) のハード・ディスクから、システムを
  起動できない。
以前さらっと目を通していたけど、気付かなかった。 ひとことFreeBSDと書いといてくれたらBIOSアップしただろうに。
古いHDDを取り付けて電源を入れると、かなり待ったあとWindowsが起動した。 よかった。そしてBIOSを更新した。
FreeBSDをインストールしたHDDを取り付けて起動すると、いきなりFreeBSD 6.0R が起動した。FreeBSDインストール時、MBRには何も入れないを選択したけど、 FreeBSDインストーラーは自分のパーティションをアクティブにしてしまっていた。 とりあえず無事起動したので安堵した。

(追記) pxebootLOADER_TFTP_SUPPORT なしでビルドすると、 pxeboot は NFS でファイルを取得しにいくらしい。 そうすれば netkitのtftpd でも対応できたはずだ。 特にDISKLESSマシンを構築する場合はその方がよいだろう。


TOPページにもどる   
更新: 20 Nov. 2005 
追加: 27 Oct. 2005