#include <grub/efi/api.h>
#include <grub/efi/console.h>
+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)
{
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;
}
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;
{
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;
}
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;
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;
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;
}
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,
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);
}