git clone https://gitlab.freedesktop.org/gnu-grub/grub.git
目的
前回GRUBから自分の書いたコードを立ち上げた際に、このメニューがどのように描画されているのか気になったので追ってみました。
GRUBから複数の自作カーネルを選択する設定
メニュー描画の呼び出し
grub/grub-core/normal
main.c
grub_enter_normal_mode()
↓
grub_normal_execute()
↓
grub_show_menu()
menu.c
grub_show_menu()
↓
show_menu()
↓
run_menu()
↓
menu_init()
↓
grub_menu_try_text()
menu_text.c
grub_menu_try_text()
↓
grub_menu_init_page()
↓
(main.c)grub_normal_init_page() バージョン
draw_border() 枠
print_message() 「Use the ↑ and ↓ keys…」
文言表示
Use the ↑ and ↓ keys…の文言はここで描画しています。
menu_text.c
static int
print_message (int nested, int edit, struct grub_term_output *term, int dry_run)
{
int ret = 0;
grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
if (edit)
{
ret += grub_print_message_indented_real (_("Minimum Emacs-like screen editing is \
supported. TAB lists completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for a \
command-line or ESC to discard edits and return to the GRUB menu."),
STANDARD_MARGIN, STANDARD_MARGIN,
term, dry_run);
}
else
{
char *msg_translated;
msg_translated = grub_xasprintf (_("Use the %C and %C keys to select which "
"entry is highlighted."),
GRUB_UNICODE_UPARROW,
GRUB_UNICODE_DOWNARROW);
if (!msg_translated)
return 0;
ret += grub_print_message_indented_real (msg_translated, STANDARD_MARGIN,
STANDARD_MARGIN, term, dry_run);
grub_free (msg_translated);
if (!grub_is_cli_disabled ())
{
if (nested)
{
ret += grub_print_message_indented_real
(_("Press enter to boot the selected OS, "
"`e' to edit the commands before booting "
"or `c' for a command-line. ESC to return previous menu."),
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
}
else
{
ret += grub_print_message_indented_real
(_("Press enter to boot the selected OS, "
"`e' to edit the commands before booting "
"or `c' for a command-line."),
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
}
}
}
return ret;
}
枠 draw_border()
座標を指定しながら文字を枠の形に並べています。
文字の定義抜粋
grub/include/grub/unicode.h
GRUB_UNICODE_CORNER_UL = 0x250f,
GRUB_UNICODE_CORNER_UR = 0x2513, ┐
GRUB_UNICODE_CORNER_LL = 0x2517, └
GRUB_UNICODE_CORNER_LR = 0x251b, ┘
GRUB_UNICODE_HLINE = 0x2501, ─
GRUB_UNICODE_VLINE = 0x2503, │
左上の角┌を配置しています
grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1,
geo->first_entry_y - 1 });
grub_putcode (GRUB_UNICODE_CORNER_UL, term);
上辺の横線─を並べてます
for (i = 0; i < geo->entry_width + 1; i++)
grub_putcode (GRUB_UNICODE_HLINE, term);
右上の角┐を置いています
grub_putcode (GRUB_UNICODE_CORNER_UR, term);
左右の縦線│を並べています
for (i = 0; i < geo->num_entries; i++)
{
grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1,
geo->first_entry_y + i });
grub_putcode (GRUB_UNICODE_VLINE, term);
grub_term_gotoxy (term,
(struct grub_term_coordinate) { geo->first_entry_x + geo->entry_width + 1,
geo->first_entry_y + i });
grub_putcode (GRUB_UNICODE_VLINE, term);
}
左下の角└を置いています
grub_term_gotoxy (term,
(struct grub_term_coordinate) { geo->first_entry_x - 1,
geo->first_entry_y - 1 + geo->num_entries + 1 });
grub_putcode (GRUB_UNICODE_CORNER_LL, term);
下辺の横線─を並べています
for (i = 0; i < geo->entry_width + 1; i++)
grub_putcode (GRUB_UNICODE_HLINE, term);
右下の角を置いています
grub_putcode (GRUB_UNICODE_CORNER_LR, term);
実際の書き込みは以下
grub-core/term/i386/pc/console.c
int10_9()からBIOS経由で書き込んでいます。これは別の記事で中身を詳しく読みます。