home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/Linux/手作りLinuxシステム/01. Boot from Floppy Disk (kernel-2.6.x)

技術/Linux/手作りLinuxシステム/01. Boot from Floppy Disk (kernel-2.6.x)

技術 / Linux / 手作りLinuxシステム / 01. Boot from Floppy Disk (kernel-2.6.x)
id: 941 所有者: msakamoto-sf    作成日: 2011-04-06 15:37:14
カテゴリ: Linux 

Linux Kernel 2.6.x を使ってフロッピーディスクから起動するLinuxシステムを作ってみます。


Kernel 2.6.x の入手とコンパイル

今回は linux-2.6.38.2.tar.bz2 を使います。
入手先:

$ pwd
/home/msakamoto/reduced.linux
$ ls
... linux-2.6.38.2.tar.bz2 ...
$ tar jxf linux-2.6.38.2.tar.bz2

出力用ディレクトリを作成し、KBUILD_OUTPUT環境変数を使ってmake menuconfigします。makeコマンドの詳細は "make help" で確認して下さい。

$ mkdir 01_boot_from_fd_2.6
$ export KBUILD_OUTPUT=`pwd`/01_boot_from_fd_2.6
$ echo $KBUILD_OUTPUT
/home/msakamoto/reduced.linux/01_boot_from_fd_2.6
$ cd linux-2.6.38.2/
$ make help
...
   # "make O=/foo/bar" としてmakeの都度ディレクトリを指定する方法もありますが、
   # 今回は使いません。
...
$ make allnoconfig
...
$ make menuconfig

CONFIG_IKCONFIG, EFL実行ファイルのサポート, FDのBlockDevice, Ext2ファイルシステムを追加します。
allnoconfigとmenuconfig後の差分:

$ diff .config .config.old
4c4
< # Wed Apr  6 09:33:17 2011
---
> # Wed Apr  6 09:31:49 2011
99,100c99
< CONFIG_IKCONFIG=y
< CONFIG_IKCONFIG_PROC=y
---
> # CONFIG_IKCONFIG is not set
369,370c368
< CONFIG_BINFMT_ELF=y
< # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
---
> # CONFIG_BINFMT_ELF is not set
395,405c393
< CONFIG_BLK_DEV=y
< CONFIG_BLK_DEV_FD=y
< # CONFIG_BLK_DEV_COW_COMMON is not set
< # CONFIG_BLK_DEV_LOOP is not set
<
< #
< # DRBD disabled because PROC_FS, INET or CONNECTOR not selected
< #
< # CONFIG_BLK_DEV_RAM is not set
< # CONFIG_CDROM_PKTCDVD is not set
< # CONFIG_BLK_DEV_HD is not set
---
> # CONFIG_BLK_DEV is not set
586,588c574
< CONFIG_EXT2_FS=y
< # CONFIG_EXT2_FS_XATTR is not set
< # CONFIG_EXT2_FS_XIP is not set
---
> # CONFIG_EXT2_FS is not set

ビルドします。 "01_..." にcdすれば、KBUILD_OUTPUT環境変数が空でもbuildできます。

$ cd 01_boot_from_fd_2.6
$ make
...
  HOSTCC  arch/x86/boot/tools/build
  BUILD   arch/x86/boot/bzImage
Root device is (253, 0)
Setup is 14008 bytes (padded to 14336 bytes).
System is 763 kB
CRC 43289aa6
Kernel: arch/x86/boot/bzImage is ready  (#1)

ここまで来ればコンパイルは成功です。

FDブート用のイメージを作成

2.6.xの場合、bzImageのままではFDブート出来ません。
SYSLINUXをインストールした上で

make fdimage

します。CentOS 5.5 の場合はパッケージとしてsyslinuxが提供されていますので、そのまま使います。入っていなければyumなどで適宜インストールしておきます。

# which syslinux
/usr/bin/syslinux
# rpm -qf /usr/bin/syslinux
syslinux-3.11-4

というわけで make してみます。

$ make fdimage
...
dd if=/dev/zero of=arch/x86/boot/fdimage bs=1024 count=1440
...
$ wc -c arch/x86/boot/fdimage
1474560 arch/x86/boot/fdimage

root側でloopbackマウントし、中身を確認してみます。

# mount .../x86/boot/fdimage /mnt/floppy -t msdos -o loop
# ls /mnt/floppy/
ldlinux.sys  linux  syslinux.cfg
# cat /mnt/floppy/syslinux.cfg
default linux

SYSLINUXでFDブートの場合はFAT16フォーマットされたFDの中にカーネルイメージが"linux"というファイル名で配置されます。
ここまで来ればVMwareなど適当な仮想マシン上で動かせます。

ところが、実際に動かしてみると分かりますが root デバイスが見つからずpanicになります。

SYSLINUXを使ったrootデバイスの設定

rdev(util-linuxパッケージ)を使う方法と "root=" カーネルパラメータを使う方法があります。
将来GRUBなど他のBootLoaderを使うときにもお世話になり、柔軟性もある後者の方法を紹介します。

今回はSYSLINUXをBootLoaderに使っているので、SYSLINUXの流儀でカーネルパラメータを指定します。FDブートの場合はFD直下の"SYSLINUX.CFG"ファイルを編集します。
参考:

SYSLINUX.CFG:

default linux


default linux
label linux
  kernel linux
  append root=0200

なお改行はDOSの流儀に従い

\r\n

にする必要があります。vimでは

:set fileformat=dos

とすれば自動でDOS改行に変換してくれます。

NOTE: "root="オプションですが、

root=/dev/fd0


root=/dev/VolGroup00/LogVol00

のようにデバイスファイル名を指定するパターンを多く見かけると思います。これらはinitrdがそうしたデバイスファイルを作っています。
今回はinitrdを使わないため、デバイスファイル名を指定できません。
そういう場合は今回のようにデバイスのmajor, minor番号をhexで指定できます。

というわけでもう一度VMwareなりBochsなりで動かしてみると、今度は

VFS: Insert root floppy and press ENTER

という表示で停止しました。

ではいよいよルートファイルシステムを作ってみます。

ルートファイルシステムの作成

今回作るルートファイルシステム:

  • 1.4MBフロッピーディスクサイズ
  • Ext2ファイルシステム
  • 最小限度のディレクトリとデバイスファイル

まず1.4MBフロッピーディスクサイズのデータファイルを作成します。

$ pwd
/home/msakamoto/reduced.linux/01_boot_from_fd_2.6
$ dd if=/dev/zero of=root_fs.img bs=1024 count=1440
1440+0 records in
1440+0 records out
1474560 bytes (1.5 MB) copied, 0.0135535 seconds, 109 MB/s

続いてExt2ファイルシステムを作成します。mke2fsコマンドで作成します。

$ su
# /sbin/mke2fs -F root_fs.img
mke2fs 1.39 (29-May-2006)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
...
#

loopbackマウントしてみます。

# mkdir /mnt/loop0
# mount root_fs.img /mnt/loop0 -t ext2 -o loop
# ls -l /mnt/loop0/
合計 12
drwx------ 2 root root 12288  4月  5 21:01 lost+found

/dev, /proc, /etc ディレクトリを作成します。

# pushd /mnt/loop0; mkdir dev proc etc; popd

最低限度必要なデバイスファイルを "cp -a" でコピーします。

# cp -a \
/dev/console \
/dev/tty[0-4] \
/dev/null \
/dev/zero \
/dev/urandom \
/dev/fd0 \
/mnt/loop0/dev/

これで「容器」は出来上がりました:

# tree /mnt/loop0/
/mnt/loop0/
|-- dev
|   |-- console
|   |-- fd0
|   |-- null
|   |-- tty0
|   |-- tty1
|   |-- tty2
|   |-- tty3
|   |-- tty4
|   |-- urandom
|   `-- zero
|-- etc
|-- lost+found
`-- proc

4 directories, 10 files

続いてBusyBoxを使って「中身」を入れます。root_fs.imgはloopbackマウントしたままにしておきます。

BusyBoxの導入

BusyBoxの紹介は下記参照:

今回は busybox-1.18.4.tar.bz2 を使いました。

ビルドの際はlinux kernelと同様cursesベースの設定ツールを使います。

$ pwd
/home/msakamoto/reduced.linux
$ ls
... busybox-1.18.4.tar.bz2 ...
$ tar jxf busybox-1.18.4.tar.bz2
$ cd busybox-1.18.4/
$ make help
Cleaning:
  clean                 - delete temporary files created by build
  distclean             - delete all non-source files (including .config)
  doc-clean             - delete all generated documentation

Build:
  all                   - Executable and documentation
  busybox               - the swiss-army executable
  doc                   - docs/BusyBox.{txt,html,1}
  html                  - create html-based cross-reference
...

BusyBoxの場合、makeコマンドの"O="オプションで別ディレクトリに出力できます。

$ pwd
/home/msakamoto/reduced.linux
$ mkdir 01_busy_box_build
$ cd busybox-1.18.4/
$ make O=../01_busy_box_build allnoconfig
...

これで一旦全オプションを無効化した設定になります。続いて "make menuconfig" で必要分だけ有効化します。

$ cd ../01_busy_box_build/
$ make menuconfig

今回は静的バイナリとしてビルドするので、下記オプションを有効にします。

Busybox Settings  --->
  Build Options  --->
    Build BusyBox as a static binary (no shared libs)

また mount コマンドを有効にするため、下記オプションを有効にします。

Busybox Settings  --->
  General Configuration  --->
    Enable Linux-specific applets and features

その他は最低限以下の機能を有効にします。

  • Core Utilities : 適当に最低限度のファイルシステム操作を出来るコマンドを選択しておきます。
  • Shell : ashで良いと思います。sh, bashにエイリアスできます。
  • Init Utilities : poweroff, halt, reboot, initを入れます。
  • Linux System Utilities : mount, umountを入れます。"-a"オプションを有効にしておきます。

あとはお好みで有効化し、ビルドします。

$ make
...
  LINK    busybox_unstripped
Trying libraries: crypt m
 Library crypt is not needed, excluding it
 Library m is not needed, excluding it
Final link with: <none>
  DOC     busybox.pod
  DOC     BusyBox.txt
  DOC     busybox.1
  DOC     BusyBox.html
$ ls
...
busybox*
busybox_unstripped*
...
$ wc -c busybox
716096 busybox
$ file busybox
busybox: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), \
 for GNU/Linux 2.6.9, statically linked, for GNU/Linux 2.6.9, stripped

ルートファイルシステムにインストールします。

$ su
# make CONFIG_PREFIX=/mnt/loop0 install

inittabを用意します。

# vim /mnt/loop0/etc/inittab

内容:

::sysinit:/etc/rcS

::askfirst:-/bin/sh
tty2::askfirst:-/bin/sh
tty3::askfirst:-/bin/sh
tty4::askfirst:-/bin/sh

::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r

BusyBoxのinittabの文法に付いてはソースコード "init/init.c" の末尾に書かれていますのでそちらを参照してください。
続いて "/etc/rcS" ファイルを用意します。

# vim /mnt/loop0/etc/rcS

内容:

#!/bin/sh
mount -a
/bin/sh

実行属性をつけるのを忘れずに。

# chmod +x /mnt/loop0/etc/rcS

最後にmountコマンドが使う fstab を用意します。

# vim /mnt/loop0/etc/fstab

内容:

/proc      /proc     proc   defaults
/dev/fd0   /         ext2   defaults

loopbackマウントを解除します。

# umount /mnt/loop0

あとはVMwareなりBochsを動かすホストマシンにroot_fs.imgを転送し、fdimageから立ち上げます。

VFS: Insert root floppy and press ENTER

と出たらroot_fs.imgに切り替え、ENTERを入力します。

上手く行けば下図のようにシェルが立ち上がり、mountコマンドを確認できます。


上手く動かない時は:

・カーネルをロードできない
→ "make fdimage"、および syslinux.cfg の修正までの作業工程を確認してみてください。

・ルートファイルシステムをマウントできない
→ Ext2ファイルシステムをbuilt-inしているか確認して下さい : CONFIG_EXT2_FS
→ Floppy Diskを有効化しているか確認して下さい : CONFIG_BLK_DEV, CONFIG_BLK_DEV_FD

・"/sbin/init"が起動しない
→ ホストマシンでルートファイルシステムを調整した後、ちゃんとumountしてからVMwareなりBochsに読み込ませているか確認して下さい。
→ "/etc/inittab", "/etc/rcS" の内容および "/etc/rcS" の実行権限を確認して下さい。
→ どうしても動かないようであれば、syslinux.cfg で "init=/bin/sh" パラメータを追加指定し、とりあえずシェルが立ち上がるか確認してみてください。

・その他、"VFS: ..." で始まるエラーメッセージが表示される
→ Kernelソースの "init" ディレクトリの中をエラーメッセージでgrepしてみてください。ルートファイルシステムやinitrd絡みのエラーメッセージはこの中でprintk()されている事が多いです。ソースを読んで、必要なら詳しいprintk()を自分で挿入しリビルドしてみるなどしていくと、原因が分かるかもしれません。

自分が嵌ってしまったのは「Ext2モジュール組み込み忘れ」と「ホストマシンでルートファイルシステムをumountせずに使ってしまった」の2点です。
umountを忘れたせいか、"/sbin/init"が起動せず困りました。
KGDBを有効化してホストマシンからのgdbデバッグも試みたのですが、あれこれ試してるうちに "init=" パラメータを追加すれば動くようになって、「じゃあ大丈夫じゃね?」と "init=" パラメータを外してKGDBも外して元に戻してみたらちゃんと動き始めたり・・・。
なかなか悩ましいです。ってかマジでなんでFDブートするためだけにこんなにハマらなくっちゃならないんだ・・・。

"make mrproper" と .config ファイル

色々試行錯誤する中でKernel Configurationを変更し、一旦全部クリーンしてからリビルドする場合があると思います。

make mrproper

すると Kernel Configuration を保存した ".config" も消してしまうので注意してください。(kernel-2.4.xの場合も同様)



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2011-04-29 15:38:22
md5:c210c959a31114e9e27adafc380a4b44
sha1:cc215c93b35cdd2a790c37fced076452c044f6b1
コメント
コメントを投稿するにはログインして下さい。