2014年6月6日金曜日

UNIX and 2BSD on PDP11(SIMH) その1

2010年ぐらいに初めてsimh-pdp11に触れてから,
ちょいちょいancient UNIXで遊ぶのですが毎回色々忘れてググってるのでメモ

まず普通にsoftware kitからUNIX v7を実行する方法
http://simh.trailing-edge.com/software.html
SIMHの公式ページの,Software Kitは様々なアーキテクチャの様々なOSをアーカイブしている
ここからUNIX v5〜v7を入手可能

uv7swre.zipをダウンロードしたら解凍し,
simh-pdp11(ArchLinux以外でビルドしたりしたらpdp11ってコマンドだと思う)をつかって,
$ simh-pdp11 UV7
で起動.UV7は起動スクリプト,simhのコマンド用のスクリプト
@プロンプトが表示されたら,
@boot
で起動
そして
:プロンプトで
:rl(0,0)rl2unix
として
RL11な0番目のディスクの,ルートにあるrl2unixというカーネルファイルを指定することで,
カーネルをブート

まずは#なプロンプトに落ちてシングルユーザーモードになるので,
^D(Ctrl-D)でマルチユーザーモードに移行
user:root password:root
でログイン可能.
あとはmailもつかえるし各種UNIXコマンドもつかえるし,困らない

exitコマンドではexitせず,^Dでログアウト

エミュレータの終了はCtrl-Eでsimhのプロンプトに抜けた後,simhのqコマンドを発行



次にUNIXv6をテープイメージからインストールする方法
http://d.hatena.ne.jp/oraccha/20101101/1288582382
を参考.oracchaさんが紹介されてるインストール手順のファイルは消えちゃってるけど,
http://shuntavista.jimdo.com/2013/01/05/unix-v6-%E3%82%92-simh-pdp11-%E4%B8%8A%E3%81%A7%E5%8B%95%E3%81%8B%E3%81%99%E3%83%A1%E3%83%A2-%E7%B0%A1%E7%95%A5%E7%89%88/
のブログで手順を公開されてる方がおられたので再現可能

http://gunkies.org/wiki/Installing_Unix_v6_(PDP-11)_on_SIMH
のほうでもテープからのインストール手順が公開されてる

http://wwwlehre.dhbw-stuttgart.de/~helbig/os/v6/dist.tap
がテープイメージ
上にあるsimhのSoftware KitでUNIX v6をインストールすると何故か
/usr/sysのカーネルソースが抜け落ちているが,このテープからインストールすると
完全な形で当時の環境が入手できる

ftp://ftp.ics.es.osaka-u.ac.jp/pub/mirrors/UnixArchive/PDP-11/Distributions/research/Dennis_v6/
阪大のUnixArchiveのミラーから入手できるUNIXv6のファイルセットからもカーネルソースは入手可能(これは普通にtarball形式)
このミラーには起動可能なsimh用の2.9BSDや2.11BSDだったりとか,
まだソフトウェアディストリビューションに過ぎなかった時代の2BSDとか,
はたまたPDP11を作ったDEC自身が開発したUNIXであるUltrixとか
資料的価値の高い物を大量にアーカイブしているので非常に興味深い

手順は,

simhの起動コマンドスクリプトでUNIXv6のテープイメージを起動するところからはじめる
d cpuはsimhのコマンドで機械語を直接メモリに置いてるが,
実機だとここでディップスイッチ操作でブートローダーを設定してたらしい.
今回はテープから起動するようにする

このスクリプトは途中で無限ループになるので,
Ctrl-Eで一度実行を停止した後にsimhのコマンドg 0で0番地に飛ぶ.

すると=プロンプトが出てくるはずである.
UNIXv6のmkfs(8) (そう,この時代はmkfsがsection VIIIだった!)は,
ファイルシステムを作る時先頭にブートローダーを埋め込む.
テープイメージはここでディスクへテープイメージを書き込むローダーが入っている
いくつか種類があるが,今回はtm(テープデバイス)からRK05なディスクデバイス(rk)に
インストールするので,tmrkコマンドで実行.
=tmrk
disk offset?
0
tape offset?
100
count?
1
=tmrk
disk offset?
1
tape offset? 101
count?
3999
と入力してテープからディスクにインストール.とりあえずこれでrk0ディスクにシステムインストール終了.
やっぱりCtrl-Eの後qで実行を終了し一度simhをリセット



ディスクからブート

とし先程同様ディップスイッチでブートローダーを設定しRK05ディスクからブートするか,

とsimhの機能(bootコマンド)で起動してしまうか.
どうやらsimhのbootコマンドはsimhの内部で汎用のブートローダーを持ってるらしい.
そしてbootコマンドのオペランドによってどのブートローダー(tmかrkかデバイスを見る)を呼ぶか判別し,呼び出してるらしいので,結局ディップスイッチ設定とやることは同じ

とりあえず起動したら@プロンプトが表示される.
UNIX v7と違いここで/にあるファイル名を指定することでカーネルを指定し,カーネルをブートしてしまう.
今回はRK05ディスクにインストールしてるのでrkunixというカーネルを起動.
user名はrootのみ最初は存在.passwordはなし.
起動するといきなりマルチユーザーモードログイン.つまりシングルユーザーモードにいかない.
また,これまた違う部分としてはcdコマンドが存在せずchdirコマンドでディレクトリ移動.
これは不便な上驚きである.

また,/devにmemやkmem以外のデバイスファイルがないのでmknodコマンドでデバイスファイルを
作成する必要がある.
現在もこのコマンドでデバイスファイル作成は可能だが,
当時はmknodやmkfs,mountにinitといった今だと/sbinや/usr/sbin相当のコマンドが/etc/に存在し,
/etcにはPATHが通ってないのでフルパスでコマンドを入力しなければならない.
/etc/mknod /dev/rk0 b 0 0
/etc/mknod /dev/rk1 b 0 1
/etc/mknod /dev/rk2 b 0 2
/etc/mknod /dev/mt0 b 3 0
/etc/mknod /dev/tap0 b 4 0
/etc/mknod /dev/rrk0 c 9 0
/etc/mknod /dev/rrk1 c 9 1
/etc/mknod /dev/rrk2 c 9 2
/etc/mknod /dev/rmt0 c 12 0
/etc/mknod /dev/lp0 c 2 0
/etc/mknod /dev/tty0 c 3 0
/etc/mknod /dev/tty1 c 3 1
/etc/mknod /dev/tty2 c 3 2
/etc/mknod /dev/tty3 c 3 3
/etc/mknod /dev/tty4 c 3 4
/etc/mknod /dev/tty5 c 3 5
/etc/mknod /dev/tty6 c 3 6
/etc/mknod /dev/tty7 c 3 7
chmod 640 /dev/*rk*
chmod 640 /dev/*mt*
chmod 640 /dev/*tap*
これでおーけー.
また,カーネルのリビルドもしておこう.
# chdir /usr/sys/conf
# cc mkconf.c
# mv a.out mkconf
# ./mkconf
rk
tm
tc
8dc
lp
done
# as m40.s
# mv a.out m40.o
# cc -c c.c
# as l.s
# ld -x a.out m40.o c.o ../lib1 ../lib2
# mv a.out /unix
mkconfコマンドで周辺機器(デバイス)は何があるのか自分で入力,設定し,
その後に/usr/sys/confに生成される各種ファイルをコンパイル,
最後に/usr/sys/lib1と/usr/sys/lib2とリンクすることでカーネルが生成される.
今回は/unixという名前で置いてるので,次回起動時にはrkunixでなくunixを指定すれば良い
なお,lib1やlib2の中のモジュールも含め完全にカーネルリビルドしたければ,
/usr/sysに移動しsh runを実行すると,runというシェルスクリプトがビルドしてくれる.
runにはすでにmkconfとその設定も記述されてしまっているので,
デバイスを増やしたり減らしたりしたければrun自体をedで編集する必要がある.

# dd if=/dev/mt0 of=/dev/rk1 count=4000 skip=4100
# /etc/mount /dev/rk1 /usr/source
# dd if=/dev/mt0 of=/dev/rk2 count=4000 skip=8100
# mkdir /usr/doc
# /etc/mount /dev/rk2 /usr/doc
これは必須ではないが,テープイメージからコマンド類のソースとドキュメントを
ddで持ってきて,別のディスク(rk1,rk2)にコピーし,これらをマウントさせておくと楽しくなると思われる.
ただ次回起動時にはマウントされなくなるので,

# cat >> /etc/rc
# /etc/mount /dev/rk1 /usr/source
# /etc/mount /dev/rk2 /usr/doc
として,rcスクリプト(起動時に実行)にmountコマンドを追加しておこう.
catとリダイレクトでテキストファイルを書く時は^D(EOF)で追記終了.

ここには書かないので先に挙げたURL達を参考にして貰いたいが,
dfコマンドは参照するデバイスがハードコードされてるので,
/usr/source/s1にあるdf.cの最初の関数のところを適当にdfで空き領域が見たいデバイスファイルに書き換えたり追加してリビルドしよう.
おそらく今回の場合は/dev/rk0,/dev/rk1,/dev/rk2を書く必要がある.

また,/usr/source/s2のsh.cの中の,
if(equal(cp1, "chdir"))としている行で,chdirをcpに変更した後リビルドすると,
今度からchdirコマンドでなくcdコマンドになってちょっぴり便利かもしれない.

これで初期設定は一度終了だが終了の前には
# sync
# sync
# sync
と適当にsyncを繰り返しディスクにバッファをフラッシュする必要がある
そうでないとまれにファイルやディスクが壊れる.
そしてCtrl-Eとqでsimhを終了

そしてインストールも終わったので起動スクリプトを変更しておく

これは今後毎回起動時にこれを呼ぶとする.
なお,カーネルに8dcを追加しこのスクリプトでもdcについていくつか設定したので,
simhでUNIXv6を起動してる最中はそのマシンのホストOSからtelnetでログイン可能である.
このスクリプトではdciを5555に設定してるのでポート5555番からtelnetログイン可能


……その2につづく