dcavalca / rpms / grub2

Forked from rpms/grub2 3 years ago
Clone

Blame SOURCES/0182-EFI-console-Do-not-set-text-mode-until-we-actually-n.patch

8631a2
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
8631a2
From: Hans de Goede <hdegoede@redhat.com>
8631a2
Date: Tue, 6 Mar 2018 17:11:15 +0100
8631a2
Subject: [PATCH] EFI: console: Do not set text-mode until we actually need it
8631a2
8631a2
If we're running with a hidden menu we may never need text mode, so do not
8631a2
change the video-mode to text until we actually need it.
8631a2
8631a2
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
8631a2
---
8631a2
 grub-core/term/efi/console.c | 65 ++++++++++++++++++++++++++++++--------------
8631a2
 1 file changed, 44 insertions(+), 21 deletions(-)
8631a2
8631a2
diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c
8631a2
index 4840cc59d3f..051633d71e9 100644
8631a2
--- a/grub-core/term/efi/console.c
8631a2
+++ b/grub-core/term/efi/console.c
8631a2
@@ -24,6 +24,11 @@
8631a2
 #include <grub/efi/api.h>
8631a2
 #include <grub/efi/console.h>
8631a2
 
8631a2
+static grub_err_t grub_prepare_for_text_output(struct grub_term_output *term);
8631a2
+
8631a2
+static int text_mode_available = -1;
8631a2
+static int text_colorstate = -1;
8631a2
+
8631a2
 static grub_uint32_t
8631a2
 map_char (grub_uint32_t c)
8631a2
 {
8631a2
@@ -66,14 +71,14 @@ map_char (grub_uint32_t c)
8631a2
 }
8631a2
 
8631a2
 static void
8631a2
-grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)),
8631a2
+grub_console_putchar (struct grub_term_output *term,
8631a2
 		      const struct grub_unicode_glyph *c)
8631a2
 {
8631a2
   grub_efi_char16_t str[2 + 30];
8631a2
   grub_efi_simple_text_output_interface_t *o;
8631a2
   unsigned i, j;
8631a2
 
8631a2
-  if (grub_efi_is_finished)
8631a2
+  if (grub_prepare_for_text_output (term))
8631a2
     return;
8631a2
 
8631a2
   o = grub_efi_system_table->con_out;
8631a2
@@ -223,14 +228,15 @@ grub_console_getkey (struct grub_term_input *term)
8631a2
 }
8631a2
 
8631a2
 static struct grub_term_coordinate
8631a2
-grub_console_getwh (struct grub_term_output *term __attribute__ ((unused)))
8631a2
+grub_console_getwh (struct grub_term_output *term)
8631a2
 {
8631a2
   grub_efi_simple_text_output_interface_t *o;
8631a2
   grub_efi_uintn_t columns, rows;
8631a2
 
8631a2
   o = grub_efi_system_table->con_out;
8631a2
-  if (grub_efi_is_finished || efi_call_4 (o->query_mode, o, o->mode->mode,
8631a2
-					  &columns, &rows) != GRUB_EFI_SUCCESS)
8631a2
+  if (grub_prepare_for_text_output (term) != GRUB_ERR_NONE ||
8631a2
+      efi_call_4 (o->query_mode, o, o->mode->mode,
8631a2
+		  &columns, &rows) != GRUB_EFI_SUCCESS)
8631a2
     {
8631a2
       /* Why does this fail?  */
8631a2
       columns = 80;
8631a2
@@ -245,7 +251,7 @@ grub_console_getxy (struct grub_term_output *term __attribute__ ((unused)))
8631a2
 {
8631a2
   grub_efi_simple_text_output_interface_t *o;
8631a2
 
8631a2
-  if (grub_efi_is_finished)
8631a2
+  if (grub_efi_is_finished || text_mode_available != 1)
8631a2
     return (struct grub_term_coordinate) { 0, 0 };
8631a2
 
8631a2
   o = grub_efi_system_table->con_out;
8631a2
@@ -253,12 +259,12 @@ grub_console_getxy (struct grub_term_output *term __attribute__ ((unused)))
8631a2
 }
8631a2
 
8631a2
 static void
8631a2
-grub_console_gotoxy (struct grub_term_output *term __attribute__ ((unused)),
8631a2
+grub_console_gotoxy (struct grub_term_output *term,
8631a2
 		     struct grub_term_coordinate pos)
8631a2
 {
8631a2
   grub_efi_simple_text_output_interface_t *o;
8631a2
 
8631a2
-  if (grub_efi_is_finished)
8631a2
+  if (grub_prepare_for_text_output (term))
8631a2
     return;
8631a2
 
8631a2
   o = grub_efi_system_table->con_out;
8631a2
@@ -271,7 +277,7 @@ grub_console_cls (struct grub_term_output *term __attribute__ ((unused)))
8631a2
   grub_efi_simple_text_output_interface_t *o;
8631a2
   grub_efi_int32_t orig_attr;
8631a2
 
8631a2
-  if (grub_efi_is_finished)
8631a2
+  if (grub_efi_is_finished || text_mode_available != 1)
8631a2
     return;
8631a2
 
8631a2
   o = grub_efi_system_table->con_out;
8631a2
@@ -291,6 +297,12 @@ grub_console_setcolorstate (struct grub_term_output *term
8631a2
   if (grub_efi_is_finished)
8631a2
     return;
8631a2
 
8631a2
+  if (text_mode_available != 1) {
8631a2
+    /* Avoid "color_normal" environment writes causing a switch to textmode */
8631a2
+    text_colorstate = state;
8631a2
+    return;
8631a2
+  }
8631a2
+
8631a2
   o = grub_efi_system_table->con_out;
8631a2
 
8631a2
   switch (state) {
8631a2
@@ -315,7 +327,7 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
8631a2
 {
8631a2
   grub_efi_simple_text_output_interface_t *o;
8631a2
 
8631a2
-  if (grub_efi_is_finished)
8631a2
+  if (grub_efi_is_finished || text_mode_available != 1)
8631a2
     return;
8631a2
 
8631a2
   o = grub_efi_system_table->con_out;
8631a2
@@ -323,18 +335,38 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
8631a2
 }
8631a2
 
8631a2
 static grub_err_t
8631a2
-grub_efi_console_output_init (struct grub_term_output *term)
8631a2
+grub_prepare_for_text_output(struct grub_term_output *term)
8631a2
 {
8631a2
-  grub_efi_set_text_mode (1);
8631a2
+  if (grub_efi_is_finished)
8631a2
+    return GRUB_ERR_BAD_DEVICE;
8631a2
+
8631a2
+  if (text_mode_available != -1)
8631a2
+    return text_mode_available ? 0 : GRUB_ERR_BAD_DEVICE;
8631a2
+
8631a2
+  if (! grub_efi_set_text_mode (1))
8631a2
+    {
8631a2
+      /* This really should never happen */
8631a2
+      grub_error (GRUB_ERR_BAD_DEVICE, "cannot set text mode");
8631a2
+      text_mode_available = 0;
8631a2
+      return GRUB_ERR_BAD_DEVICE;
8631a2
+    }
8631a2
+
8631a2
   grub_console_setcursor (term, 1);
8631a2
+  if (text_colorstate != -1)
8631a2
+    grub_console_setcolorstate (term, text_colorstate);
8631a2
+  text_mode_available = 1;
8631a2
   return 0;
8631a2
 }
8631a2
 
8631a2
 static grub_err_t
8631a2
 grub_efi_console_output_fini (struct grub_term_output *term)
8631a2
 {
8631a2
+  if (text_mode_available != 1)
8631a2
+    return 0;
8631a2
+
8631a2
   grub_console_setcursor (term, 0);
8631a2
   grub_efi_set_text_mode (0);
8631a2
+  text_mode_available = -1;
8631a2
   return 0;
8631a2
 }
8631a2
 
8631a2
@@ -348,7 +380,6 @@ static struct grub_term_input grub_console_term_input =
8631a2
 static struct grub_term_output grub_console_term_output =
8631a2
   {
8631a2
     .name = "console",
8631a2
-    .init = grub_efi_console_output_init,
8631a2
     .fini = grub_efi_console_output_fini,
8631a2
     .putchar = grub_console_putchar,
8631a2
     .getwh = grub_console_getwh,
8631a2
@@ -364,14 +395,6 @@ static struct grub_term_output grub_console_term_output =
8631a2
 void
8631a2
 grub_console_init (void)
8631a2
 {
8631a2
-  /* FIXME: it is necessary to consider the case where no console control
8631a2
-     is present but the default is already in text mode.  */
8631a2
-  if (! grub_efi_set_text_mode (1))
8631a2
-    {
8631a2
-      grub_error (GRUB_ERR_BAD_DEVICE, "cannot set text mode");
8631a2
-      return;
8631a2
-    }
8631a2
-
8631a2
   grub_term_register_output ("console", &grub_console_term_output);
8631a2
   grub_term_register_input ("console", &grub_console_term_input);
8631a2
 }