いものやま。

雑多な知識の寄せ集め

『OS自作入門』を読んでみた。(その6)

前回はリンカとリンカスクリプトを使ってアドレスの問題を解決した。

これで最初のOSっぽいプログラムは一応完了で、次はちゃんとフロッピーディスクの内容をメモリに読み込んで実行するIPL(Initial Program Loader)を作っていくことになる。
ただ、その前にもう一仕事。

フロッピーディスクのイメージ作成の改善

ここまではフロッピーディスクのイメージをまるごと作っていたわけだけど、この先はファイルも増えてくるし、ブートセクタに書き込むプログラム(IPL)とOS本体をちゃんと分けておきたいので、フロッピーディスクのイメージ作成の改善を。

具体的には、IPLとOS本体はそれぞれ別のリンク単位にして、ELFファイルおよびバイナリファイルをそれぞれ作成し、IPLはブートセクタとして、そしてOS本体はフロッピーディスクの最初のファイルとして、ディスクイメージに配置するようにしていきたい。

本ではここでedimgという著者お手製のツールを使っているんだけど、これはWindows用のプログラム。
Windows用だからそもそもMacだと動かないというのはあるんだけど、それを抜きにしても、なんともよく分からないツールを使うというのはあまり気が進まない。
(ネットで検索しても情報が出てこないから)
それしか方法がないのなら仕方ないけど、よく使われている標準的なツールがすでにあるなら、そっちを使った方がいい。

ちなみに、Macの場合、hdiutilというコマンドラインツールが標準としてあるみたい。
少し触ってみたけど、使えなくはなさそうな感じ。

ただ、問題点として、当然Macでしか使えないのでUnixではダメだし、もう少し重い問題として、ディスクイメージを操作するためにマウントすると、隠しファイルがコソッと作られてしまうというのがあった。
これから作ろうとしているIPLは、OS本体が一番先頭のファイルとして置かれていることが前提となっているので、これだとダメ。
もちろん、ちゃんとFATファイルシステムを扱えるようにIPLを作ればいいんだけど・・・それだと本よりかなり頑張らないといけなくなる。

そんなわけで、どうしたものかと調べていたんだけど、どうやらGNUのmtoolsに含まれるmformatおよびmcopyというツールを使ってやるといいみたいだった。

Mtools - GNU Project - Free Software Foundation

mtoolsはUnix環境でMS-DOSファイルシステムを扱うためのユーティリティで、mformatを使うとディスクイメージの作成が、そしてmcopyを使うとそのディスクイメージへのファイルのコピーが出来る。
(他にもいろいろツールが入ってる)

このmtoolsは多くのLinuxディストリビューションなら最初から入っているみたい。
なので、Linuxなら特に何もせず使えると思う。

ただ、Macには入っていないので、ビルドするところから。

mtoolsのビルド

毎度おなじみ、tarボールを落としてきて、展開。

$ tar zxvf mtools-4.0.18.tar.gz
$ cd mtools-4.0.18

で、あとは./configureしてmakeといきたいところだったんだけど、ちょっと問題があって、修正が必要だった。

そのままビルドすると、以下のようなエラーが出てしまう:

gcc  -DHAVE_CONFIG_H -DSYSCONFDIR=\"/usr/local/etc\" -DCPU_i386 -DVENDOR_apple -DOS_darwin16_6_0 -DOS_darwin16 -DOS_darwin -g -O2 -Wall -fno-strict-aliasing -I.  -I.  -c mainloop.c
mainloop.c:89:15: error: expected ')'
int unix_loop(UNUSED(Stream_t *Stream), MainParam_t *mp, char *arg,
              ^
./sysincludes.h:106:47: note: expanded from macro 'UNUSED'
#  define UNUSED(x) x __attribute__ ((unused));x

そこで、ネットで調べてmainloop.cを以下のように修正:

--- mainloop.org.c
+++ mainloop.c
@@ -86,7 +86,7 @@
 }

 int unix_dir_loop(Stream_t *Stream, MainParam_t *mp); 
-int unix_loop(UNUSED(Stream_t *Stream), MainParam_t *mp, char *arg,
+int unix_loop(Stream_t *Stream UNUSEDP, MainParam_t *mp, char *arg,
           int follow_dir_link);

 static int _unix_loop(Stream_t *Dir, MainParam_t *mp,
@@ -95,7 +95,7 @@
     return unix_dir_loop(Dir, mp);
 }

-int unix_loop(UNUSED(Stream_t *Stream), MainParam_t *mp,
+int unix_loop(Stream_t *Stream UNUSEDP, MainParam_t *mp,
           char *arg, int follow_dir_link)
 {
     int ret;

そして、単に./configureをすると、iconv関係のシンボルが見つからないというリンクエラーが出たので、以下のようにライブラリを追加で指定してビルド:

$ LIBS='-liconv' ./configure
$ make
$ sudo make install

これでOK。

mformatを使ったディスクイメージの作成

mtoolsがインストールできたので、さっそくmformatを使ってディスクイメージを作ってみる。

mformatを使ってディスクイメージを作るには、以下のようにすればいい:

$ mformat -f 1440 -B (ブートセクターのバイナリファイル) -C -i (イメージファイル名) ::

ちなみに、-f 1440は、サイズの指定。
あと、-vオプションを使うと、ボリュームラベルを指定できるみたい。
(指定しない場合、NO NAMEというボリュームラベルになるっぽい)

そして、一番気になるのは、最後の::の部分だと思う。

実は、mtoolsでは:というのが特別なドライブレター(AドライブのAやCドライブのCのこと)になっていて、:というドライブレターはディスクイメージのドライブレターになっている。
つまり、A:でAドライブ、C:でCドライブを指し示すように、::でディスクイメージのドライブを指し示すことになっている。
そして、::を使った場合には、一緒に-iオプションを使ってディスクイメージのファイルを指定してやる。

mcopyを使ったファイルのコピー

これでディスクイメージは作れるようになったので、あとはOS本体のバイナリファイルをこのディスクイメージにコピー出来さえすればいい。
それを行うには、mcopyを使う:

$ mcopy -i (イメージファイル名) (OS本体のバイナリファイル) ::

一番最後の::は前述の通り。
これでOS本体のバイナリファイルがディスクイメージにコピーされることになる。
(そして、一番最初のファイルとして配置される)


これでIPLを作っていくための準備は完了。
次はIPLを作っていく予定。

今日はここまで!

30日でできる! OS自作入門

30日でできる! OS自作入門