Ubuntu 10.04 (Lucid) でスプラッシュスクリーンをなんとかする

なんとかするってなんだ。

わたしが使っているマシンの VGANVIDIAGeForce 7600 GS です。結構古いですね。んで Ubuntu Lucid から NVIDIA のカードのデフォルトグラフィックドライバが nouveau というのにかわったんだけど,これから nvidia プロプラドライバに変更したら,起動時のスプラッシュスクリーンの表示が解像度が低くなってしまった。

実害はないんだけど,なんとなく気持ち悪いので直してみました。

[Lucid][Ubuntu 10.04] High resolution Plymouth & Virtual Terminal for ATI/NVIDIA cards with proprietary/restricted driver | Tux's idyllic life. がとても参考になった。英語に抵抗感のないひとはこちらを読んだらいいと思う。とてもわかりやすい構造で書いているので。

概要だけいうと,カーネルフレームバッファを uvesafb というドライバモジュール*1を利用するように変更する。なおスプラッシュスクリーンは Plymouth という機構にかわったらしいんだけど,そのへんのカスタマイズとかには興味ないので触れません。



まず,必要となるソフトをインストールする。uvesafb カーネルモジュール自体はもともと入ってるが,uvesafb には v86d というコンポーネントが必要になるのでインストールする。また,使っているグラフィックカードBIOS レベルで利用可能な画面解像度を調べるために hwinfo というパッケージもインストールする(こちらは必ずしも必要ない)。

$ sudo aptitude install v86d hwinfo

さっそく hwinfo コマンドを使って,使っているグラフィックカードでサポートされている VESA BIOS ビデオモードを確認する。sudo つけなくても怒られないけど,下記のような結果を得ることができないのでつける。

$ sudo hwinfo --framebuffer

02: None 00.0: 11001 VESA Framebuffer                           
  [Created at bios.464]
  Unique ID: rdCR.XJVGY3Zr0S5
  Hardware Class: framebuffer
  Model: "NVIDIA G73 Board - p345h0b "
  Vendor: "NVIDIA Corporation"
  Device: "G73 Board - p345h0b "
  SubVendor: "NVIDIA"
  SubDevice: 
  Revision: "Chip Rev"
  Memory Size: 256 MB
  Memory Range: 0xd0000000-0xdfffffff (rw)
  Mode 0x0300: 640x400 (+640), 8 bits
  Mode 0x0301: 640x480 (+640), 8 bits
  Mode 0x0303: 800x600 (+800), 8 bits
  Mode 0x0305: 1024x768 (+1024), 8 bits
  Mode 0x0307: 1280x1024 (+1280), 8 bits
  Mode 0x030e: 320x200 (+640), 16 bits
  Mode 0x030f: 320x200 (+1280), 24 bits
  Mode 0x0311: 640x480 (+1280), 16 bits
  Mode 0x0312: 640x480 (+2560), 24 bits
  Mode 0x0314: 800x600 (+1600), 16 bits
  Mode 0x0315: 800x600 (+3200), 24 bits
  Mode 0x0317: 1024x768 (+2048), 16 bits
  Mode 0x0318: 1024x768 (+4096), 24 bits
  Mode 0x031a: 1280x1024 (+2560), 16 bits
  Mode 0x031b: 1280x1024 (+5120), 24 bits
  Mode 0x0330: 320x200 (+320), 8 bits
  Mode 0x0331: 320x400 (+320), 8 bits
  Mode 0x0332: 320x400 (+640), 16 bits
  Mode 0x0333: 320x400 (+1280), 24 bits
  Mode 0x0334: 320x240 (+320), 8 bits
  Mode 0x0335: 320x240 (+640), 16 bits
  Mode 0x0336: 320x240 (+1280), 24 bits
  Mode 0x033d: 640x400 (+1280), 16 bits
  Mode 0x033e: 640x400 (+2560), 24 bits
  Config Status: cfg=new, avail=yes, need=no, active=unknown

このカードでは BIOS レベルでは 1920x1080 とかサポートされてない。がーん。

以上で下準備おわり。


早速設定をしていく。GRUB2 の場合,/etc/default/grub の該当部分を下記のように変更する。

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash nomodeset video=uvesafb:mode_option=1280x1024-24,mtrr=2,scroll=ywrap"

GRUB_GFXMODE=1280x1024

GRUB_GFXMODE のほうは別に指定しなくてもいいと思う。

キモは GRUB_CMDLINE_LINUX_DEFAULT のほうなんだけど,quiet splash はもともと設定されていると思う。

nomodeset は KMS (Kernel Mode Setting) を無効にするという意味。今回のようにカーネルフレームバッファドライバとしては uvesafb を使うばあい,Kernel Mode Setting は使えない(フレームバッファドライバと X.Org ドライバが一致しないからね)んで指定しているみたい。たぶんわざわざ書かなくても自動的に KMS は無効になると思うんだけど。

で,video=uvesafbフレームバッファドライバとして uvesafb を使うという意味で以降その設定が続く。どんなオプションを指定できるのかは fb/uvesafb.txt 参照。

mode_option=1280x1024-24 というのは,さきほど hwinit で調べた指定しうる解像度(と色深度)を指定する。

mtrr=2 というのは,MTRR レジスタ*2に設定する内容。わたしの環境では 2 を指定しているけど,とりあえず 3 を指定しておくとよい。後述。

scroll=ywrap は,端的に言うと仮想ターミナル画面でのスクロールの実現方法を設定している。ywrap, ypan, redraw を指定することができて,頭のほうから順にパフォーマンスがいい((わたしの GeForce 7600 GS だと scroll=ywrap でひととおり問題なく動くんだけど,デュアルスクリーンの場合にセカンダリモニタの表示内容がスクロール時におかしくなる。実害ないのでそのままにしてるけど。))。


んで,カーネル起動時に uvesafb モジュールを読み込んでもらうために initramfs のほうにも指定しておく必要があるみたい。具体的には /etc/initramfs-tools/modules に,

uvesafb mode_option=1280x1024-24 mtrr=2 scroll=ywrap

のように追記する。書式がちょっと違うけど,指定している内容はさきほどと同じ。

あと,/etc/initramfs-tools/conf.d/splash というファイルを作成して

FRAMEBUFFER=y

という内容にする(もしすでにあれば追記する)。


以上のプロセスで GRUB2 や initramfs の設定を更新する準備ができたので,順次更新していく。

$ sudo update-grub2

$ sudo update-initramfs -u


これでうまくいったら Plymouth の解像度があがる。わたしはあがった。でも黒ブランク画面の時間が短くなった気はしなかった(そもそも KMS disabled だから nouveau より不利だけど)。

あと,関係ないけど Lucid になって起動ちょっぱやになったっていう報告をいくつかみるけど,自分の環境ではそんな感じでもないですね。たんにマシンパワーのおかげで Karmic の時点でもはやかっただけかもだけど。

んで,副作用?で,仮想ターミナルの解像度もあがりました。やったね。jfbterm とかいれると仮想ターミナルもなかなか快適。jfbterm 抜ける時に画面がフリーズしちゃうけど。

MTRR について

fb/uvesafb.txt によると

mtrr:n  Setup memory type range registers for the framebuffer
        where n:
              0 - disabled (equivalent to nomtrr) (default)
              1 - uncachable
              2 - write-back
              3 - write-combining
              4 - write-through

        If you see the following in dmesg, choose the type that matches
        the old one.  In this example, use "mtrr:2".
...
mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining
...

nomtrr  Do not use memory type range registers.
fb/uvesafb.txt

のように設定できる。

で,たぶん write-combining > write-back > write-through > uncachable の順にパフォーマンスがよくなる。パフォーマンスといっても今回の例では uvesafb ドライバ部分の話であって,X.Org が立ち上がったあとは話が別(たぶん nvidia プロプラドライバがよしなに設定してくれる)。

どのモードをサポートしているかはグラフィックチップやグラフィックカードによって異なるみたい。だけど,どれを指定すればいいかはやってみなきゃわかんなさそう((X.Org が立ち上がっている状態で /proc/mtrr とかみてみたけどわかんなかった。uncachable になってたし。))。指定してみて間違っていると起動時の dmesg で教えてくれる。

以下は write-back (2) しかサポートしていないグラフィックカードmtrr=3 (write-combining) を指定した時の dmesg の例。

mtrr: type mismatch for d0000000,800000 old: write-back new: write-combining
mtrr: type mismatch for d0000000,400000 old: write-back new: write-combining
mtrr: type mismatch for d0000000,200000 old: write-back new: write-combining
mtrr: type mismatch for d0000000,100000 old: write-back new: write-combining
mtrr: type mismatch for d0000000,80000 old: write-back new: write-combining
mtrr: type mismatch for d0000000,40000 old: write-back new: write-combining
mtrr: type mismatch for d0000000,20000 old: write-back new: write-combining
mtrr: type mismatch for d0000000,10000 old: write-back new: write-combining
mtrr: type mismatch for d0000000,8000 old: write-back new: write-combining
mtrr: type mismatch for d0000000,4000 old: write-back new: write-combining
mtrr: type mismatch for d0000000,2000 old: write-back new: write-combining
mtrr: type mismatch for d0000000,1000 old: write-back new: write-combining

このようにいわれるので mtrr=2 に設定をかえた。

かえたあとの dmesg は以下のとおり。

uvesafb: NVIDIA Corporation, G73 Board - p345h0b , Chip Rev   , OEM: NVIDIA, VBE v3.0
uvesafb: protected mode interface info at c000:c2e0
uvesafb: pmi: set display start = c00cc316, set palette = c00cc380
uvesafb: pmi: ports = 3b4 3b5 3ba 3c0 3c1 3c4 3c5 3c6 3c7 3c8 3c9 3cc 3ce 3cf 3d0 3d1 3d2 3d3 3d4 3d5 3da 
uvesafb: VBIOS/hardware supports DDC2 transfers
uvesafb: monitor limits: vf = 76 Hz, hf = 83 kHz, clk = 210 MHz
uvesafb: scrolling: ywrap using protected mode interface, yres_virtual=2048
uvesafb: framebuffer at 0xd0000000, mapped to 0xf8700000, using 10240k, total 262144k

MTRR まわりで文句はいわれなくなった。

用語など

あとで書くかも。

*1:旧来の vesafb をつかってもいけるらしいんだけど,blacklist 入りしてるみたいなので uvesafb を使うほうがいいと思う。

*2:ほんとは MTR レジスタなので「馬から落馬」なんだけど