minix 1.1
プロジェクトXである。
スーパー望遠鏡「アルマ」の創造者たちって本で、紙上プロジェクトXしてたんだ。電波で宇宙を見る。日本では野辺山にあるデッシュが有名だ。けど、見たい帯域が水蒸気に邪魔されて、上手く観測出来ない。
歯痒い思いに駆られた天文学者達は、地球上で適した場所探し。チリに良い場所を見つける。雨がほとんど降らない乾いた大地、標高5000mの地。余りに星が沢山見えるものだから、★と★を結んで、星座って事が考えられない。逆に★が無い暗黒の空を結んで星座を連想する現地人。 そんな場所だ。
望遠鏡なら光学式だろう。いえ、可視光も電波の一種。周波数によってエネルギーが異なる。 高い周波数程エネルギーが高い。エネルギーは温度換算出来る。絶対0度ぐらいの周波数で観測したい。周波数で言うと、30GHzぐらい。じゃ、1MHzぐらいは、絶対0度を下回ってしまうのでは? よーく考えたら、反比例の関係になるんで、どこまで行っても絶対0度にはなれないって事なんだろうね。
反射鏡に相当するパラボラアンテナの精度が大事。ミクロン級に仕上げないと像がボケる。 軽くする必要が有るので素材はアルミ。切削用の工具を当てるだけで変形してしまうような代物。難題である。町工場の不屈の精神で、画期的な工作法を開発。治具を開発してるようなものだ。
太陽光が当たると温度上昇、逆に日陰は現地の寒い気温。どうする? 風の三菱の面目で、強い風で冷却。それに断熱材で断熱。南米で一番と言う塗装工事屋を探しだす。
望遠鏡を多数配置させて、その電波を合成。ってか、相関を取って雑音の除去。中身はFFTですって。そんな方法が有る事、初めて知った。
昔の天文学者は観測の為の望遠鏡作りでレンズ磨きから始めたそうな。今の天文学者は、電波望遠鏡の設計やら、THz級の30dBアンプに使う石(トランジスタ)まで、自作しちゃう。(どのメーカーも引き受けてくれない為)凄い世界だ箏。
minix 1.1
が膨大な(しかも分かり難い)qemuマニュアルのあんちょこになってて嬉しい。何でこんな事を急に書いてるかと言うと、minix本を見てて、1.1を動かそうと試みたんだ。
Downloads for previous releases
sakae@pen:/tmp/Intel-1.1$ qemu-system-i386 -nographic -fda floppy_disk1 SeaBIOS (version 1.12.0-1) iPXE (http://ipxe.org) 00:03.0 C980 PCI2.10 PnP PMM+07F90100+07ED0100 C980 Booting from Hard Disk... Boot failed: could not read the boot disk Booting from Floppy... Boot failed: not a bootable disk Booting from DVD/CD... Boot failed: Could not read from CDROM (code 0003) Booting from ROM... iPXE (PCI 00:03.0) starting execution...ok iPXE initialising devices...ok iPXE 1.0.0+git-20190125.36a4c85-1 -- Open Source Network Boot Firmware -- http://ipxe.org Features: DNS HTTP iSCSI NFS TFTP AoE ELF MBOOT PXE bzImage Menu PXEXT net0: 52:54:00:12:34:56 using 82540em on 0000:00:03.0 (open) :
こんな風にbootを失敗する。
C-a h C-a h print this help C-a x exit emulator C-a s save disk data back to file (if -snapshot) C-a t toggle console timestamps C-a b send break (magic sysrq) C-a c switch between console and monitor C-a C-a sends C-a QEMU 3.1.0 monitor - type 'help' for more information (qemu) info block floppy0 (#block151): floppy_disk1 (raw) Attached to: /machine/unattached/device[16] Removable device: not locked, tray closed Cache mode: writeback ide1-cd0: [not inserted] Attached to: /machine/unattached/device[23] Removable device: not locked, tray closed sd0: [not inserted] Removable device: not locked, tray closed
ここまで、あんちょこのおかげで、すんなり行った。感謝です。
sakae@pen:/tmp/Intel-1.1$ qemu-system-i386 -fda floppy_disk1 -boot a WARNING: Image format was not specified for 'floppy_disk1' and probing guessed . Automatically detecting the format is dangerous for raw images, write . Specify the 'raw' format explicitly to remove the restrictions.
明示的にbootをフロッピーディスクと指定しても、警告が出て来て、グラフィック画面の案内は上記と同様になる。Ctl-Alt-1(or 2)で、グラフィック画面をモニターとかにも切り替えられるけどね。
bootしないって事は、bootableなfloppyとして認めて貰えないって事かな。 マスターブートレコードを見ると、MBRの証拠として、ブートシグネチャ 0xAA55 が必要。そして4つの区画の一つにブートフラグが必要。
hexeditでFloppy_disk1を開いてみると、
000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 000001F0 00 00 00 00 00 00 00 00 E3 00 27 16 00 00 27 16 ..........'...'.
最後の27 16となってる所を、55 AA に変更して、ブートシグネチャを付加すると
Booting MINIX 1.1
一応、bootした。本の説明では、fsckが起動するはずなんだけど、だんまりである。書き換えてしまった元データに意味が有るんだな。
tools/build.cが、floppy1を作り上げるソフトらしい。
* bootblok: the diskette boot program * kernel: the operating system kernel * mm: the memory manager * fs: the file system * init: the system initializer * fsck: the file system checker
こんな風にシステムが配置され
* begins directly after it. The kernel, mm, fs, init, and fsck are each * padded out to a multiple of 16 bytes, and then concatenated into a * single file beginning 512 bytes into the file. The first byte of sector 1 * contains executable code for the kernel. There is no header present. * * After the boot image has been built, build goes back and makes several * patches to the image file or diskette: * * 1. The last 4 words of the boot block are set as follows: * Word at 504: Number of sectors to load * Word at 506: DS value for running fsck * Word at 508: PC value for starting fsck * Word at 510: CS value for running fsck
こんな風にパッチを当てるそうだ。オイラーが書き換えてしまった部分は、fsckのロードアドレス(0x1627)。これじゃ、暴走するに決まってる。
tools/MINIX/bootblok.s
final = 504 fsck_ds = 506 fsck_pc = 508 fsck_cs = 510 : mov ax,fsck_ds | set segment registers mov ds,ax | when sep I&D DS != CS mov es,ax | otherwise they are the same. mov ss,ax | words 504 - 510 are patched by build seg cs jmpi @fsck_pc | jmp to fsck
binary patch then run
上記のアセンブラーコードに出て来るfsck_csってのが、何処でも参照されていないんだ。不思議な事だ。全体をまとめてパッチを当てるプログラムが、tools/build.cに有るんで、パッチを当ててる部分、patch1()を見ておく。
read_block(0, ubuf); /* read in boot block */ ubuf[(SECTOR_SIZE/2) - 4] = sectrs + 1; ubuf[(SECTOR_SIZE/2) - 3] = ds; ubuf[(SECTOR_SIZE/2) - 2] = ip; ubuf[(SECTOR_SIZE/2) - 1] = cs; write_block(0, ubuf);
ipってのはインテル用語。普通語に直すとpcってなる。確かに書き込んでいるね。それしか分からない。
藁をも掴む気持ちで、C86/bootblok.asmの該当部分を見る。C86ってdirはMS-DOSで開発する人用のmakefileとかが入っている。同様にMINIXは頑張ってminixだけで何とかしようという人用。PCIXは、富豪ユーザー用で、PC-UNIXって開発システムを持ってる人用だそうだ。
mov ax,fsck_ds ; set segment registers mov ds,ax ; when sep I&D ds != cs mov es,ax ; otherwise they are the same. mov ss,ax ; This gets patched by 'build' jmp DWORD PTR cs:fsck_pc ; call the booted program ; its address is at 508 (dec)
あれれ、jmp命令がcs(コードセグメント)とセットになってるぜ。で、参照元は508番地だ。そうか、508-511番地に存在するcsとpcを使って、ジャンプしろとな。
だったら、508番地(0x1fc)ってのが、生で表れているはず。これを別な番地(0x1f0)に移して、そこに飛び先のセットを置いておけばいいじゃん。そうすれば、シグネチャ用の番地(0xAA55)を確保出来るよ。しばしバイナリアン御用達のhexeditと格闘。
sakae@pen:/tmp$ cmp -l Intel-1.1/floppy_disk1 m-1.1/floppy_disk1 181 374 360 499 0 47 500 0 26 511 47 125 512 26 252
Intel-1.1はオリジナル。m-1.1の方はパッチ済のやつ。
このcmpの出力で注意点が3つある。 アドレスが10進表記になってる。アドレスが1オリジンになってる。バイトの表示は古めかしい8進表示になっている。バイナリアンの仕様のdiffじゃ無いって事。
これからもcmpを多用するなら、バイナリアン仕様のcmpxでも作っておくかな。 変更場所は、/usr/src/usr.bin/cmp/regular.c
(void)printf("%6lld %3o %3o\n", (long long)byte, ch1, ch2);
ob$ ./a.out -l Intel-1.1/floppy_disk1 m-1.1/floppy_disk1 b4 fc f0 1f2 0 27 1f3 0 16 1fe 27 55 1ff 16 aa
これで走らせてみる
sakae@pen:/tmp/m-1.1$ qemu-system-i386 -nographic -fda floppy_disk1 Booting MINIX 1.1 Hit key as follows: = start MINIX (root file system in drive 0) f check the file system (first insert any file system diskette) l check and list file system (first insert any file system diskette) m make an (empty) file system (first insert blank, formatted diskette) h check hard disk file system Hit C-a c # QEMU 3.1.0 monitor - type 'help' for more information (qemu) change floppy0 floppy_disk2 Hit C-a c (qemu) f Checking diskette. Answer questions with y or n. Then hit RETURN Checking zone map Checking inode map Checking inode list blocksize = 1024 zonesize = 1024 20 Regular files 8 Directories 13 Block special files 3 Character special files 51 Free inodes 53 Free zones Hit key as follows: = start MINIX (root file system in drive 0) :
成功である。上のやつは、フロッピーディスクの2枚目(ルートファイルシステム)をチェックしたものである。どんなファイルが配置されてるかはlコマンドで確認出来るぞ。
じゃ本番
qemu-system-i386 -fda boot -monitor stdio
floppyを入れ替えるchangeってqemuのコマンドを画面切り替え、Ctl-Alt-1(or 2)して入力するのが面倒。なんで、モニター画面を常に別に出しておく。
それから、突然bootなんてのが出てきたけど、これはREADME_1.1に
Disk 1: Boot Disk Disk 2: Root File System Disk 3: /usr Disk 4: /user
こんな説明が有ったので、分かり易いように、名前を変えている。
で、= を押しても、残念ながらminixが起動してきーせん。諦めて、kernelの起動コードを眺めている。最初の部分は、アセンブラーコードになってる。
kernel/MINIX/mpx88.s
.text begtext: |*===========================================================================* |* MINIX * |*===========================================================================* MINIX: | this is the entry point for the MINIX kernel. jmp M.0 | skip over the next few bytes .word 0,0 | build puts DS at kernel text address 4 M.0: cli | disable interrupts mov ax,cs | set up segment registers mov ds,ax | set up ds mov ax,4 | build has loaded this word with ds value mov ds,ax | ds now contains proper value mov ss,ax | ss now contains proper value mov _scan_code,bx | save scan code for '=' key from bootstrap mov sp,#_k_stack | set sp to point to the top of the add sp,#K_STACK_BYTES | kernel stack call _main | start the main program of MINIX M.1: jmp M.1 | this should never be executed
kernel/C86/mpx88.asm これ参考値でMS-DOS用。
$main: Minix: ; this is the entry point for the Minix kernel. jmp short M0 ; skip over the next word(s) ORG 4 ; build writes the ds value at text address 4 ker_ds DW dgroup ; this word will contain kernel's ds value ; and it forces relocation for dos2out M0:cli ; disable interrupts mov ax,cs ; set up segment registers mov ds,ax ; set up ds mov ax,cs:ker_ds ; build has loaded this word with ds value mov ds,ax ; ds now contains proper value mov ss,ax ; ss now contains proper value mov dgroup:scan_cod,bx ; save scan code for '=' key from bootstrap mov sp,offset dgroup:k_stack ; set sp to point to the top of the add sp,K_STACK_BYTES ; kernel stack call main ; start the main program of Minix M1:jmp M1 ; this should never be executed
fsck.c/main
c = getc(); command = c & 0xFF; switch (command) { : case '=': return((c >> 8) & 0xFF);
これで、元に戻る? bootblkへか? いや違うかtools/MINIX/fsck1.sあたりかな。
call _main mov bx,ax | put scan code for '=' in bx cli mov dx,#0x60 mov ds,dx mov es,dx mov ss,dx jmpi 0,0x60 | jmp to kernel
MS-DOSのコードにヒントが無いか?
MINIX SEGMENT AT 60h ; This is where Minix is loaded kernel label byte ; absolute address 0000:1536d = 0060:0000h MINIX ENDS call main mov bx,ax ; put scan code for '=' in bx cli mov dx,60h mov ds,dx mov es,dx mov ss,dx jmp far ptr kernel ; direct jmp to kernel & start Minix
qemuのmonitorを使って、regsterの確認
(qemu) info registers EAX=00000700 EBX=00000016 ECX=00000000 EDX=000003da ESI=00000000 EDI=00000002 EBP=000062ac ESP=000062a0 EIP=0000449c EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0 ES =0000 00000000 0000ffff 00009300 CS =0060 00000600 0000ffff 00009b00 SS =0060 00000600 0000ffff 00009300 DS =0060 00000600 0000ffff 00009300 FS =0000 00000000 0000ffff 00009300 GS =0000 00000000 0000ffff 00009300 LDT=0000 00000000 0000ffff 00008200 TR =0000 00000000 0000ffff 00008b00 GDT= 00000000 00000000 IDT= 00000000 000003ff :
csやdsが指定した値になってるので、一応kernelは走っているっぽい。分かるのはここまでだなあ。残念ながらね。
fsdb
つまらないのでウダウダしてたら、fsdb なんて言う楽しそうなコマンドを見つけた。
ob# fsdb -f /dev/rvnd0c ** /dev/rvnd0c ** File system is already clean Editing file system `/dev/rvnd0c' Last Mounted on /mnt/ffs current inode: directory I=2 MODE=40775 SIZE=512 MTIME=Apr 13 09:00:56 2020 [847228541 nsec] CTIME=Apr 13 09:00:56 2020 [847228541 nsec] ATIME=Apr 13 08:42:56 2020 [419367358 nsec] OWNER=root GRP=wheel LINKCNT=2 FLAGS=0 BLKCNT=4 GEN=9b7cfeb fsdb (inum: 2)> ls slot 0 ino 2 reclen 12: directory, `.' slot 1 ino 2 reclen 12: directory, `..' slot 2 ino 3 reclen 488: regular, `aa' fsdb (inum: 2)>
どうやって使うかはman嫁。
from 6845
kernelが出すメッセージを拝めないのでソースを拝んでいたんだ。bootのメッセージはBIOSに依頼してた。それから、= キーの値をカーネルまで渡しているのは、キーコードが異なるマシン(オリベッティ製のPC)があるので、その判定をやってるためだった。
それはいいんだけど、qemuのコンソール(平たく言うとCRT)は、ビデオタイプなのね。で、そのコントロールをやってる石が 6845っていうものらしい。元ハード屋の性で、データシートを見たい。そんな事で、検索してたら、
こんな面白いページにたどり着いたぞ。