64bit 1FDLinux

x86-64 (amd64) 用の1枚のフロッピーディスク (FD) で起動する 64bit Linuxです。Linux も多くのファイルシステムやデバイスをサポートするようになって、どんどん大ききなって来ました。今回、x86-64 (amd64) 用に 64bit でコンパイルしたカーネルを1枚の FD で動作させることに挑戦してみました。カーネルのコンパイルに使用した .config を ここ におきます。カーネルのコンパイルになれた方は好きなように変更して下さい。コンパイルされた bzImage は 1,350KB になりました。ほとんど1.44MB のFD いっぱいです。 rvtl は Linux 上で動作する Tiny Basic インタプリタですが、init プロセスとして使うことができます。PID が 1 の場合(initプロセス)、/etc/init.vtl が実行されることを利用してシェルの代わりに使用します。/sbin/init を /bin/rvtl へのシンボリックリンクにして、カーネル起動後に直接 rvtl を起動します。Windows 環境でも FD からブートできれば、64bit の Linuxを試すことができます(実用性はありません)。

ダウンロードとFDへの書き込み

rvtl1fd64.img (1,440KB) をダウンロードします。

Linux を使っている場合は以下のように展開後、dd を使って FD に書き込みます。

dd of=/dev/fd0 if=rvtl1fd64.img

Windows の場合は、RawWrite for windowsで FD に書き込みます。 rvtl1fd64.img の場所を 「Image file」のテキストボックスで指定して 「Write」ボタンを押すだけです。

VirtualBox のフロッピー用のイメージとしても使用できます。このページのスクリーンショットは VirtualBox を使って取得しています。

実行

FD から起動するとスクリーンに以下のように表示されます。起動画面の下半分に Linux のコマンドと rvtl のコマンドとの対応が表示されます。RETURN キーを押すと指定可能な画面モードが表示されます。

使用可能なフレームバッファの解像度と色数が表示されます。使用可能なフレームバッファは環境によって異なりますが、640x480x16 や 1024x768x16 など表示可能な色(depth) は16ビットを指定してください。モード番号の前のアルファベットを入力して指定することもできます。

Linuxのカーネルから直接起動(プロセスIDが1)された場合、rvtl は /etc/init.vtl というファイルが存在すると、それをロードします。今回のFDイメージの /etc/init.vtl では次のようにしています。

|mo none /proc proc
/
|ca /proc/filesystems
/
|ca /proc/mounts
/
, /bin/ws
/
|cd /vtl
,="/bin/rvtl menu.vtl runq.vtl"

まず最初に proc ファイルシステムをマウントして、/proc 以下のファイルから システムの情報を取得できるように用意します。/proc/filesystems と /proc/mounts を表示した後、/bin/ws で画面に表示できる行数と桁数を表示、最後に子プロセスとして /bin/rvtl がmenu.vtlを実行してメニューを表示します。

カーネルとして linux-2.6.29.3 を使っているため、ブートロゴがペンギンの Tux ではなく、タスマニアデビルの Tuz が表示されます。

数字キーを入力してメニューを選択します。「1」はフレームバッファのデモが 実行されます。

この1FDLinux は 64bit のカーネルが init として 32bit の rvtl を起動します。 init は子プロセスとして、rvtlでmenu.vtl を実行しています。メニューで「8」を選択すると 64bit のプログラムが起動できることが確認できます。「(64bit Linux) hello, world」と表示するだけですが、一応64bit用の ELF64形式のプログラムです。

メニューで「9」を選択すると、rvtl を対話モードで実行します。「~」でメニューに戻ります。下の画面は、>="menu.vtl" で menu.vtl を読み込んで、0 でリストを表示したところです。

デスクトップ用の Linux もどんどん使いやすく高機能になっていて、 何をするにも不自由なく使えますが、低機能なところで遊んでみるのも 勉強になります。今回は rvtl でセグメント違反になる不具合で苦労しましたが、 原因は2.6.25以降のカーネルは、プロセスがメモリを取得(sys_brk)する場合に、 セキュリティのためにランダムなアドレスを使用する機能が追加されていました。 1FDLinux用に小さなカーネルとするために機能を削っていたのですが、 「機能を追加しない」というコンパイルスイッチを "Y" と指定すべきところを "N" としていました。rvtl が必要とする連続したメモリ空間が取得できなかった にもかかわらず、そこをアクセスしてセグメント違反が発生していました。 久しぶりにカーネルのソースを色々調べて、2.6.27以降のカーネルでは、 システムコールを実装している関数は SYSCALL_DEFINE マクロで定義されている ことなど、いい勉強になりました。 rvtl で今でも使っているsys_brk は 古代のシステムで使われていたシステムコールであることも知りました。