GRUB をセットアップする

こんにちは、masm11 です。

約半月前、原神がメジャーバージョンアップしまして、 PC のディスクを Linux と Windows で分け合っていたところ、 Windows 領域が足りなくなったので、パーティションを切り直しました。 それ以降、どうも再起動中にフリーズする等、調子が悪くなってしまったので、 フルリカバリしました。 その後も Boot Loader として systemd-boot を使っていたのですが、 エントリの順序がうまく制御できないことが不満で、 GRUB に戻ろうと思い立ちました。

以前は grub.cfg を自前で書いていたのですが、 今回は grub-mkconfig に従いたいと思います。

なお、今回は長めの駄文となっております。 時間に余裕のある時にでもお付き合いいただければ幸いです。

インストール

OS は Arch Linux です。pacman コマンドでインストールできます。

sudo pacman -S grub

そして /boot にインストールします。

grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB

さっそく grub-mkconfig してみます。

luna:~ % sudo grub-mkconfig -o /dev/null
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-linux-zen
Found initrd image: /boot/amd-ucode.img /boot/initramfs-linux-zen.img
Found linux image: /boot/vmlinuz-linux
Found initrd image: /boot/amd-ucode.img /boot/initramfs-linux.img
Warning: os-prober will not be executed to detect other bootable partitions.
Systems on them will not be added to the GRUB boot configuration.
Check GRUB_DISABLE_OS_PROBER documentation entry.
Adding boot menu entry for UEFI Firmware Settings ...
done

とりあえず /dev/null に出力してみました。warning は出てるけど、まぁいいかな。

sudo grub-mkconfig -o /boot/grub/grub.cfg

で生成しました。

文字サイズの調整

再起動してみました。

  • submenu になってる
  • 文字が小さい

エントリ数は少ないので、submenu にする必要はありません。 submenu は↓これで無効にできます。

GRUB_DISABLE_SUBMENU=y

文字サイズについては、↓こういうコマンドでフォントが作成できます。

sudo grub-mkfont --output=/boot/grub/fonts/Noto24.pf2 --size=24 /usr/share/fonts/noto-cjk/NotoSansCJK-Medium.ttc 

Noto Font から Noto24.pf2 を作成しました。これを使うには、GRUB_FONT を指定します。

GRUB_FONT=/boot/grub/fonts/Noto24.pf2

設定を変更した際には grub.cfg の再生成が必要なので、実行します。

sudo grub-mkconfig -o /boot/grub/grub.cfg

そして再起動しました。

なお、今後はいちいち書きませんが、grub.cfg の再生成と再起動はしていると思ってください。

なんともひどいことになってますね。枠が切れ切れだし、文字の間隔は広いし、余計な場所に罫線の切れ端が表示されています。

別のフォントにしてみます。

sudo pacman -S ttf-dejavu
sudo grub-mkfont --output=/boot/grub/fonts/dejavu24.pf2 --size=24 /usr/share/fonts/TTF/DejaVuSansMono.ttf

でフォントを生成して、

GRUB_FONT=/boot/grub/fonts/dejavu24.pf2

としてみましたが、今度は枠が化けてますし、日本語も化けてます。

別の方法にしてみます。 GRUB_FONT をコメントアウトして、画面モードを変えます。

GRUB_GFXMODE=1280x720

このモードは、GRUB を起動し、c キーを押すとコマンドモードになりますので、 そこで videoinfo コマンドを実行すると、どんな画面モードが使えるかわかります。

まぁまだちょっと小さいけど、とりあえずこんなもんかな… (スクリーンショットだとわかりにくいかもしれませんが・・・)

Windows の起動設定

/etc/grub.d/29_windows を以下の内容で作成しました。

#!/bin/sh
exec tail -n +3 $0
menuentry "Windows" {
  search --no-floppy --fs-uuid --set=root 56AB-C0F2
  chainloader /EFI/Microsoft/bootmgfw.efi
}

本来は /EFI/Microsoft/Boot/bootmgfw.efi なのですが、 ちょっと面倒くさい事情があり、 そのコピーを /EFI/Microsoft/bootmgfw.efi に置いてあります。

os-prober を使うと Windows を自動で見つけてくれるらしいのですが、 efi ファイルの場所が通常と違うので、今回は自分で書きました。

デフォルトエントリの設定

前回選択したエントリを、今回のデフォルトエントリとすることができます。

GRUB_DEFAULT=saved
GRUB_SAVEDEFAULT=true

/etc/default/grub に以上の設定をします。

これだけでは、Arch Linux のエントリは問題ないのですが、 Windows はデフォルトになりません。 先程作成した /etc/grub.d/29_windows を以下のように修正します。

#!/bin/sh
exec tail -n +3 $0
menuentry "Windows" --class windows --class os $menuentry_id_option 'windows' {
  savedefault
  search --no-floppy --fs-uuid --set=root 56AB-C0F2
  echo 'Loading Windows...'
  chainloader /EFI/Microsoft/bootmgfw.efi
}
  • savedefault を追加しました。
  • echo はどうでもいいです。
  • $menuentry_id_option 'windows' を追加しました。
  • --class windows --class os もどうでもいいです。テーマに影響するらしいです。

これにより、エントリの ID を windows と指定し、 エントリ選択時に savedefault でその ID を保存しています。

なお、保存先は /boot/grub/grubenv のようです。

文字サイズの調整・再

画面解像度が低いと、やっぱりあんまり綺麗じゃないですね…

解像度は高くして、やっぱりフォントサイズを大きくしたいです。

いろんなフォントを試しましたが、横線が長すぎるのは変わりませんでした。 デフォルトのフォントだと問題なかったので、それの別サイズを作ることにします。

まず、AUR (Arch User Repository) から ttf-unifont をインストールします。 AUR からインストールするにはいろいろなコマンドがありますが、 私は yay を使っています。

yay -S ttf-unifont

/usr/share/fonts/Unifont/Unifont.ttf ができますので、これを pf2 ファイルに 変換します。

grub-mkfont --verbose -o unifont40.pf2 --size 40 /usr/share/fonts/Unifont/Unifont.ttf

unifont40.pf2 を /boot/grub/fonts/ にコピーし、GRUB_FONT の設定をします。

GRUB_FONT=/boot/grub/fonts/unifont40.pf2

これで横線は綺麗になりました。 が、縦線は切れ切れです。 よく見ると横線も切れ切れですが。

誤差のせいかなぁ、と思ったのですが、 40, 42, 44, 46, 48 とサイズを変えてみましたが、 変わりませんでした。

ここまでのまとめ

/etc/default/grub の有効行:

GRUB_DEFAULT=saved
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="Arch"
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"
GRUB_CMDLINE_LINUX=""
GRUB_PRELOAD_MODULES="part_gpt part_msdos"
GRUB_TIMEOUT_STYLE=menu
GRUB_TERMINAL_INPUT=console
GRUB_GFXMODE=1920x1080
GRUB_GFXPAYLOAD_LINUX=keep
GRUB_DISABLE_RECOVERY=true
GRUB_DISABLE_SUBMENU=y
GRUB_DISABLE_OS_PROBER=false
GRUB_FONT=/boot/grub/fonts/unifont40.pf2
GRUB_SAVEDEFAULT=true

/etc/grub.d/29_windows:

#!/bin/sh
exec tail -n +3 $0
menuentry "Windows" --class windows --class os $menuentry_id_option 'windows' {
  savedefault
  search --no-floppy --fs-uuid --set=root 56AB-C0F2
  echo 'Loading Windows...'
  chainloader /EFI/Microsoft/Boot/bootmgfw.efi
}

(なお、試行錯誤中に「事情」が解決したため、bootmgfw.efi は本来の場所に戻しています)

スクリーンショット:

なんでしょうね、この、ドットを大きくしただけのようなフォントは…

なお、通常、ブートローダの画面をスクリーンショット撮るなんて不可能ですよね。 この画像は、ESP (EFI System Partition) を virtualbox 内にコピーして起動して、 virtualbox の機能で一旦動画にし、 そこから png に切り出したものです。 動画は grub-screen0.webm というファイルに保存されますので、以下のコマンドで png に変換します。たくさんできますので、その中から至高の一枚を選びます。

mpv --vo=image --vo-image-format=png grub-screen0.webm

一念発起: テーマを使う

テーマを使ってみることにしました。 starfield というテーマをベースにします。 GRUB にはデフォルトで付属していると思います。

正直、出来は悪いです。黒っぽい背景に黒文字。読めたものではありません。 が、手を加えるにはシンプルで良いかな、と思います。

テーマをコピーします。

sudo cp -r /usr/share/grub/themes/starfield /boot/grub/themes

フォントを作ります。

cd /boot/grub/themes/starfield
sudo grub-mkfont --verbose -o noto40.pf2 --size 40 /usr/share/fonts/noto/NotoSans-Regular.ttf

テーマを書き換えてフォントを変更します。

sudo vi /boot/grub/themes/starfield/theme.txt
selected_item_font = "DejaVu Sans Bold 14"

selected_item_font = "Noto Sans Regular 40"

に書き換えます。

/etc/default/grub を変更します。

GRUB_THEME=/boot/grub/themes/starfield/theme.txt

GRUB_FONT= はコメントアウトします。

そして grub.cfg を再生成します。

LANG=C sudo grub-mkconfig -o /boot/grub/grub.cfg

grub-mkconfig が pf2 ファイルを探して grub.cfg に列挙してくれるので、 フォントを追加した場合には grub-mkconfig の実行が必須です。

この調子で、

  • Noto Sans Mono Regular 24
  • Noto Sans Mono Regular 32
  • Noto Sans Mono Regular 40
  • Noto Sans Regular 24
  • Noto Sans Regular 32

を生成します。そして、theme.txt の各所に指定します。

色は、非選択は白 (#fff)、選択中は黄 (#fc0) にしました。

あと、selected_item_pixmap_style については説明が必要かと思います。

選択中のエントリの上下左右背景に装飾を表示することができます。 左、左上、上、右上、右、右下、下、左下、背景に表示する画像をそれぞれ指定しておくと、 選択中のアイテムの各所にその画像を表示してくれます。 ファイル名は、以下のように指定します。

selected_item_pixmap_style = "blob_*.png"

* の部分には、上を北と見立てて、それぞれ、w, nw, n, ne, e, se, s, sw, c が入ります。 * がないと表示が異常になるようです。 対応する画像がなければ単に表示されないだけです。

今回は、左に ● を表示するだけなので、この絵を書いた blob_w.png を置いておき、 上記のように指定すると、左にだけ blob_w.png が表示されるわけです。

デフォルトの blob_w.png だと小さかったので、GIMP で開いて拡大して作成しました。

message-font: "Noto Sans Mono Regular 32"
message-color: "#000"
message-bg-color: "#fff"
terminal-box: "terminal_box_*.png"
terminal-font: "Noto Sans Mono Regular 24"
desktop-image: "starfield.png"
+ label {
        top = 100%-100
        left = 0
        width = 100%
        height = 96
        text = "@KEYMAP_MIDDLE@"
        align = "center"
        font = "Noto Sans Regular 24"
        color = "#FFF"
}
+ boot_menu {
        left = 10%
        width = 80%
        top = 20%
        height = 50%    
        item_font = "Noto Sans Mono Regular 40"
        item_color = "#fff"
        selected_item_font = "Noto Sans Mono Regular 40"
        selected_item_color= "#fc0"
        selected_item_pixmap_style = "blob_*.png"
        icon_height = 25
        icon_width = 25
        item_height = 48
        item_padding = 8
        item_icon_space = 0
        item_spacing = 8
        scrollbar = true
        scrollbar_width = 20
        scrollbar_thumb = "slider_*.png"
        menu_pixmap_style = "boot_menu_*.png"
}
+ progress_bar {
        id = "__timeout__"
        left = 15%
        top = 80%
        height = 20
        width = 70%
        font = "Noto Sans Mono Regular 32"
        text_color = "#000"
        fg_color = "#fff"
        bg_color = "#6ac"
        border_color = "#fff"
        text = "@TIMEOUT_NOTIFICATION_LONG@"
}

これで画面は以下のようになりました。

これならいいですね!

若干文字の輪郭がエイリアスを起こしていますが、 pf2 はビットマップフォントらしいので、 アンチエイリアスはないのでしょうかね。

アンチエイリアスに対応

https://lists.gnu.org/archive/html/grub-devel/2010-02/msg00205.html

↑なんと、昔、パッチがあったようですが、入らなかったようですね。 この ML ではないですが、いろいろなサイトに残っているやりとりの履歴を見たところ、 「ほんの数秒しか表示されない or 全く表示されない画面を、そんなに綺麗にしても…」 のような意見もありました。確かにそれはそうかもしれませんね。

でも… 綺麗な画面にしてみたくありませんか? というわけで、そのパッチを取り込んでみました。

わかりますか? 先程のスクリーンショットと比較してみてください。 W の文字がすごく綺麗になっています。 あと、一番下の操作方法のメッセージも文字が綺麗になっています。

端末表示でも綺麗です。gj 等の baseline より下の部分が表示されていない ことに気づいたので、それも修正しました。

まとめ

ついでに以下を実施しました。

  • メッセージを日本語にした
  • エントリの前にアイコンを表示した
  • 選択エントリの表示方法を変更した (前に●を表示するのでなく、背景を白っぽくした)
  • タイトルを表示した

というわけで、最終形態を置いておきます。

アイコンは、menuentry に --class arch とある場合には /boot/grub/themes/starfield/icons/arch.png を探して、 存在したらそれを表示してくれる、という具合です。

最後に、antialiasing パッチや私の修正を混ぜたリポジトリは こちらです。 reject された他人のパッチがベースなので、これをマージリクエスト することはおそらくないでしょう。

ではまた!