From: Hans de Goede Date: Wed, 15 Apr 2020 10:26:21 +0000 (+0200) Subject: efi/console: Do not set text-mode until we actually need it X-Git-Tag: grub-2.06-rc1~275 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d7c3abd8;p=thirdparty%2Fgrub.git efi/console: Do not set text-mode until we actually need it If we're running with a hidden menu we may never need text mode, so do not change the video-mode to text until we actually need it. This allows to boot a machine without unnecessary graphical transitions and provide a seamless boot experience to users. Signed-off-by: Hans de Goede Signed-off-by: Javier Martinez Canillas Reviewed-by: Daniel Kiper --- diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c index 64591b90a..2f1ae85ba 100644 --- a/grub-core/term/efi/console.c +++ b/grub-core/term/efi/console.c @@ -24,6 +24,16 @@ #include #include +typedef enum { + GRUB_TEXT_MODE_UNDEFINED = -1, + GRUB_TEXT_MODE_UNAVAILABLE = 0, + GRUB_TEXT_MODE_AVAILABLE +} +grub_text_mode; + +static grub_text_mode text_mode = GRUB_TEXT_MODE_UNDEFINED; +static grub_term_color_state text_colorstate = GRUB_TERM_COLOR_UNDEFINED; + static grub_uint32_t map_char (grub_uint32_t c) { @@ -106,15 +116,39 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)), efi_call_2 (o->enable_cursor, o, on); } +static grub_err_t +grub_prepare_for_text_output (struct grub_term_output *term) +{ + if (grub_efi_is_finished) + return GRUB_ERR_BAD_DEVICE; + + if (text_mode != GRUB_TEXT_MODE_UNDEFINED) + return text_mode ? GRUB_ERR_NONE : GRUB_ERR_BAD_DEVICE; + + if (! grub_efi_set_text_mode (1)) + { + /* This really should never happen */ + grub_error (GRUB_ERR_BAD_DEVICE, "cannot set text mode"); + text_mode = GRUB_TEXT_MODE_UNAVAILABLE; + return GRUB_ERR_BAD_DEVICE; + } + + grub_console_setcursor (term, 1); + if (text_colorstate != GRUB_TERM_COLOR_UNDEFINED) + grub_console_setcolorstate (term, text_colorstate); + text_mode = GRUB_TEXT_MODE_AVAILABLE; + return GRUB_ERR_NONE; +} + static void -grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)), +grub_console_putchar (struct grub_term_output *term, const struct grub_unicode_glyph *c) { grub_efi_char16_t str[2 + 30]; grub_efi_simple_text_output_interface_t *o; unsigned i, j; - if (grub_efi_is_finished) + if (grub_prepare_for_text_output (term) != GRUB_ERR_NONE) return; o = grub_efi_system_table->con_out; @@ -327,14 +361,15 @@ grub_console_getkey (struct grub_term_input *term) } static struct grub_term_coordinate -grub_console_getwh (struct grub_term_output *term __attribute__ ((unused))) +grub_console_getwh (struct grub_term_output *term) { grub_efi_simple_text_output_interface_t *o; grub_efi_uintn_t columns, rows; o = grub_efi_system_table->con_out; - if (grub_efi_is_finished || efi_call_4 (o->query_mode, o, o->mode->mode, - &columns, &rows) != GRUB_EFI_SUCCESS) + if (grub_prepare_for_text_output (term) != GRUB_ERR_NONE || + efi_call_4 (o->query_mode, o, o->mode->mode, + &columns, &rows) != GRUB_EFI_SUCCESS) { /* Why does this fail? */ columns = 80; @@ -349,7 +384,7 @@ grub_console_getxy (struct grub_term_output *term __attribute__ ((unused))) { grub_efi_simple_text_output_interface_t *o; - if (grub_efi_is_finished) + if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE) return (struct grub_term_coordinate) { 0, 0 }; o = grub_efi_system_table->con_out; @@ -357,12 +392,12 @@ grub_console_getxy (struct grub_term_output *term __attribute__ ((unused))) } static void -grub_console_gotoxy (struct grub_term_output *term __attribute__ ((unused)), +grub_console_gotoxy (struct grub_term_output *term, struct grub_term_coordinate pos) { grub_efi_simple_text_output_interface_t *o; - if (grub_efi_is_finished) + if (grub_prepare_for_text_output (term) != GRUB_ERR_NONE) return; o = grub_efi_system_table->con_out; @@ -375,7 +410,7 @@ grub_console_cls (struct grub_term_output *term __attribute__ ((unused))) grub_efi_simple_text_output_interface_t *o; grub_efi_int32_t orig_attr; - if (grub_efi_is_finished) + if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE) return; o = grub_efi_system_table->con_out; @@ -385,19 +420,15 @@ grub_console_cls (struct grub_term_output *term __attribute__ ((unused))) efi_call_2 (o->set_attributes, o, orig_attr); } -static grub_err_t -grub_efi_console_output_init (struct grub_term_output *term) -{ - grub_efi_set_text_mode (1); - grub_console_setcursor (term, 1); - return 0; -} - static grub_err_t grub_efi_console_output_fini (struct grub_term_output *term) { + if (text_mode != GRUB_TEXT_MODE_AVAILABLE) + return 0; + grub_console_setcursor (term, 0); grub_efi_set_text_mode (0); + text_mode = GRUB_TEXT_MODE_UNDEFINED; return 0; } @@ -412,7 +443,6 @@ static struct grub_term_input grub_console_term_input = static struct grub_term_output grub_console_term_output = { .name = "console", - .init = grub_efi_console_output_init, .fini = grub_efi_console_output_fini, .putchar = grub_console_putchar, .getwh = grub_console_getwh, @@ -428,14 +458,6 @@ static struct grub_term_output grub_console_term_output = void grub_console_init (void) { - /* FIXME: it is necessary to consider the case where no console control - is present but the default is already in text mode. */ - if (! grub_efi_set_text_mode (1)) - { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot set text mode"); - return; - } - grub_term_register_output ("console", &grub_console_term_output); grub_term_register_input ("console", &grub_console_term_input); } diff --git a/include/grub/term.h b/include/grub/term.h index c21513338..9da03dc75 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -75,9 +75,11 @@ /* These are used to represent the various color states we use. */ typedef enum { + /* Used for uninitialized grub_term_color_state variables */ + GRUB_TERM_COLOR_UNDEFINED = -1, /* The color used to display all text that does not use the user defined colors below. */ - GRUB_TERM_COLOR_STANDARD, + GRUB_TERM_COLOR_STANDARD = 0, /* The user defined colors for normal text. */ GRUB_TERM_COLOR_NORMAL, /* The user defined colors for highlighted text. */