@ -9,11 +9,38 @@
# include <common.h>
# include <efi_loader.h>
/* If we can't determine the console size, default to 80x24 */
static int console_columns = 80 ;
static int console_rows = 24 ;
static bool console_size_queried ;
# define EFI_COUT_MODE_2 2
# define EFI_MAX_COUT_MODE 3
struct cout_mode {
unsigned long columns ;
unsigned long rows ;
int present ;
} ;
static struct cout_mode efi_cout_modes [ ] = {
/* EFI Mode 0 is 80x25 and always present */
{
. columns = 80 ,
. rows = 25 ,
. present = 1 ,
} ,
/* EFI Mode 1 is always 80x50 */
{
. columns = 80 ,
. rows = 50 ,
. present = 0 ,
} ,
/* Value are unknown until we query the console */
{
. columns = 0 ,
. rows = 0 ,
. present = 0 ,
} ,
} ;
const efi_guid_t efi_guid_console_control = CONSOLE_CONTROL_GUID ;
# define cESC '\x1b'
@ -56,8 +83,9 @@ const struct efi_console_control_protocol efi_console_control = {
. lock_std_in = efi_cin_lock_std_in ,
} ;
/* Default to mode 0 */
static struct simple_text_output_mode efi_con_mode = {
. max_mode = 0 ,
. max_mode = 1 ,
. mode = 0 ,
. attribute = 0 ,
. cursor_column = 0 ,
@ -131,8 +159,10 @@ static efi_status_t EFIAPI efi_cout_output_string(
struct efi_simple_text_output_protocol * this ,
const unsigned short * string )
{
struct cout_mode * mode ;
u16 ch ;
mode = & efi_cout_modes [ efi_con_mode . mode ] ;
EFI_ENTRY ( " %p, %p " , this , string ) ;
for ( ; ( ch = * string ) ; string + + ) {
print_unicode_in_utf8 ( ch ) ;
@ -140,13 +170,12 @@ static efi_status_t EFIAPI efi_cout_output_string(
if ( ch = = ' \n ' ) {
efi_con_mode . cursor_column = 1 ;
efi_con_mode . cursor_row + + ;
} else if ( efi_con_mode . cursor_column > console_ columns) {
} else if ( efi_con_mode . cursor_column > mode - > columns ) {
efi_con_mode . cursor_column = 1 ;
efi_con_mode . cursor_row + + ;
}
if ( efi_con_mode . cursor_row > console_rows ) {
efi_con_mode . cursor_row = console_rows ;
}
if ( efi_con_mode . cursor_row > mode - > rows )
efi_con_mode . cursor_row = mode - > rows ;
}
return EFI_EXIT ( EFI_SUCCESS ) ;
@ -160,6 +189,14 @@ static efi_status_t EFIAPI efi_cout_test_string(
return EFI_EXIT ( EFI_SUCCESS ) ;
}
static bool cout_mode_matches ( struct cout_mode * mode , int rows , int cols )
{
if ( ! mode - > present )
return false ;
return ( mode - > rows = = rows ) & & ( mode - > columns = = cols ) ;
}
static efi_status_t EFIAPI efi_cout_query_mode (
struct efi_simple_text_output_protocol * this ,
unsigned long mode_number , unsigned long * columns ,
@ -170,6 +207,8 @@ static efi_status_t EFIAPI efi_cout_query_mode(
if ( ! console_size_queried ) {
/* Ask the terminal about its size */
int n [ 3 ] ;
int cols ;
int rows ;
u64 timeout ;
console_size_queried = true ;
@ -191,15 +230,40 @@ static efi_status_t EFIAPI efi_cout_query_mode(
goto out ;
}
console_columns = n [ 2 ] ;
console_rows = n [ 1 ] ;
cols = n [ 2 ] ;
rows = n [ 1 ] ;
/* Test if we can have Mode 1 */
if ( cols > = 80 & & rows > = 50 ) {
efi_cout_modes [ 1 ] . present = 1 ;
efi_con_mode . max_mode = 2 ;
}
/*
* Install our mode as mode 2 if it is different
* than mode 0 or 1 and set it as the currently selected mode
*/
if ( ! cout_mode_matches ( & efi_cout_modes [ 0 ] , rows , cols ) & &
! cout_mode_matches ( & efi_cout_modes [ 1 ] , rows , cols ) ) {
efi_cout_modes [ EFI_COUT_MODE_2 ] . columns = cols ;
efi_cout_modes [ EFI_COUT_MODE_2 ] . rows = rows ;
efi_cout_modes [ EFI_COUT_MODE_2 ] . present = 1 ;
efi_con_mode . max_mode = EFI_MAX_COUT_MODE ;
efi_con_mode . mode = EFI_COUT_MODE_2 ;
}
}
if ( mode_number > = efi_con_mode . max_mode )
return EFI_EXIT ( EFI_UNSUPPORTED ) ;
if ( efi_cout_modes [ mode_number ] . present ! = 1 )
return EFI_EXIT ( EFI_UNSUPPORTED ) ;
out :
if ( columns )
* columns = console_columns ;
* columns = efi_cout_modes [ mode_number ] . columns ;
if ( rows )
* rows = console_rows ;
* rows = efi_cout_modes [ mode_number ] . rows ;
return EFI_EXIT ( EFI_SUCCESS ) ;
}
@ -210,11 +274,15 @@ static efi_status_t EFIAPI efi_cout_set_mode(
{
EFI_ENTRY ( " %p, %ld " , this , mode_number ) ;
/* We only support text output for now */
if ( mode_number = = EFI_CONSOLE_MODE_TEXT )
return EFI_EXIT ( EFI_SUCCESS ) ;
return EFI_EXIT ( EFI_UNSUPPORTED ) ;
if ( mode_number > efi_con_mode . max_mode )
return EFI_EXIT ( EFI_UNSUPPORTED ) ;
efi_con_mode . mode = mode_number ;
efi_con_mode . cursor_column = 0 ;
efi_con_mode . cursor_row = 0 ;
return EFI_EXIT ( EFI_SUCCESS ) ;
}
static efi_status_t EFIAPI efi_cout_set_attribute (