まずgfxbootのテーマの作成とは、 プログラミングであると認識することが必要である。 また、ややこしいのにドキュメントが少ない。 かなりの根性がいるので要注意。
openSuse辺りのパッケージのソースを入手し、 再度バイナリのパッケージをつくる。 ただ、そのままだとエラーになるので、 コンパイルオプションをちょっと変えておく。(Vine-4.2用) (gfxboot-4.0.14-option.patch , gfxboot.spec)
rpm -ivh gfxboot-4.0.14-4.1.src.rpm mv gfxboot-4.0.14-option.patch ~/rpm/SOURCES/ rpm -bb gfxboot.spec
あとは導入
rpm -ivh ~/rpm/RPM/i386/gfxboot-4.0.14-4.1tpu0.i386.rpm ~/rpm/RPM/i386/gfxboot-devel-4.0.14-4.1tpu0.i386.rpm
なにか作る前に、全体のイメージを明らかにしておくことが必要。 gfxbootの場合、画面内の何処に何を置くのか、 そのためのコードはどの様に分割するのかを決めておく。
取りあえず最低限の要素として、「背景」「メニュー」「タイマ」を 準備することにする。アニメーションは今回は使わない。 全体タイトルや操作説明は背景に書込むことにする。 細かな操作が必要なら、素のgrubの側でやれば良い。
位置関係は以下の様にしてみる。

文字を書く場合のフォントは、メニュー用とタイマ用の2種類とする。
コードは分割して次のようなファイルに配置することにする。
型の名前、色の名前、キーコード、 画面設定関数等のよく使う名前や関数等を、 "common.inc"ファイルにまとめて書いておく。
gimp等で640x480の画像を作成し、
タイトルと説明、メニュー枠を描き、JPEGで保存する。
ファイル名はここでは"back.jpg"とする。
(取りあえずこんな感じ)
気軽にブートローダをテストできる環境 があるのなら、ここまでのところをテストできる。
まず、boot.configに以下の記述をする。
%% include common.inc %% include init.inc
次に、init.incに以下の記述をする。 (common.incは既にあるものとする)
640 480 32 findmode setmode pop 0 0 moveto "back.jpg" findfile setimage 0 0 image.size image
コンパイルする。
gfxboot-compile -O -c boot.config init
アーカイブして、gfxbootのテーマにする。
(echo init; echo back.jpg) |cpio -o > bootlogo
取りあえず、 試してみて背景画像が見えたらOK. どれかキーを押すか、タイムアウトで普通のgrubの画面に戻るはず。
メニューでは、選択肢の表示とキー入力の処理が必要である。
選択肢の文字列などは、最初にMenuInit関数に飛んでくるので、 ここで保存等の処理をする。
キー入力はKeyEvent関数で処理することになるので、 この関数からメニュー処理の関数を呼ぶことにする。 (時間切れも0のキーのKeyEventとなることに注意)
menu.incにつぎのように書く.
やることは、 メニューの情報ををもつ3つのデータをスタックから取り出して、 使えるように覚えておくMenuInitと言う関数を定義することと、 覚えておいたメニューの情報を使うため、 その他の適当な関数を定義することである。
% MenuInit
% ( menu_entries_array cmdline_args_array defaultentry ) -> ( )
/MenuInit {
/menu.default exch def
/menu.args exch def
/menu.txts exch def
/menu.font font.normal def
/menu.color gray def
/menu.hicolor white def
/menu.xoff 210 def
/menu.yoff 170 def
/menu.width 400 def
/menu.dy 36 def
/menu.current 0 def
0 1 menu.txts length 1 sub {
dup menu.txts exch get menu.default eq {
/menu.current exch def
} { pop } ifelse
} for
menu.font setfont
0 1 menu.txts length 1 sub {
menu.txts exch get
{
dup strsize pop menu.width le { exit } if
dup dup length dup 3 le { pop pop exit } if
over over 1 sub 0 put
over over 2 sub '.' put
over over 3 sub '.' put
over over 4 sub '.' put
pop pop
} loop
pop
} for
/menu.backs menu.txts length array def
0 1 menu.txts length 1 sub {
menu.xoff over menu.dy mul menu.yoff add moveto
menu.width menu.dy savescreen
menu.backs 3 1 roll put
} for
menu.show
} def
% () -> ()
/menu.show {
menu.font setfont
0 1 menu.txts length 1 sub {
menu.xoff over menu.dy mul menu.yoff add moveto
menu.backs over get restorescreen
dup menu.current eq {
menu.hicolor setcolor
} {
menu.color setcolor
} ifelse
menu.xoff over menu.dy mul menu.yoff add moveto
menu.txts exch get show
} for
} def
% () -> ()
/menu.next {
menu.current menu.txts length 1 sub lt {
/menu.current menu.current 1 add def
} if
menu.show
} def
% () -> ()
/menu.prev {
menu.current 0 gt {
/menu.current menu.current 1 sub def
} if
menu.show
} def
"menu.show"と言った名前の中の'.'に文字であるという以上の意味はない。 ただ、このような命名規則にすることで、 他のファイルで利用する辞書項目と混ざりにくくなる。
keyevent.incにつぎのように書く。
% KeyEvent : input event handling
% ( key ) -> ( input_buffer menu_entry action )
% key
% bit 0-7 ascii
% bit 8-15 scan code
% bit 16-32 status bits (ctrl, shift...)
% action
% 0: ok, stay in input loop
% 1: switch to text mode
% >=2: start linux
%
/KeyEvent {
dup 0 eq { keyevent.selected return } if
dup 0xff and /keyevent.key exch def
dup 8 shr 0xff and /keyevent.keycode exch def
16 shr 0xffff and /keyevent.keystat exch def
keyevent.keycode KC_UP eq { menu.prev } if
keyevent.keycode KC_DOWN eq { menu.next } if
keyevent.key KEY_ESC eq { "" -1 1 return } if
keyevent.key KEY_ENTER eq { keyevent.selected return } if
"" -1 0 return
} def
% keyevent.selected :
% () -> (str int int)
/keyevent.selected {
menu.current 0 lt menu.current menu.txts length ge or {
"" -1 1 return
} if
menu.args menu.current get menu.current 2 return
} def
KeyEvent関数は、1つの情報をスタックから取り出した後、 適切な3つの情報をスタックに積んでからリターンする必要があることに注意。
メニューの文字を書くためのフォントをあらかじめ作成する必要がある。
今回は以下のようにして、VineのVL Pゴシックからフォントを生成する。
gfxboot-font -l 36 -p /usr/X11R6/lib/X11/fonts/TrueType -f VL-PGothic-Regular:size=32 normal.fnt
もし日本語等を使う場合には、フォントの作成時に アルファベットも含めて使う文字をオプションで指定する必要があるが、 今回はアルファベットのみなので特に指定しない。
ここまででもう一度テストする。
boot.configに以下の記述。
%% include common.inc %% include menu.inc %% include keyevent.inc %% include init.inc
init.incに以下の記述。
% 640x480 32bpp mode 640 480 32 findmode setmode pop % set background image "back.jpg" findfile setimage 0 0 image.size image % font /font.normal "normal.fnt" findfile def
コンパイル
gfxboot-compile -O -c boot.config init
アーカイブしてテーマファイル("bootlogo")の作成
(echo init; echo back.jpg; echo normal.fnt;) | cpio -o > bootlogo
これを使ってブートして、メニューの項目が見え、 上下の矢印で移動、Enterで決定できればOK。
タイマーは、タイムアウトまでの時間を表示するためのものである。 Timeoutに定期的に飛んでくるだけであるので、この関数を記述すれば良い。
今回は残り時間を文字としてだけでなく、絵としても表示することにする。 ただ、あまり画像が大きいとgfxbootが扱える範囲を超えてしまうようなので、 画像を4分割して部品として使うことで大きさを節約している。
% Timeout : Boot timeout counter.
% ( timeout time ) -> ( )
% timeout: total time in 18.2Hz steps, time: current value.
/Timeout {
timeout.sec .undef eq { timeout.init } if
/timeout.sec over 10 mul 150 add 182 div def
/timeout.step over 8 mul 3 index 4 mul 6 div add 3 index div
dup 8 gt { pop 8 } if def
timeout.sec timeout.lastsec ne timeout.step timeout.laststep ne or {
timeout.update
/timeout.lastsec timeout.sec def
/timeout.laststep timeout.step def
} if
} def
% () -> ()
/timeout.init {
/timeout.lastsec -1 def
/timeout.laststep -1 def
/timeout.xoff 20 def
/timeout.yoff 200 def
/timeout.image "timer.jpg" findfile def
/timeout.alpha "timer-b.jpg" findfile def
/timeout.width 160 def
/timeout.height 160 def
/timeout.strbuf 12 string def
/timeout.font font.normal def
/timeout.color gray def
/timeout.strxoff 50 def
/timeout.stryoff 270 def
/timeout.stepimages 12 array def
timeout.image setimage
0 1 11 {
dup 6 mod timeout.width 2 div mul
over 6 div timeout.height 2 div mul
timeout.width 2 div timeout.height 2 div
timeout.image setimage unpackimage
exch
dup 6 mod timeout.width 2 div mul
over 6 div timeout.height 2 div mul
timeout.width 2 div timeout.height 2 div
timeout.alpha setimage unpackimage
exch
dup 2 mod timeout.width 2 div mul timeout.xoff add
over 6 div timeout.height 2 div mul timeout.yoff add moveto
timeout.stepimages over
timeout.width 2 div timeout.height 2 div savescreen put
0 0 moveto
timeout.stepimages exch get
2 index exch 2 index exch
blend
free free
} for
} def
% () -> ()
/timeout.update {
timeout.step 8 ge { 1 1 0 timeout.drawquad } if
timeout.step 7 eq { 3 1 0 timeout.drawquad } if
timeout.step 6 le { 5 1 0 timeout.drawquad } if
timeout.step 6 ge { 7 1 1 timeout.drawquad } if
timeout.step 5 eq { 9 1 1 timeout.drawquad } if
timeout.step 4 le { 11 1 1 timeout.drawquad } if
timeout.step 4 ge { 6 0 1 timeout.drawquad } if
timeout.step 3 eq { 8 0 1 timeout.drawquad } if
timeout.step 2 le { 10 0 1 timeout.drawquad } if
timeout.step 2 ge { 0 0 0 timeout.drawquad } if
timeout.step 1 eq { 2 0 0 timeout.drawquad } if
timeout.step 0 le { 4 0 0 timeout.drawquad } if
timeout.font setfont
timeout.color setcolor
timeout.sec "%4ds" timeout.strbuf sprintf
timeout.strxoff timeout.stryoff moveto
timeout.strbuf show
} def
% (img_index x_index y_index) -> ()
/timeout.drawquad {
exch timeout.width 2 div mul timeout.xoff add
exch timeout.height 2 div mul timeout.yoff add
moveto
timeout.stepimages exch get restorescreen
} def
これが不透明率を設定する画像("timer-b.jpg")。

boot.configに以下の記述
%% include common.inc %% include menu.inc %% include keyevent.inc %% include timeout.inc %% include init.inc
コンパイル
gfxboot-compile -O -c boot.config init
アーカイブしてテーマファイルの作成
( echo init ; echo back.jpg ; echo normal.fnt ; echo timer.jpg ; echo timer-b.jpg ) | cpio -o > bootlogo
こんな感じになるはず
取りあえずこれでブートセレクタとして最低限のものは揃ったと思う。
あらかじめMakefileを作っておくと、 ファイルの中身を変えたときに"make"と打つだけで テーマのアーカイブまで作ってくれる。
MKBOOTMSG=gfxboot-compile MKBLFONT=gfxboot-font BOOTLOGO=bootlogo IMG_FILES=back.jpg timer.jpg timer-b.jpg INC_FILES=common.inc init.inc keyevent.inc menu.inc timeout.inc FILES=init $(IMG_FILES) normal.fnt all: $(FILES) echo $(FILES) | sed -e "s/ /\n/g" | cpio -o > $(BOOTLOGO) init: boot.config $(INC_FILES) $(MKBOOTMSG) -O -l log -c boot.config init normal.fnt: $(MKBLFONT) -v -l 36 \ -p /usr/X11R6/lib/X11/fonts/TrueType \ -f VL-PGothic-Regular:size=32 \ normal.fnt > normal.fnt.log small.fnt: $(MKBLFONT) -v -l 24 \ -p /usr/X11R6/lib/X11/fonts/TrueType \ -f VL-PGothic-Regular:size=23 \ small.fnt > small.fnt.log clean: rm *.log *.fnt init $(BOOTLOGO) || true
makeはタブとスペースを区別するので注意.
(2008/11/1)