bochs in Debian/WSL2

Table of Contents

bochs in Debian/WSL2

前回、debianが提供するbochsが全く使い物にならず、WSL2の祟りじゃーと判 断しちゃった。それでArchLinuxで野良buildしたんだった。2分程の簡単なお 仕事ですって、分かっちゃたんで、debianでも、ちょっと試してみるかって気 になった。

configのパラメータはArchのそれを周到。cursesが無いぞと文句あり。ヘッダー ぐらい最初から入れておいて欲しいぞ。

Xも入いるはずなんだけど、これは無視された。特に文句を言われなかったん で、有効になっているものと思っていたんだ。でも、config.logを見ると、

configure:19518: checking for X
configure:19626: gcc -E  conftest.c
conftest.c:52:10: fatal error: X11/Xlib.h: No such file or directory
   52 | #include <X11/Xlib.h>

さりげなく、無視ですよ。で、出来あがったのは、

sakae@atom:~/xv6-public$ ldd /usr/local/bin/bochs
        linux-vdso.so.1 (0x00007ffdd1da4000)
        libncurses.so.6 => /lib/x86_64-linux-gnu/libncurses.so.6 (0x00007f8b33efb000)
        libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f8b33ec8000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f8b33cae000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f8b33bcf000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f8b33baf000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8b339cc000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f8b3415f000)

run

cuが必要になるので、apt経由で先に入れておく。

cu(1)                       General Commands Manual                      cu(1)

NAME
       cu - Call up another system

       When a connection is made to the remote system, cu forks into two  pro‐
       cesses.   One reads from the port and writes to the terminal, while the
       other reads from the terminal and writes to the port.

       -l line, --line line
            Name the line to use by giving a device name.  This may be used to
            dial  out  on  ports that are not listed in the UUCP configuration
            files.  Write access to the device is required.

不愛想なコマンドだけど、とても便利。なんでArchLinuxな人達は、これを無 視するのかねぇ。

早速、実行。

sakae@atom:~/xv6-public$ bochs -qf CPU
========================================================================
                        Bochs x86 Emulator 2.7
              Built from SVN snapshot on August  1, 2021
                Timestamp: Sun Aug  1 10:07:00 CEST 2021
========================================================================
00000000000i[      ] BXSHARE not set. using compile time default '/usr/local/share/bochs'
00000000000i[      ] reading configuration from CPU
00000000000i[      ] installing term module as the Bochs GUI
00000000000i[      ] using log file LOG

Bochs connected to screen "/dev/pts/14"
Next at t=0
(0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b          ; ea5be000f0
<bochs:1>

この画面になったら成功間違いなし。指示に従って、ラインを開いで準備する。

sakae@atom:~$ cu -l /dev/pts/14
Connected.

debuggerで一時停止してるのを、contすると、xv6が起動してくる。

Bochs VGABios (PCI) 0.8a 03 Jun 2021
This VGA/VBE Bios is released under the GNU
Please visit :
. http://bochs.sourceforge.net
. http://www.nongnu.org/vgabios
NO Bochs VBE Support available!

Bochs 2.7 BIOS - build: 08/01/21
$Revision: 14314 $ $Date: 2021-07-14 18:10:19 +0200 (Wed, 14 Jul 2021) $
Options: apmbios pcibios pnpbios eltorito rombios32

ata0 master: Generic 1234 ATA-6 Hard-Disk (   4 MBytes)
ata0  slave: Generic 1234 ATA-6 Hard-Disk (   0 MBytes)

Press F12 for boot menu.

Booting from Hard Disk...
cpu0: starting 0
sb: size 1000 nblocks 941 ninodes 200 nlog 30 logstart 2 inodestart 32 bmap start 58
init: starting sh
$

目出度くxv6のshellが起動してきた。

舞台裏

この裏で動いてきる通信の機構を見ていく。まずは、xv6と言う仮想マシン側 のシリアル制御。console.c

static void
cgaputc(int c)
{
  int pos;
    :
  if(c == '\n')
    pos += 80 - pos%80;
  else if(c == BACKSPACE){
    if(pos > 0) --pos;
  } else
    crt[pos++] = (c&0xff) | 0x0700;  // black on white

  if(pos < 0 || pos > 25*80)
    panic("pos under/overflow");

  if((pos/80) >= 24){  // Scroll up.
    memmove(crt, crt+80, sizeof(crt[0])*23*80);
    pos -= 80;
    memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos));
  }

  outb(CRTPORT, 14);
  outb(CRTPORT+1, pos>>8);
  outb(CRTPORT, 15);
  outb(CRTPORT+1, pos);
  crt[pos] = ' ' | 0x0700;
}

簡単な画面制御ってかカーソルの位置を考慮しつつ、出力してるのが分かる。

一方、bochsの方は、xv6な仮想マシンに接続される端末を模擬してる。そのソー スは、gui/term.ccだ。

static unsigned int text_rows = 25, text_cols = 80;
static unsigned long last_cursor_x, last_cursor_y;

// TERM implementation of the bx_gui_c methods (see nogui.cc for details)

void bx_term_gui_c::specific_init(int argc, char **argv, unsigned headerbar_y)
{

  FILE *old_stdin = stdin;
  FILE *old_stdout = stdout;

  scr_fd = open("/dev/ptmx",O_RDWR);
  if(scr_fd > 0){
    stdin = stdout = fdopen(scr_fd,"wr");
    grantpt(scr_fd);
    unlockpt(scr_fd);
    fprintf(stderr, "\nBochs connected to screen \"%s\"\n",ptsname(scr_fd));
  }

void bx_term_gui_c::clear_screen(void)
{
    :
#if BX_HAVE_MVHLINE
  if (LINES > (int)text_rows) {
    mvhline(text_rows, 0, ACS_HLINE, text_cols);
  }
#endif
#if BX_HAVE_MVVLINE
  if (COLS > (int)text_cols) {
    mvvline(0, text_cols, ACS_VLINE, text_rows);
  }

画面制御の代表部分を抽出してみた。bochsのdebuuger制御とかも、ここに出 てきて面倒な事になっている。それはそうと、根本にある、cursesの事が理解 不足なので、そちらを先に調べてみるか。

こういうのは、ncursesのマニュアルを調べるべきなんだろうけど、ドキュメ ントを大切にしない伝統が有るリナでは、役不足である。よって、ここからは OpenBSDにスイッチする事にする。

ncurses

https://invisible-island.net/ncurses/announce.html

Writing Programs with NCURSES and Python で Curses プログラミング

curses による端末制御

特殊な画面制御~GCCの画面制御ライブラリ

ncurses 使い方 man

ob$ cc z.c -lncurses

アッタッチして調査。

ob$ gdb -q a.out -p 51446
Reading symbols from a.out...
Attaching to program: /tmp/a.out, process 51446
Reading symbols from /usr/lib/libcurses.so.14.0...
Reading symbols from /usr/lib/libc.so.97.1...
Reading symbols from /usr/libexec/ld.so...
[Switching to thread 305077]
_thread_sys_read () at /tmp/-:3
3       /tmp/-: No such file or directory.
(gdb) bt
#0  _thread_sys_read () at /tmp/-:3
#1  0x045c0eb6 in _libc_read_cancel (fd=0, buf=0xcf7d2951, nbytes=1)
    at /usr/src/lib/libc/sys/w_read.c:27
#2  0x0531a0b4 in fifo_push (sp=0x66478a00)
    at /usr/src/lib/libcurses/base/lib_getch.c:211
#3  kgetch (sp=0x66478a00) at /usr/src/lib/libcurses/base/lib_getch.c:597
#4  _nc_wgetch (win=0x6648eaa0, result=0xcf7d29fc, use_meta=1)
    at /usr/src/lib/libcurses/base/lib_getch.c:435
#5  0x0531a726 in wgetch (win=0x6648eaa0)
    at /usr/src/lib/libcurses/base/lib_getch.c:558
#6  0x19a7fa6c in main () at z.c:25
(gdb) f 6
#6  0x19a7fa6c in main () at z.c:25
25                      key = getch();

内部的には、getch == wgetch なのね。ncursesの使い方 の方も述べておられ る様に、ほとんどX-Windowと同じらしい。

manページの補完

/usr/src/lib/libcurses/の中は、manの原稿で溢れている。 curs_addch.3 みたいな奴が、64個存在してた。こんなのmanコマンドで引くのは大変だ。

man curses すれば対応表は一応列挙されるけどね。そこで登場するのは、 emacs経由でのman引き。

In this buffer, type RET to select the completion near point.

7 possible completions:
curs_add_wch              curs_add_wchstr           curs_addch
curs_addchstr             curs_addstr               curs_addwstr
curs_attr
-=UU:%*-  F1  *Completions*   All   (1,0)      (Completion List) ---------------
Manual entry: curs_a ;; TABで補完

なお、manだけじゃなくて、womanなんて言う洒落たコマンドもあります。きち んとしたmanシステムの無いWindowsで重宝するらしいです。

Linux/OpenBSDでbochsの挙動違い

リナとBSDでbochsが動作する様になった。けど、 display_library にterm を指定した場合の挙動が違う。リナの方は起動時に、/dev/pts/14へ接続しろ とか言われるのに、OpenBSDでは、起動した端末がそのまま利用される。 そんなの無視でもいいんだけど、神は細部に宿ると言うから、深入りしてみる。

/dev/ptmx

前述した様にbochsの中では、/dev/ptmxを経由してtermとやりとりする様にコー ドが記述されている。このデバイスは何者? debianのマニュアルでは、

NAME
       ptmx, pts - pseudoterminal master and slave

       When a process opens /dev/ptmx, it gets a file descriptor for  a  pseu‐
       doterminal  master  and a pseudoterminal slave device is created in the
       /dev/pts directory.  Each file descriptor obtained by opening /dev/ptmx
       is  an independent pseudoterminal master with its own associated slave,
       whose path can be found by passing the file descriptor to ptsname(3).

xterm や sshを実現する為の必需品らしい。一方、OpenBSDには、そんなデバ イスは存在しないぞ。一体全体どうなってるの? これはもう、OpenBSD側を調 べる鹿。

gdb出来る様にする

残念ながら、portsで提供されてるbochsは、debug情報がstripされている。こ れはもう、自前でコンパイルしろって事だ。

checking for mvaddch in -lcurses... yes
Package curses was not found in the pkg-config search path
checking for mvaddch in -lncurses... yes
Package ncurses was not found in the pkg-config search path
checking for mvaddch in -ltermlib... yes
Package termlib was not found in the pkg-config search path
checking for mvaddch in -lpdcurses... no
Curses library not found: tried curses, ncurses, termlib and pdcurses.

前回のArchLinuxでbochsを作成した時に利用したconfigureを走らせると、こ んなエラーになった。ライブラリー存在するか、mvaddch関数を試してみたよ。 そしたら、lcursesとかlncursesとか、使えそうなのが発見できたよ。でも、 それらに対すとpkg-configが何ひとつとして発見できなかったよ。ちゃんとし たライブラリィーを入れて下さいってさ。これ、デフォでは、curses類が何も 入っていない、リナ向けの案内だ。昔からリナ中心で回っているのね。悔しい けど、これが現実だ。

じゃ、BSDの人達は、この現実にどう向き合ったか? きっとパッチが提供され てるはず。

ピッタリのパッチが有った。

ob$ patch </usr/ports/emulators/bochs/patches/patch-configure_in
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|the configure script tries to use pkg-config to get the LDFLAGS for
|ncurses, but we don't have .pc files for libncurses, so fall back to the
|hardcoded -lncurses.
|
|Index: configure.in
|--- configure.in.orig
|+++ configure.in
--------------------------
Patching file configure.in using Plan A...
Hunk #1 succeeded at 2929.
done

パッチが成功したら。それを元にもう一仕事。新らしいconfigureを作成。

ob$ autoconf configure.in >aa
Provide an AUTOCONF_VERSION environment variable, please
ob$ AUTOCONF_VERSION=2.69 autoconf configure.in >configure

これでconfigureは成功した。実際にコンパイルしてみると、別の所で更なる エラー。きりが無さそうなので、portsの中で、全部のパッチを適用したよ。 そしてそのツリー(usr/ports/pobj/bochs-2.7/bochs-2.7)を、そっくりその まま利用させて貰った。

portsをガシガシ利用するなら、こちらは必見だ。 OpenBSD Porter's Handbook

gdbしてみる

ob$ gdb -q bochs
Reading symbols from bochs...
(gdb) b bx_term_gui_c::specific_init
Breakpoint 1 at 0x1b56f9: file term.cc, line 181.
(gdb) r -qf CPU
Starting program: /var/OPT/bin/bochs -qf CPU
========================================================================
                        Bochs x86 Emulator 2.7
              Built from SVN snapshot on August  1, 2021
                Timestamp: Sun Aug  1 10:07:00 CEST 2021
========================================================================
00000000000i[      ] BXSHARE not set. using compile time default '/opt/share/bochs'
00000000000i[      ] reading configuration from CPU
00000000000i[      ] installing term module as the Bochs GUI
00000000000i[      ] using log file LOG

Breakpoint 1, bx_term_gui_c::specific_init (this=0x6433d000, argc=1,
    argv=0xcf7eafcc, headerbar_y=<optimized out>) at term.cc:181
181       put("TERM");

初めてCフラフラ語でBPしたよ。:: の左側がクラスで、右側がメソッドって理 解でいいのかな。クラス名がファイル名ってのに、ちと惑わされそう。ああ、 そうか! 親分は bx_term_gui.c だけど、子分には、term用とか、mac用とか、 色々と有るんだな。

(gdb) bt
#0  bx_term_gui_c::specific_init (this=0x6433d000, argc=1, argv=0xcf7eafcc,
    headerbar_y=<optimized out>) at term.cc:181
#1  0x1768b330 in bx_gui_c::init (this=0x6433d000, argc=1, argv=0xcf7eafcc,
    max_xres=800, max_yres=600, tilewidth=16, tileheight=24) at gui.cc:204
#2  0x175f93ea in bx_vgacore_c::init_gui (this=0x49167000) at vgacore.cc:175
#3  0x175f9099 in bx_vgacore_c::init (this=0x49167000) at vgacore.cc:99
#4  0x175b805a in bx_init_plugins () at plugin.cc:827
#5  0x175b9fa1 in bx_devices_c::init (this=0x38608170 <bx_devices>,
    newmem=0x38607c00 <bx_mem>) at devices.cc:362
#6  0x175ab287 in bx_init_hardware () at main.cc:1374
#7  0x175aa663 in bx_begin_simulation (argc=3, argv=0xcf7eb2e4) at main.cc:1014
#8  0x1768fcdf in bx_real_sim_c::begin_simulation (this=<optimized out>,
    argc=3, argv=0xcf7eb2e4) at siminterface.cc:887
#9  0x17697ba0 in bx_text_config_interface (menu=<optimized out>)
    at textconfig.cc:466
#10 text_ci_callback (userdata=0x0, command=CI_START) at textconfig.cc:1113
#11 0x1768fc83 in bx_real_sim_c::configuration_interface (this=0x4e7379c0,
    ignore=<optimized out>, command=CI_START) at siminterface.cc:880
#12 0x175a99c6 in bxmain () at main.cc:335
#13 0x175aa29b in main (argc=3, argv=0xcf7eb2e4) at main.cc:551

少しステップ実行する。

(gdb) n
183       io->set_log_action(LOGLEV_PANIC, ACT_FATAL);
(gdb)
187       if (!strcmp(SIM->get_param_string(BXPN_LOG_FILENAME)->getptr(), "-"))
(gdb)
200       initscr();
(gdb) n
205       start_color();
(gdb) n
206       cbreak();
(gdb) n
207       curs_set(1);
(gdb) n
208 max_  keypad(stdscr,TRUE);, tilewidth=16, tileheight=24) at gui.cc:204
(gdb)

check with source

ソース・レベルで、実行の流れを制御(実際は、コンパイルの可否)してる。そ のフラグ定義を確認。

[sakae@arch bochs-2.7]$ grep BX_DEBUGGER_TERM -r .
./gui/term.cc:#define BX_DEBUGGER_TERM (BX_DEBUGGER && !defined(__OpenBSD__))
./gui/term.cc:#if BX_DEBUGGER_TERM
./gui/term.cc:#if !BX_DEBUGGER_TERM
./gui/term.cc:#if BX_DEBUGGER_TERM
./gui/term.cc:#if BX_DEBUGGER_TERM

ふむ、OpenBSDだけ、別扱いする為のスイッチが定義されてた。

ついでなんで、もっと大本のスイッチも確認。確認先は、configureがウンウ ン言いながら作成した、config.hです。

[sakae@arch bochs-2.7]$ grep BX_DEBUGGER config.h
#define BX_DEBUGGER 1
#define BX_DEBUGGER_GUI 1
#if (BX_DEBUGGER || BX_GDBSTUB) && BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS

たまたま、ArchLinuxでの残骸を確認したけど、他意は無い。

ChatGPT

3月になってパンがまた値上がりしたと、女房がプンプンしてた。ならば自前 でパンを作れないか? 小麦って、用途別に色々あるよね。何が違うの? この所ChatGPTとも疎遠にしてたので、BAN防止の意味も兼ねて、聞いてみる。

Q: 麦の種類について質問します。うどん用の麦、パン用の麦、パスタ用の麦 の3種類ついて、それぞれの特徴を表形式で提示してください。

A: 以下は、うどん用の麦、パン用の麦、パスタ用の麦のそれぞれの特徴を簡単にまとめた表です。ただし、これは一般的な傾向であり、品種や地域によって異なることがあります。

特徴 うどん用の麦 パン用の麦 パスタ用の麦
用途 主にうどんやそばなどの麺に使用 パンの製造に使用 パスタの製造に使用
タンパク質含有量 比較的低い 中程度 中程度
グルテン含有量 低い 高い 中程度
グルテンの特性 やわらかく伸びやすい 強力でしっかりとした結合力 中程度の伸びやすさと強さ
粉の色 白っぽい 淡いクリーム色から茶色 やや淡いクリーム色
用途における影響 もちもちとした食感が求められる 膨らみやすく、ふんわりとした食感が求められる しっかりとした噛み応えが求められる

Q: これらの小麦と、ビール用の大麦との違いについて、2000文字で説明してください。

A: 小麦と大麦(ビール用の大麦)は、植物の異なる品種であり、それぞれ異なる用途に向けて栽培されています。以下は、これらの主な違いについての詳細な説明です。

1. 学名と分類:

  • 小麦: 小麦は主にTriticum属に属する穀物で、主要な種類にはティモシー小麦(Triticum aestivum)やデュラム小麦(Triticum durum)などがあります。
  • 大麦(ビール用の大麦): 大麦は主にHordeum属に属する穀物で、ビール製造に使用される大麦は一般にHordeum vulgare種の特定の品種です。

2. 用途:

  • 小麦: 小麦は主に食用として栽培され、パン、うどん、パスタなどの製品に使用されます。また、小麦粉は多くの調理に広く利用されます。
  • 大麦(ビール用の大麦): ビール用の大麦は麦芽として使用され、ビール醸造の主成分となります。大麦は麦芽に変わる過程でデンプンを酵素によってブドウ糖に変え、酵母がアルコールと二酸化炭素を生成する過程でビールが製造されます。

3. 栄養成分:

  • 小麦: 小麦は主に炭水化物を提供し、タンパク質も含まれていますが、小麦のグルテンは特に重要です。
  • 大麦(ビール用の大麦): ビール用の大麦は主にデンプン、タンパク質、ビタミン、ミネラルを含みます。大麦のアミノ酸組成は小麦と異なり、麦芽製造過程で特有の風味と色をビールに与えます。

4. 栽培条件:

  • 小麦: 小麦は広範囲にわたる気候と土壌条件で栽培されますが、好ましい条件により良好な収量と品質が得られます。
  • 大麦(ビール用の大麦): ビール用の大麦は一般に冷涼な気候で栽培され、特に適切な乾燥期間が必要です。これにより、大麦の穀粒が十分に発芽し、麦芽へと変化します。

5. 物理的特性:

  • 小麦: 小麦粉は比較的白く、小麦のグルテンは強力で伸びやすい性質を持っています。
  • 大麦(ビール用の大麦): 大麦は一般に小麦よりも茶色がかっており、大麦の穀粒は小麦のそれと比較して硬く、麦芽への変換が特有の風味を生み出します。

総括的に言えば、小麦とビール用の大麦はそれぞれ異なる特性を持ち、異な る産業や料理で使用されています。 小麦は主に食品加工において利用され、 大麦はビール醸造において独自の役割を果たしています。


This year's Index

Home