Display
漢字console
前々囘だったか、コンソールの機能を調べている時、FreeBSDのコンソールが国際化された事を知った。それって、漢字ROMに相当するフォントを設定すれば日本語を表示出来るよって事だねぇ。
かの昔、FM-11と言うパソコンを使ってた。日本語は貧弱なカタカナしか表示出来無いやつ。で、うん万円だか出して漢字ROMを装着すると、漢字が表示出来る。指を咥えてパソコンショップの前をうろうろしてたなあ。
現代なら無料で出来るはず。少し調べてみた。
Newcons とか newcons and CJK fonts
日本語BDFフォントを変換してFreeBSD 10.xのvt(4)コンソールで使う
こんな資料が出てきたぞ。肝心のROMは Index of ~emaste/newcons から b16.fnt を頂いてきて /usr/share/vt/fonts に装着すればよいらしい。まだ正式版数は出ていないからアングラ版だけど。
そして、下記でそのフォントを使うぜいって指示を出す。
# /usr/sbin/vidcontrol -f b16.fnt
いうまでもないけど、使えるのは指定した仮想コンソールのみだ。別の仮想コンソールに切り換えてしまうと、有効にはなっていない。何処でも漢字にしたかったら、 /etc/rc.conf に指定しておくと良いらしい。
font8x16="b16.fnt"
kldload vesa
kldload: can't load vesa: module already loaded or in kernel
vidcontrol -i mode
mode# flags type size font window linear buffer
------------------------------------------------------------------------------
上の説明では、vesaをロードした後、vidcontrolすると、使えるモードが出てくるらしいんだけど、無しのつぶて。
VGA
で、気が付くと、コンソールの表示系については知識が全くない。前回はキーボードをやったので、今度は表示系。何の根拠も無いけど(qemuのdisplayを三田時、CRTコントローラの代わりにVGAが鎮座してたって野生の勘)調べてみる。 VGA Function
ThinkpadでFreeBSDを起動した時のデバイス探査の結果
[sakae@fb ~]$ dmesg | grep VGA vtvga0: <VT VGA driver> vgapci0: <VGA-compatible display> port 0x1800-0x1807 mem 0xf2400000-0xf27fffff,0xd0000000-0xdfffffff irq 16 at device 2.0 on pci0 agp0: <Intel GM45 SVGA controller> on vgapci0 vgapci1: <VGA-compatible display> mem 0xf2100000-0xf21fffff at device 2.1 on pci0
こんな風になってて、この状態でコンソールが漢字を表示してくれたから、VGAが表示器って事は確定だな。
詳しい事は、vga(4), vgl(3) だな。
[sakae@fb ~]$ sysctl -a | grep vga VT(vga): resolution 640x480 machdep.vga_aspect_scale: 100 dev.vgapci.0.%pnpinfo: vendor=0x8086 device=0x2a42 subvendor=0x17aa subdevice=0x213a class=0x030000
vendorが8086ってのは、ごり押しで取得したナンバープレートみたいなもので、勿論それはインテルさんを表している。
何処に、ドライバーが有るか探してみる。
sakae@fbox:/sys/dev $ grep GM45 -rIl . ./drm2/drm_pciids.h ./agp/agp_i810.c
wsconsctl
そういう時は、OpenBSDで確認。と言っても全く同じコマンドが有るわけではないので、類似品で確認してみる。
ob$ doas wsconsctl -a : display.type=vga-pci display.fontwidth=8 display.fontheight=16 display.emulations=vt100 display.screentypes=80x25,80x25bf,80x40,80x40bf,80x50,80x50bf :
そうだよな、こういうのが出てきて欲かった。
frame buffer
取り敢えず、漢字コンソールでw3mが使えるようになったんで、これってX無しだよなとプチ感激してるんだけど、Xに有ったスクリーンセーバーはコンソール版にはないかな? かすかな記憶を辿って、見つけ出したドライバー。 splash(4)
Screen saver
daemon_saver.ko Animated BSD Daemon screen saver.
dragon_saver.ko Draws a random dragon curve.
Screen saver modules can be loaded using kldload(8):
kldload logo_saver
The timeout value in seconds can be specified as follows:
vidcontrol -t N
指示通りにやってみたけど、動かない。大体どこに入ってる?
例えば、こんな所に有った。ひょっとしてscじゃないと動かない? 野生の勘が冴えてる。vtでは、まだサポートされていないってさ。
/sys/dev/syscons/daemon/daemon_saver.c
static u_char *daemon_pic[] = {
" , ,",
" /( )`",
" \\ \\___ / |",
" /- _ `-/ '",
" (/\\/ \\ \\ /\\",
" / / | ` \\",
" O O ) / |",
" `-^--'`< '",
" (_.) _ ) /",
" `.___/` /",
" `-----' /",
"<----. __ / __ \\",
"<----|====O)))==) \\) /====",
"<----' `--' `.__,' \\",
" | |",
" \\ / /\\",
" ______( (_ / \\______/",
" ,' ,-----' |",
" `--{__________)",
NULL
};
だったら、古い奴に切り換えてみよう。切り換えはsysctlじゃ出来無くてて、起動時に設定だ。
sakae@fbox:~ $ cat /boot/loader.conf kern.vty=sc
後は任意なタイミングで
kldload daemon_saver vidcontrol -t 600
とかやると、10分何もしなければ、ダエモン君が動き出す。右から左へ、左の壁にぶつかると向きを反転してジャンプしながら動く。ついでに、ホスト名とuname -or 相当の案内がフローティングで表示されたよ。これは楽しい。
vidcontrol -i mode
mode# flags type size font window linear buffer
------------------------------------------------------------------------------
24 (0x018) 0x00000021 T 80x25 8x16 0xb8000 32k 32k 0x00000000 32k
30 (0x01e) 0x00000021 T 80x50 8x8 0xb8000 32k 32k 0x00000000 32k
256 (0x100) 0x0000000f G 640x400x8 P 8x16 0xa0000 64k 64k 0xe0000000 250k
257 (0x101) 0x0000000f G 640x480x8 P 8x16 0xa0000 64k 64k 0xe0000000 300k
258 (0x102) 0x0000000b G 800x600x4 4 8x16 0xa0000 64k 64k 0x00000000 234k
:
330 (0x14a) 0x0000000f G 1152x864x16 D 8x16 0xa0000 64k 64k 0xe0000000 1944k
331 (0x14b) 0x0000000f G 1152x864x24 D 8x16 0xa0000 64k 64k 0xe0000000 2916k
332 (0x14c) 0x0000000f G 1152x864x32 D 8x16 0xa0000 64k 64k 0xe0000000 3888k
vtの時には動かなかった、モード表示が出来るようになった。
vidcontrol MODE_279
とかやると、1024x768x16の設定になる。
vidcontrol -i adapter
fb0:
vga0, type:VESA VGA (5), flags:0x2700ff
initial mode:24, current mode:24, BIOS mode:3
frame buffer window:0xb8000, buffer size:0x8000
window size:0x8000, origin:0x0
display start address (0, 0), scan line width:80
reserved:0x0
これも、前回やったminixの時に出て来た、CRTコントローラに似た説明だなあ。
今度はコンソールの画面ダンプをやってみる。-pは、アトリビュートも付いたフルダンプ。-Pの方は、テキスト情報だけのダンプ。
root@fbox:/tmp # vidcontrol -p < /dev/ttyv0 >ZZZ root@fbox:/tmp # vidcontrol -P < /dev/ttyv0 > YYY
sakae@fbox:/tmp $ hd ZZZ|head -4 00000000 53 43 52 53 48 4f 54 5f 01 02 50 19 72 07 6f 07 |SCRSHOT_..P.r.o.| 00000010 6f 07 74 07 40 07 66 07 62 07 6f 07 78 07 3a 07 |o.t.@.f.b.o.x.:.| 00000020 2f 07 74 07 6d 07 70 07 20 07 23 07 20 07 76 07 |/.t.m.p. .#. .v.| 00000030 69 07 64 07 63 07 6f 07 6e 07 74 07 72 07 6f 07 |i.d.c.o.n.t.r.o.|
SCRSHOT_ と言うヘッダーに続いて、スクリーンの内容、root@fvox:/tmp # vidcontroっていう文字列が伺える。アトリビュートの解説は、vidcontrolに載っていて、概要は、
The vidcontrol output contains a small header which includes additional
information which may be useful to utilities processing the output.
The first 10 bytes are always arranged as follows:
Byte Range Contents
1 - 8 Literal text “SCRSHOT_”
9 File format version number
10 Remaining number of bytes in the header
Subsequent bytes depend on the version number.
Version Byte Meaning
1 11 Terminal width, in characters
12 Terminal depth, in characters
13 and up The snapshot data
The VGA color attribute byte looks like this:
bits# width meaning
7 <X0000000> 1 character blinking
6:4 <0XXX0000> 3 background color
3 <0000X000> 1 bright foreground color
2:0 <00000XXX> 3 foreground color
Here is a list of the three bit wide base colors:
0 Black
1 Blue
2 Green
3 Cyan
4 Red
5 Magenta
6 Brown
7 Light Grey
これを読み取ると、forgroundは、普通の明るい灰色なんて事が分る。 尚、-Hを付けると、tmuxのヒストリー参照宜しく、過去に遡って、画面の内容を確認出来る。
/ /
Options: .- -.
6. Kernel: default/kernel (1 of 2) -- -.
7. Boot Options `:` `:`
.-- `--.
.---.....----.
Autoboot in 0 seconds. [Space] to pause
Loading kernel...
/boot/kernel/kernel text=0xfc084 text=0xb391e0 text=0x5b5110 data=0xb0 data=0x10
9290+0x2d5540 syms=[0x4+0xe91c0+0x4+0x17caac]
Loading configured modules...
/etc/hostid size=0x25
/boot/entropy size=0x1000
---<<BOOT>>---
Copyright (c) 1992-2021 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 13.1-RELEASE-p2 GENERIC i386
:
こんな起動時のサーと流れてしまう部分も、記録してたぞ。
/sys/dev/syscons/sctermvar.h
static __inline void
sc_term_up(scr_stat *scp, int n, int head)
{
if (n < 1)
n = 1;
n = imin(n, scp->ypos - head);
if (n <= 0)
return;
sc_move_cursor(scp, scp->xpos, scp->ypos - n);
}
ヘッダーファイルと侮るなかれ、minixの時に魅た画面制御と同様のコードが出てきた。
Days of WINE and Struggles again[1] やっぱり、表示って事で捉えると、コンソールもXも陸続きになってるんだなあ。ってな事で、Xの環境をログでチェックしてみる。
/var/log/Xorg.0.log
[ 537.520] (II) Loading /usr/local/lib/xorg/modules/extensions/libglx.so [ 537.664] (II) Loading /usr/local/lib/xorg/modules/drivers/modesetting_drv.so [ 537.670] (II) Loading /usr/local/lib/xorg/modules/drivers/scfb_drv.so [ 537.681] (II) Loading /usr/local/lib/xorg/modules/drivers/vesa_drv.so [ 537.712] (II) Loading /usr/local/lib/xorg/modules/libvbe.so [ 537.726] (II) Loading /usr/local/lib/xorg/modules/libint10.so [ 537.871] (II) Loading /usr/local/lib/xorg/modules/libshadow.so [ 537.872] (II) Loading /usr/local/lib/xorg/modules/libfb.so [ 537.899] (II) Loading /usr/local/lib/xorg/modules/libint10.so [ 541.552] (II) Loading /usr/local/lib/xorg/modules/input/libinput_drv.so [ 542.414] (II) Loading /usr/local/lib/xorg/modules/input/synaptics_drv.so
インテル入ってるなんだけど、使われていない。 lib/xorg/modules/drivers/intel_drv.so が足りない気がする。xf86-video-intelを入れればいいのかな? 今更だけど。
入れたらちゃんと使ってくれた。アスペクト比が正しくなったぞ。vesaだと、横に長い間延びした表示だったけど、今度はキリリとした表示になった。
Linuxでは、どうかと思って調べてみたら、vesaを使ってた。そんなんで委員会。
daemon
ダエモン君が元気よく跳ね回っているので、その活動環境を調べてみる。
前述したようにFreeBSDでのコンソールは2系統有る。元々有ったのは、scと呼ばれるやつ。日本語とかは知りませんと言う欧米向け。それじゃあんまりだってんで、utfをサポートしたvtというのが新に開発された。このおかげで漢字ROMを装着すれば、日本語OKっとなった。 デフォでは、vtに設定されてる。けど、完全にscの機能を引き継いだ訳ではない。 ダエモン君の躍動を感じたかったら、scに切り換えると言う屈辱がまっている。
vt or not vt, that is the question.
で、どこでその切り換えが行われる? 答は、 /sys/kern/kern_cons.c
/*
* Temporary support for sc(4) to vt(4) transition.
*/
static unsigned vty_prefer;
static char vty_name[16];
SYSCTL_STRING(_kern, OID_AUTO, vty, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, vty_name,
0, "Console vty driver");
int
vty_enabled(unsigned vty)
{
static unsigned vty_selected = 0;
if (vty_selected == 0) {
TUNABLE_STR_FETCH("kern.vty", vty_name, sizeof(vty_name));
do {
#if defined(DEV_SC)
if (strcmp(vty_name, "sc") == 0) {
vty_selected = VTY_SC;
break;
}
#endif
#if defined(DEV_VT)
if (strcmp(vty_name, "vt") == 0) {
vty_selected = VTY_VT;
break;
}
#endif
こんな注意書きが付いて、コードが掲載されてた。開発者が忙しくて、余分な機能はまだ実装されていない。んなもんだから、昔のコードも使えるようになってんだね。
How to show daemon
表示されるダエモン君は、赤が基調で、目玉や足が青、フォークの部分は黄色だったりする。ああ、forkがさりげなく出てきたけど、これってUNIXの大事な特徴だね。普通はフォークとナイフだけど、unixの場合は、forkとexecveが超大事なシステムコールだ。これ無しでは、1日としてならず。
上であげた、/* Who is the author of this ASCII pic? */ な、ダエモン君の御姿の他に
static u_char *daemon_attr[] = {
" R R",
" RR RR",
" R RRRR R R",
" RR W RRR R",
" RWWW W R RR",
" W W W R R",
" B B W R R",
" WWWWWWRR R",
" RRRR R R R",
" RRRRRRR R",
" RRRRRRR R",
"YYYYYY RR R RR R",
"YYYYYYYYYYRRRRYYR RR RYYYY",
"YYYYYY RRRR RRRRRR R",
" R R",
" R R RR",
" CCCCCCR RR R RRRRRRRR",
" CC CCCCCCC C",
" CCCCCCCCCCCCCCC",
NULL
};
こんな、色使いの指示書が付属してる。フォークの部分は黄色って理解してくれって事。
実際に描画してる部分は、こうなっている。
static void
draw_daemon(sc_softc_t *sc, int xpos, int ypos, int dxdir, int xoff, int yoff,
int xlen, int ylen)
{
:
switch (daemon_attr[y][px]) {
case 'R': attr = FG_LIGHTRED | BG_BLACK; break;
case 'Y': attr = FG_YELLOW | BG_BLACK; break;
case 'B': attr = FG_LIGHTBLUE | BG_BLACK; break;
case 'W': attr = FG_LIGHTGREY | BG_BLACK; break;
case 'C': attr = FG_CYAN | BG_BLACK; break;
default: attr = FG_WHITE | BG_BLACK; break;
}
if (dxdir < 0) { /* Moving left */
sc_vtb_putc(&sc->cur_scp->scr,
(ypos + y)*sc->cur_scp->xsize
+ xpos + x,
sc->scr_map[daemon_pic[y][px]],
ATTR(attr));
} else { /* Moving right */
:
ダエモン君のサイズは、結構巨大だ。この巨大な矩形が、表示枠の中を跳ね回る、バウンス・ボールごときのプログラムになってる。
#define DAEMON_MAX_WIDTH 32 #define DAEMON_MAX_HEIGHT 19
実際の描画は、scvtb.c
void
sc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a)
{
if (vtb->vtb_type == VTB_FRAMEBUFFER)
writew(sc_vtb_pointer(vtb, at), a | c);
else
*(u_int16_t *)sc_vtb_pointer(vtb, at) = a | c;
}
vm_offset_t
sc_vtb_pointer(sc_vtb_t *vtb, int at)
{
return (vtb->vtb_buffer + sizeof(u_int16_t)*(at));
}
フレームバッファーエリアへの書込みが行われる。
待て
お座りじゃ、ポチへの指示になっちゃうけど、ダエモン君が舞台へ登場する待ち時間は、どうやってる? いわゆるタイム・キーパーの事ね。
vidconrolコマンドの該当部分
static void
set_screensaver_timeout(char *arg)
:
nsec = atoi(arg);
:
if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) {
今気が付いたんだけど、ioctlの第一引数は全てZEROだなあ。標準入力に対しての設定って事か。中には明かに標準出力系もあるのになあ。面倒くさい疑惑があるぞ。まあ、心情としては、オイラーもそうするだろうね。
syscons.c
#define DEFAULT_BLANKTIME (5 * 60) /* 5 minutes */
#define MAX_BLANKTIME (7 * 24 * 60 * 60) /* 7 days!? */
static int
sctty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
{
:
switch (cmd) { /* process console hardware related ioctl's */
:
case CONS_BLANKTIME: /* set screen saver timeout (0 = no saver) */
if (*(int *)data < 0 || *(int *)data > MAX_BLANKTIME)
return EINVAL;
s = spltty();
scrn_blank_time = *(int *)data;
run_scrn_saver = (scrn_blank_time != 0);
splx(s);
return 0;
最長7日まで設定出来るって十分過ぎるな。