6845

こんな田舎なんで、コロナウィルスの影響は無いと思っていたんだ。ああ、感染エリアから疎開して来る人が居るから、確率の問題ではあるけどね。

この間の年金支給日に銀行へ行ったら、来銀記念のプレゼントを外で配っていたぞ。それはいいんだけど、ちらしを一枚渡された。次回の6月の支給は当面中止との事。 神奈川県みたいに、対面を気にしますからなあ。

消毒用のアルコールがさっぱり無いと思っていたら、濃度の高い酒が発売されてる。消毒代用アルコール、厚生労働省も太鼓判。酒と言っても飲酒禁止だな。マスクは大量生産とか言ってたけど、さっぱり出回らない。

この間、薬局の前を通ったら、駐車場が満車。そして長い行列。最後尾の人に、何を目当てですかって聞いたら、みんな並んでいるんで、私も並んでみましたですって。昔のソ連みたいだな。 程なくして、店の人が出てきて、今日はマスクの入荷はありませんと声を張り上げた。 雲の子を散らすように行列が解消された。

ロジスティクスがなってないぞ。アベノマスクもいいけど、あれはお子様用。普通のマスクはどうなった? 次なる手は10万円あげるから、特注マスクを自己調達しろって方針だな。まったくもう。

どこかの国みたいに、街頭を消毒車が走り回るようにしろよ。こちらは、丁度果樹園の消毒時期。消毒車が、無駄に噴煙をまき散らしながら畑を走り回っていたぞ。やる気なら、JAに指令して、全国から消毒車をかき集めなさいよ。 これは、農林水産省の大臣に命令一発だぞ。

それから、県境に関所を設けて、通行手形が無い人は、越境まかりならんぐらいは、やれよ。

bad gcc ?

前回の最後に、minixが起動したらだんまりになっちゃうって事を書いた。 minix本によれば、カーネルが起動すると、qemuのコンソールがクリアされて、メモリーの状況が報告されるとか。続いて、usrのフロッピーに入れ替えろの案内が出るらしい。

悔しいので、ソースのどのあたりで出してるか確認。 mm/main.c

  /* Print memory information. */
  mem1 = tot_mem/CLICK_TO_K;
  mem2 = (ram_base + 512/CLICK_SIZE)/CLICK_TO_K;        /* MINIX, rounded */
  mem3 = ram_clicks/CLICK_TO_K;
  printf("%c 8%c~0",033, 033);  /* go to top of screen and clear screen */
  printf("Memory size = %dK     ", mem1);
  printf("MINIX = %dK     ", mem2);
  printf("RAM disk = %dK     ", mem3);
  printf("Available = %dK\n\n", mem1 - mem2 - mem3);
  if (mem1 - mem2 - mem3 < 32) {
        printf("\nNot enough memory to run MINIX\n\n", NO_NUM);
        sys_abort();
  }

fs/main.c

  printf("Loading RAM disk from root diskette.      Loaded:   0K ");
   :
  printf("\rRAM disk loaded.  Please remove root diskette.           \n\n");

この後は、initが起動して、/etc/rcが動き出す。

/bin/getlf "Please insert /usr diskette in drive 0.  Then hit RETURN."
/etc/mount /dev/fd0 /usr
/usr/bin/date -q </dev/tty
cat /etc/message
/etc/update  &

現在時刻をmmddyyhhmmssって入力すると、ログインプロンプトが出て来るって流れ。これ、悔しいからソース読んでの机上のトレースね。

で、どうもカーネルが動き出すと、qemuのコンソールと言うかVGAな窓に自力でメッセージを出している。それまでは、BIOSに頼ってたから文字が見えたんだろう。自 力で文字出力が失敗。どうも、MC6845って石を上手くコントロール出来ない疑惑があるな。

話が逸れた。前回見つけたos5ってのを試してみる。環境はDebian(32Bit)

debian:os5-blog-20150405$ make
ld -o sys.bin kernel/sys.o kernel/intr.o lib/console_io.o kernel/main.o -M -s -T kernel/sys.ld -x > System.map
ld: kernel/intr.o: in function `intr_init':
intr.c:(.text+0x9): undefined reference to `_GLOBAL_OFFSET_TABLE_'
ld: kernel/intr.o: in function `intr_set_mask_master':
intr.c:(.text+0xb2): undefined reference to `_GLOBAL_OFFSET_TABLE_'
ld: kernel/intr.o: in function `intr_get_mask_master':
intr.c:(.text+0xd9): undefined reference to `_GLOBAL_OFFSET_TABLE_'
ld: kernel/intr.o: in function `intr_set_mask_slave':
intr.c:(.text+0xfe): undefined reference to `_GLOBAL_OFFSET_TABLE_'
ld: kernel/intr.o: in function `intr_get_mask_slave':
intr.c:(.text+0x125): undefined reference to `_GLOBAL_OFFSET_TABLE_'
ld: kernel/intr.o:intr.c:(.text+0x14a): more undefined references to `_GLOBAL_OFFSET_TABLE_' follow
make: *** [Makefile:19: sys.bin] Error 1

リンクに失敗してる。ぐぐってみると、

 CFLAGS  =       -Wall -Wextra -fno-pic

高級な機能はいらないので、機能を落とせらしい。これで無事に動いた。

undefined reference to _GLOBAL_OFFSET_TABLE_ (only when generating binaries)

gccで指定したアーキテクチャのバイナリをコンパイルする方法

皆さんも同じ苦労をされてるようで、それもこれも、gccの闇を覗いてしまったためなんでしょうな。

ってか、gccってリナのカーネルとユーザーランドをコンパイル出来る事が一番大事って考えている節がある。それ以外は、組み込み用途用って割り切って、オプションを五万と与えないと、希望の事が出来ないんだな。

んな事で、今度はDebian(64Bit)で試してみる。表示せずってか、ロードが終了しましたって所で止まって、カーネルのプロンプトが出てこない。

これって、64Bit用gcc系で、32bit系のアプリを作れっていう、組み込み技術者向けの問題です。Makefileに細工します。

CFLAGS  =       -Wall -Wextra -fno-pic -m32

.s.o:
        as --32 -o $@ $<

boot.bin: boot/boot.o
        ld -m elf_i386 -o $@ $< -T boot/boot.ld

sys.bin: kernel/sys.o kernel/intr.o lib/console_io.o kernel/main.o
        ld -m elf_i386 -o $@ kernel/sys.o kernel/intr.o lib/console_io.o kernel main.o -M -s -T kernel/sys.ld -x > System.map

run: fd.img
        qemu-system-i386 -drive format=raw,file=fd.img,if=floppy

CFLAGに32Bit用でコンパイル指示。アセンブラも同様に指示(何で、オプションに統一性が無いか? そりゃリナだからでしょう)リンカーも、elf_i386って言う、新発明なオプションを指示してあげます。もう、糞ったれな開発環境を十分に露呈してくれています。

最後のqemuの起動方法は、おまけです。こうすると、無様な警告を抑止出来ます。 これで、無事に64Bit環境でも動きました。万歳。

MC6845

VRAMを直接叩くって、その筋の人達みたい。

CRTC 昔は苦労が多かったんだなあ。その分色々な勉強が出来ただろうけど。

BIOS VRAM service INT 10H これは貴重な資料だな。BIOSなんて叩く事余り無いからね。 BIOSを使用しないでテキストを表示させるこちらは、nasmと言う、Windows怪では有名なアセンブラを使う例。 アセンブラもIntel式が有ったり、AT&T式が有ったり(gasと言うかリナのやつも同種)と、混沌とした世界です。出来れば避けて通りたい。

こういうページも見つかった。

カーネルデバッグで使うQEMUオプションチートシート

また、仮想化を徹底的に使い倒そうという人のチートシートも見つかった。面白いな。

qemu-4.1.1$ emacs ./roms/sgabios/sgabios.S にBIOSの内容が置いてあったぞ。

/*
 * int10h_isr
 *
 * entry point for int 10h
 *
 * save all registers, force return to chain to previous int10h isr
 * decide which function in ah needs to be dispatched
 *
 * ah = 0x00 set mode
 * ah = 0x01 set cursor type
 * ah = 0x02 set cursor position
 * ah = 0x03 read cursor position
 * ah = 0x04 read light pen position
 * ah = 0x05 set active display page
 * ah = 0x06 scroll active page up
 * ah = 0x07 scroll active page down
    :

滅多に見る事が無い、珍品の類。拝んでおけよ。

xv6-public

なんてのがリナの32Bit機に入っていた。250GもDiskが有るんで、何でも入れておくっていう、キャッシュの役割を担っている。

キャッシュから、64Bit機に持ってきて走らせようとしたら、mkfsってtoolが有るにも関わらず、無いと言うとんでも無いエラーを喰らった。何故なんだと3秒考えて、32Bitアプリは64Bit環境じゃ、普通には動かんわなあと気付いた。make clean; make qemuしたら、普通に動いた。やれやれ。

other os

作って理解するOSx86系コンピュータを動かす理論と実装

nasmを全面的に採用してるな。敷居が高いと思われる。

「30日でできる! OS自作入門」を読み終わった(実装した)

この方、手を動かしてLinuxに移植されてる。有り難い事に、 30daysOSで、成果物が公開されてた。 色々な所へのリンクも豊富。

ふと、qemuってどんなパソコンをサポートしてるか調べてみた。

sakae@pen:/tmp$ qemu-system-i386 -machine help
Supported machines are:
pc                   Standard PC (i440FX + PIIX, 1996) (alias of pc-i440fx-3.1)
pc-i440fx-3.1        Standard PC (i440FX + PIIX, 1996) (default)
 :
q35                  Standard PC (Q35 + ICH9, 2009) (alias of pc-q35-3.1)
isapc                ISA-only PC

マザーボードの事なのかな。

16 to 32

リアルモードからプロテクトモードへって事かな。ロングモードってのは64Bitを指すようだ。

プロテクティッドモードとGDT

xv6 のブートローダーを読む(良記事)

xv6のブートプロセスめも 32bit-modeになるまで

自作OSをとりまく環境の変化 さすが、さくらさん

そして、一歩前へ

大神 祐真 (Ohgami Yuma) (サークル名:へにゃぺんて)(今話題のクラスター、こういうのは大歓迎)

liumOS

二歩戻る。あれ、こんなフレーズの歌があったな。

しあわせは 歩いてこない
だから歩いて ゆくんだね
一日一歩 三日で三歩
三歩進んで 二歩さがる
  :
千里の道も 一歩から
はじまることを 信じよう

なかなか、元気の出る曲だな。ああ、曲と言えば、上を向いて歩こう なんてのを亜門さんが プロヂュースして、頑張ろうっていってる。アメリカだと、すきやきソング。

なんですきやきソングか? かの昔アメリカで日本ブームが生まれた。食い物が一番分かり易い。移住者がすき焼きを広めた。そして歌もついでにってんで、坂本九ちゃんが登場。 かくして、上を向いて歩こうが、すきやきソングと米国では認知されたそうな。知らんかったわい。

Intelの懺悔

最近のインテルは、レガシィなBIOSを葬る事に必死らしいな。同時に古い人が大好きなRS232CにもさよならさせようってんでUSBですかい。

で、CPUが、16,32,64Bitへと移行させる伝統の儀式を亡きものとして扱いたいので、新しいBIOSに移行しようとしてる。懺悔と言うより、汚い部分の隠蔽工作。USBを扱うのも素人には大変な事なので、全部まとめて新BIOSに押し込んじゃえって塩梅なんだな。

そうなると、 x86(i386)向けのOS作成日記みたいな苦労は(多分)不要になるはず。(ですよね)

Linux Insides ここに、メモリーの配置表が置いてあった。なかなかこういうの手に入らないので貴重。

losetup

OSの事ばかり書くと嫌われてしまうので、無理してリナの話題を引っ張り出した。 ループバックデバイスでISOファイルを簡単にマウント出来るって事から、BSDに有ったvnconfig相当なんて無いと思っていたよ。

でも、探してみたら、 ループバック・デバイスとはこんなのが見つかった。一人よがりを訂正しなければならないな。

と言う事で、losetupを試してみる。

debian:tmp$ bc
512 * 32
16384
^C
debian:tmp$ sudo losetup -o 16384 /dev/loop0 USB128M
debian:ntfs-3g_ntfsprogs-2017.3.23$ sudo src/ntfs-3g /dev/loop0 /mnt
ntfs_pread(): pos 0, count 512
Beginning bootsector check.
Checking OEMid, NTFS signature.
 :
Couldn't find name '.NTFS-3G' in pathname '.NTFS-3G/UserMapping'.
debian:tmp$ df
Filesystem     1K-blocks      Used Available Use% Mounted on
 :
/dev/loop0        127980      7976    120004   7% /mnt

USBメモリーをddでダンプした奴(USB128M)は、NTFSが始まっている場所が32セクター分ずれている。そこで、そのずれを計算して、ループバックデバイスを作る時にオフセットをかませる。

ntfs-3gは、ソースから --enable-debug で作っておいてインストールさせていない。よって、出来立てのホヤホヤをsrcの下で指定。デバック用なんで、ガチャガチャとメッセージが出て来るけど、最終的にマウント成功。

debian:~$ cd /mnt
debian:mnt$ ls -l
total 0
drwxrwxrwx 1 root root 0 Mar 14 06:13 'System Volume Information'/
debian:mnt$ echo First write > QzQzQz
debian:mnt$ ls
 QzQzQz*  'System Volume Information'/

適当に変な名前のファイルに書き込み

debian:~$ sudo umount /mnt
[sudo] password for sakae:
debian:~$ sudo losetup -a
/dev/loop0: [0042]:72493 (/tmp/USB128M), offset 16384
debian:~$ sudo losetup -D
debian:~$ sudo losetup -a

それからumountして、losetupを解除した。

次は、この変な名前のファイルが何処に有るか調べる。使う道具はhexeedit。普通にQzQzQzで探すと見つからない。そこで、内容で探してみる。

029BD0D0   20 00 00 00  00 00 00 00  06 00 51 00  7A 00 51 00   .........Q.z.Q.
029BD0E0   7A 00 51 00  7A 00 00 00  50 00 00 00  68 00 00 00  z.Q.z...P...h...
029BD0F0   00 00 00 00  00 00 01 00  50 00 00 00  18 00 00 00  ........P.......
029BD100   01 00 04 80  14 00 00 00  24 00 00 00  00 00 00 00  ........$.......
029BD110   34 00 00 00  01 02 00 00  00 00 00 05  20 00 00 00  4........... ...
029BD120   20 02 00 00  01 02 00 00  00 00 00 05  20 00 00 00   ........... ...
029BD130   20 02 00 00  02 00 1C 00  01 00 00 00  00 03 14 00   ...............
029BD140   FF 01 1F 00  01 01 00 00  00 00 00 01  00 00 00 00  ................
029BD150   80 00 00 00  28 00 00 00  00 00 00 00  00 00 02 00  ....(...........
029BD160   0C 00 00 00  18 00 00 00  46 69 72 73  74 20 77 72  ........First wr
029BD170   69 74 65 0A  00 00 00 00  FF FF FF FF  00 00 00 00  ite.............

ファイルの内容近くに、ファイル名っぽいのが伺える。ntfsってどんな奴? 知らない事を大雑把に伺うには、みんなの百科事典が良い。

NT File System

図書館戦争なんて本を読んでいたら、百科事典を使うコツをさりげなく紹介してたぞ。いきなり調べたい項目を調べるな、だそうだ。最終巻が索引になってるのので、まずそれを調べろと。 関連項目が出てる事が多いので、調査の奥行が拡がるよとな。図書司の常識らしい。

日付範囲が1601年1月1日を原点とするとな。ファイルスタンプは無駄に細かい(と感じる)100ns刻み。ファイル名はUTF-16で255文字が最大。なる程ね。そういう訳でQzQzQzって言うASCII文字の検索ではひっかからなかったのか。

いえね、ファイル名はASCII以外禁止って家訓がありましたから、そんな発想すらありませんでした。自分を基準に感がるなって事で大いに反省しましょ。

NTFS-3Gの事も紹介されてた。マイクロソフトと知的所有権の合意のもとで開発されていることから、他の実装と比較し、安定した読み書きが行えるとされる。なる程、こぞってみんなが使う訳だ。

関連項目に載ってた マスター ファイル テーブル ってのは、参考になるなあ。索引項目に相当するものが掲載されてて中々便利だな。

minixのファイルシステムからデータを読む

tc_adjtime

昔の積み残しだ。ntpdなやつ。OpenBSDなカーネルの中。

sys_adjtimeの挙動を簡単に追う。核心部分は下記 kern_tc.c

  tc_adjtime(int64_t *old, int64_t *new)
  {
          struct timehands *th;
          u_int gen;

B         if (old != NULL) {
                  do {
                          th = timehands;
                          gen = th->th_generation;
                          membar_consumer();
                          *old = th->th_adjtimedelta;
                          membar_consumer();
  =>              } while (gen == 0 || gen != th->th_generation);

gdbの結果。

(gdb) p *old
$1 = 4810000

ユーザーランド側の結果を簡単プログラムで確認した。

ob$ ./mon
4 810000

結局th_adjtimedeltaに調整残余がマイクロ秒単位で残っていたよ。

中途半端だけど、これぐらいにしとく。もうそろそろ、OpenBSDの新しいのが出てくる頃だからね。新しくなったら、再開しよう。