xxBIOS

前回、パケット解析するってんで、wiresharkを入れた。折角なんで色々遊んでいたら、 メニューが豆腐文字になってる事に気が付いた。

何故? MobaXtermのXサーバーに日本語フォントが入っていないのだろう。環境を英語に 切り替えてから起動したら、ちゃんと英語で表示された。wiresharkは、世界制覇を 成し遂げて、世界各国で愛用されてるんだな。納得。

toolsメニューにluaなんてのが有った。マニュアルの項目が有ったので選んでみると、 なんと、wiresharkのlua対応部分が、MobaXtermに表示されるじゃないですか。それはいいんだけど、 qでマニュアルを終了すると、

/usr/local/bin/xdg-open: x-www-browser: not found
/usr/local/bin/xdg-open: firefox: not found
/usr/local/bin/xdg-open: chrome: not found
/usr/local/bin/xdg-open: iceweasel: not found
/usr/local/bin/xdg-open: seamonkey: not found
/usr/local/bin/xdg-open: mozilla: not found
/usr/local/bin/xdg-open: epiphany: not found
/usr/local/bin/xdg-open: midori: not found
/usr/local/bin/xdg-open: konqueror: not found
/usr/local/bin/xdg-open: chromium-browser: not found
/usr/local/bin/xdg-open: google-chrome: not found
/usr/local/bin/xdg-open: www-browser: not found
/usr/local/bin/xdg-open: links2: not found
/usr/local/bin/xdg-open: elinks: not found
/usr/local/bin/xdg-open: links: not found
/usr/local/bin/xdg-open: lynx: not found

こんなにブラウザーを探し回っての挙句、w3mでも使ってくれたのかな? それとも、 MobaXtermに内蔵のやつかな。wiresharkも世界制覇をしようとすると、流行っている ブラウザーを覚えておかないといけないようで、大変だな。

w3mが中途半端に実装されてる(キーバインドがオイラーの常用してるのと違う?)みたいで 表示されてるページのURLが得られなかった。けど、表示内容を頼りに、

Chapter 10. Lua Support in Wiresharkが、見せたい所だと判明。

世間で流行りのPythonを選ばず、Luaを選ぶなんて、『月に変わって、おしおきよ』みたいで、 カッコいいな。

オイラーも、ミーハーで、Luaをやってみるかな。 お気楽 Lua プログラミング超入門 によると、非常に速いらしいですから。

Lua 5.2 リファレンスマニュアル

高速スクリプト言語 Lua を始めよう

こういうのも有ったし、探してる途中で、何回もYAMAHAの所へ連れていかれた。あそこの ルーターとかの拡張は Lua語で行うのね。ネットワークやるなら、Luaが合言葉に なってるんだな。どうでしゃろ > ISPの現場の方

boot msg

前回のOpenBSDでの仮想PCで、時計機能がメタメタ原因推測で、RTCが入っていない疑惑が 有った。

FreeBSD上のbhyveで動く仮想PCでは、何事も無かったがごとく、正常に動く。BIOSが 搭載されててRTCが機能してる事が予想される。

こう推理したなら、裏を取るのが刑事の仕事。何事も頭でっかちはいけません。 靴をすり減らし額に汗してこそ、真実に迫る事が出来るんですから。 (スマソ、相変わらず警察小説の読みすぎです)

下記が物的証拠、いや電磁的証拠になるかな? bhyveでOpenBSDを起動した時に コンソールに流れるメッセージを拾ってみた。

Copyright (c) 1982, 1986, 1989, 1991, 1993
        The Regents of the University of California.  All rights reserved.
Copyright (c) 1995-2016 OpenBSD. All rights reserved.  http://www.OpenBSD.org

OpenBSD 6.0 (GENERIC) #2148: Tue Jul 26 12:55:20 MDT 2016
    deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC
real mem = 251658240 (240MB)
avail mem = 240394240 (229MB)
warning: no entropy supplied by boot loader
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.6 @ 0xf101f (9 entries)
bios0: vendor BHYVE version "1.00" date 03/14/2014
acpi0 at bios0: rev 2
acpi0: sleep states S5
acpi0: tables DSDT APIC FACP HPET MCFG
acpi0: wakeup devices
acpitimer0 at acpi0: 3579545 Hz, 32 bits
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)

BHYVEバージョンのSMBIOSってのが、検出されています。後、細かい事だけど、ログインした時 の、バナーが、OpenBSDのそれと違ってた。

OpenBSD/amd64 (ob60.localdomain) (tty00)

login: root
Password:
Last login: Mon Oct 31 13:11:43 on tty00
OpenBSD 6.0 (GENERIC) #2148: Tue Jul 26 12:55:20 MDT 2016

OpenBSDをホストとした時は、GENERICじゃなくて、GENERIC.MP になってた。これは、 ホストのカーネルを使ってbootしたから、オイラーが改変したものになってるんだな。 ついでに、OpenBSDをホストとしてvmdから起動した時のdmsgを挙げておく。

OpenBSD 6.0 (GENERIC.MP) #0: Wed Oct 19 06:38:40 JST 2016
    root@ob.localdomain:/usr/src/sys/arch/amd64/compile/GENERIC.MP
RTC BIOS diagnostic error 20<config_unit>
real mem = 251658240 (240MB)
avail mem = 239656960 (228MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0
acpi at bios0 not configured

これを見ると、OSが起動した直後にRTC機能を黙って使ってて、後になってBIOSとかの 詳しい事を報告してるんだな。見比べてみると、よく分かる。こういうのもカーネル探検の 一つの方法なんでしょうかね。

更に参考に、OpenBSDのホスト起動時のdmesg冒頭付近。

OpenBSD 6.0 (GENERIC.MP) #0: Wed Oct 19 06:38:40 JST 2016
    root@ob.localdomain:/usr/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 1593769984 (1519MB)
avail mem = 1541029888 (1469MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.7 @ 0xe0010 (242 entries)
bios0: vendor Phoenix Technologies LTD version "6.00" date 07/02/2015
bios0: VMware, Inc. VMware Virtual Platform
acpi0 at bios0: rev 2
acpi0: sleep states S0 S1 S4 S5

この場合、ホストは、VMWAREが作り出す仮想PC上で動いている事になる。SMBIOSってのが 検出されてるな。これってBIOSのOSS版って事かな。核になるBIOSを元に、それとの インターフェースと言うか、設定変更出来るようにしたのが、Phoenixって会社って 事かな。

RTC

ちょいと調べてみた。

RT/CMOSから日時を取得する

BIOS interrupt call

こちらは、その際中に見つけたもの。色々コレクションされてて面白い。特にコアなんかが 懐かしくて。。。ああ、爺の昭和回顧ですな。

半導体コレクション展示会場

FreeBSDのbhyveがBIOSのRTCをサポートしてるって事は、RTCのICをエミュレートしてるって 事だな。今の所bhyveはamd64でしかサポートしていないんだから、その部分が書かれて いる部分は、推測出来る。

そう、あるべき場所は、/sys/amd64/vmm/io/ の中だろう。ピンポン。 vrtc.hとvrtc.cがそれだろう。コードを見る前に想像してみる。上で調べたように、 時刻の設定と読み出しが出来れば十分。リアルな石だと、水晶の分周比がどうだのとか、 カウンター部をどうするとかあるだろうけど、そこまで考える必要は無いな。

要求が有ったら、内部的に持ってる値を返すだけ。1Hz毎の割り込みで、ソフトで実現した カウンターを増加させていく。割り込みって事は、ハンドラーを登録したりする必要が 有るだろうね。

まずは、ヘッダーファイルを見て概要を掴む。大体予想通りだけど、nvramのr/wも 用意されてるようだ。

コードを見ると、冒頭付近に、RTC-IC相当のリソースが定義して有った。これらは、 どんなタイミングで作成されるの? 一つ上の階層に、vmm.cが有り、そこで、vrtc_initに よって作られるんだ。他にどんな資源が必要?

/*
 * Initialization:
 * (o) initialized the first time the VM is created
 * (i) initialized when VM is created and when it is reinitialized
 * (x) initialized before use
 */
struct vm {
        void            *cookie;                /* (i) cpu-specific data */
        void            *iommu;                 /* (x) iommu-specific data */
        struct vhpet    *vhpet;                 /* (i) virtual HPET */
        struct vioapic  *vioapic;               /* (i) virtual ioapic */
        struct vatpic   *vatpic;                /* (i) virtual atpic */
        struct vatpit   *vatpit;                /* (i) virtual atpit */
        struct vpmtmr   *vpmtmr;                /* (i) virtual ACPI PM timer */
        struct vrtc     *vrtc;                  /* (o) virtual RTC */
        volatile cpuset_t active_cpus;          /* (i) active vcpus */
        int             suspend;                /* (i) stop VM execution */
        volatile cpuset_t suspended_cpus;       /* (i) suspended vcpus */
        volatile cpuset_t halted_cpus;          /* (x) cpus in a hard halt */
        cpuset_t        rendezvous_req_cpus;    /* (x) rendezvous requested */
        cpuset_t        rendezvous_done_cpus;   /* (x) rendezvous finished */
        void            *rendezvous_arg;        /* (x) rendezvous func/arg */
        vm_rendezvous_func_t rendezvous_func;
        struct mtx      rendezvous_mtx;         /* (o) rendezvous lock */
        struct mem_map  mem_maps[VM_MAX_MEMMAPS]; /* (i) guest address space */
        struct mem_seg  mem_segs[VM_MAX_MEMSEGS]; /* (o) guest memory regions *\
/
        struct vmspace  *vmspace;               /* (o) guest's address space */
        char            name[VM_MAX_NAMELEN];   /* (o) virtual machine name */
        struct vcpu     vcpu[VM_MAXCPU];        /* (i) guest vcpus */
};

これが、仮想PCを表す構造体。かの昔、IBMが、PC/ATって言って、公開したやつだな。 果たして、OpenBSDでは、どうなっているのだろう?

OpenBSD on QEMU

OpenBSDのゲストをOpenBSDで動かす、もう一つの手が有ったな。2015年の9月に OpenBSD探検で使ったQEMUだ。

ホストマシンも64Bitになった事だし、動作もきびきびしてる事だろう。期待を込めて 入れてみた。

QEMUのリダイレクトの方法が、昔と違っていて、焦ったぞ。下記は、起動スクリプト。

[ob: expl]$ cat boot
#!/bin/sh
qemu-system-x86_64 -m 256M  -net user,hostfwd=tcp::2022-:22 \
  -net nic disk

MobaXtermが使えるので、vgaなコンソールでも気にならない。起動させたら、後は忘れて しまってもよい。そして、sshでログインする。

[ob: expl]$ ssh -p 2022 localhost
sakae@localhost's password:
$ dmesg
OpenBSD 6.0 (GENERIC) #2148: Tue Jul 26 12:55:20 MDT 2016
    deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC
real mem = 251527168 (239MB)
avail mem = 239603712 (228MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.8 @ 0xf6a40 (9 entries)
bios0: vendor SeaBIOS version "rel-1.9.1-0-gb3ef39f-prebuilt.qemu-project.org" date 04/01/2014
bios0: QEMU Standard PC (i440FX + PIIX, 1996)
acpi0 at bios0: rev 0
acpi0: sleep states S3 S4 S5
 :
nvram: invalid checksum
clock: unknown CMOS layout

QEMUのプロジェクトが提供してる SeaBIOSってのが使われているみたいだ。最後の2行が 気になるけど、 ちょっと使ってみた限りでは、普通に使えるな。

$ df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/wd0a      738M    411M    290M    59%    /
$ ifconfig em0
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        lladdr 52:54:00:12:34:56
        index 1 priority 0 llprio 3
        groups: egress
        media: Ethernet autoselect (1000baseT full-duplex)
        status: active
        inet 10.0.2.15 netmask 0xffffff00 broadcast 10.0.2.255

OpenBSD探検をやる為の最低限のインストールを行った。ネットは、vboxと同じような 構成だな。

で、カーネルの実行を覗き見るために、debugオプションを付けてコンパイルだな。 今回は、母艦と言うかホストもOpenBSDなんで、そこの資源を使ってコンパイル しちゃえ。探検用のゲストOSの名前は、explって事にした。

コンパイル手順は、去年と同じなんだけど、ちょっと工夫をしておいた。

make depend
COPTS="-O0 -gdwarf-2 -g3" make

探検中にマクロの参照を容易にするおまじない。コンパイルが終了すると、bsd.gdbって言う debug情報入りの巨大なカーネル(289M)が作成される。そしてそこからstripして、ぜい肉を 落としたカーネルが最後に作成される。こちらは、12.9Mの大きさだった。

よくTVでやってる、ダイエット特集に比じゃありませんで。ここは、大いに驚く所です。 そして、最後の仕上げとして、小さい方のカーネルをゲスト側に転送しておこう。

さて、いよいよ探検。上記のbootスクリプトに -s オプションを付けて起動。 ログイン出来たら、コンパイルした所に移動して、ホスト側からgdbを立ち上げる。 なお、コンパイルの残骸、*.o *.d は、不要なので削除しておく。

[ob: EXPL]$ pwd
/sys/arch/amd64/compile/EXPL
[ob: EXPL]$ egdb bsd.gdb
GNU gdb (GDB) 7.11
   :
Reading symbols from bsd.gdb...done.
(gdb) target remote :1234
Remote debugging using :1234
acpicpu_idle () at ../../../../dev/acpi/acpicpu.c:1170
1170                    break;
(gdb) b sys_gettimeofday
Breakpoint 1 at 0xffffffff8123ae66: file ../../../../kern/kern_time.c, line 323.
(gdb) c
Continuing.

Breakpoint 1, sys_gettimeofday (p=0xffff800007262468, v=0xffff800007273e60,
    retval=0xffff800007273eb0) at ../../../../kern/kern_time.c:323
323     {

OpenBSDの最新式gdbは、egdbって名前になってるのでそれを使う。OSに備え付けのgdbを 使うと、emacs上から正しく操作できない。システムコールは、接頭語として、sys_ が 付くので、焦らない事。

(gdb) bt
#0  sys_gettimeofday (p=0xffff800007262238, v=0xffff80000726ee60,
    retval=0xffff80000726eeb0) at ../../../../kern/kern_time.c:323
#1  0xffffffff81479ef2 in mi_syscall (p=0xffff800007262238, code=67,
    callp=0xffffffff81b740d0 <sysent+1072>, argp=0xffff80000726ee60,
    retval=0xffff80000726eeb0) at ../../../../sys/syscall_mi.h:77
#2  0xffffffff81479d0b in syscall (frame=0xffff80000726ef20)
    at ../../../../arch/amd64/amd64/trap.c:568
#3  0xffffffff810017fb in Xsyscall ()

ゲスト側OSを停止すると、勝手に接続が切れる。

(gdb) c
Continuing.
Remote connection closed
(gdb) q

これで、探検のための環境構築とリハビリを終了したな。

QEMUのBIOS

QEMUでポートフォワーディングをやる為のオプションを調べていたんだ。そしたら、 BIOSのオプションに出くわした。一部を抜粋すると、

       -smbios file=binary
           Load SMBIOS entry from binary file.

       -smbios
       type=0[,vendor=str][,version=str][,date=str][,release=%d.%d][,uefi=on|off]
           Specify SMBIOS type 0 fields

       -smbios
       type=1[,manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
           Specify SMBIOS type 1 fields
          :

こんな具合に、type=2,3,4,17 と指定出来るみたい。一体これは何を意味するの?

調べてみたけど、ようわからん。これ以上はソース嫁みたいですよ。深入りは止しておこう。