diff options
author | Rob Clark | 2017-09-13 18:05:44 -0400 |
---|---|---|
committer | Alexander Graf | 2017-09-20 11:29:35 +0200 |
commit | 3a45bc7faa5f93513369fc4447db2c379c19b2ca (patch) | |
tree | c218322a6b80d45756e0d2991e2dbe6bab4babf4 | |
parent | a18c5a8382284037ea8fa4742736a65317476d23 (diff) |
efi_loader: Some console improvements for vidconsole
1) use fputs() to reduce cache flushes from once-per-char to
once-per-string
2) handle \r, \t, and \b in addition to just \n for tracking
cursor position
3) cursor row/col are zero based, not one based
Signed-off-by: Rob Clark <robdclark@gmail.com>
[agraf: s/unsigned/unsigned int/]
Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r-- | include/efi_api.h | 6 | ||||
-rw-r--r-- | lib/efi_loader/efi_console.c | 58 |
2 files changed, 39 insertions, 25 deletions
diff --git a/include/efi_api.h b/include/efi_api.h index 604c5b7ec4e..c3b9032a48d 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -29,6 +29,8 @@ enum efi_timer_delay { }; #define UINTN size_t +typedef long INTN; +typedef uint16_t *efi_string_t; #define EVT_TIMER 0x80000000 #define EVT_RUNTIME 0x40000000 @@ -427,10 +429,10 @@ struct efi_simple_text_output_protocol { void *reset; efi_status_t (EFIAPI *output_string)( struct efi_simple_text_output_protocol *this, - const unsigned short *str); + const efi_string_t str); efi_status_t (EFIAPI *test_string)( struct efi_simple_text_output_protocol *this, - const unsigned short *str); + const efi_string_t str); efi_status_t(EFIAPI *query_mode)( struct efi_simple_text_output_protocol *this, unsigned long mode_number, unsigned long *columns, diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index d596c582413..fd5398d61d9 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -140,34 +140,46 @@ static efi_status_t EFIAPI efi_cout_reset( return EFI_EXIT(EFI_UNSUPPORTED); } -static void print_unicode_in_utf8(u16 c) -{ - char utf8[MAX_UTF8_PER_UTF16] = { 0 }; - utf16_to_utf8((u8 *)utf8, &c, 1); - puts(utf8); -} - static efi_status_t EFIAPI efi_cout_output_string( struct efi_simple_text_output_protocol *this, - const unsigned short *string) + const efi_string_t string) { - struct cout_mode *mode; - u16 ch; + struct simple_text_output_mode *con = &efi_con_mode; + struct cout_mode *mode = &efi_cout_modes[con->mode]; - mode = &efi_cout_modes[efi_con_mode.mode]; EFI_ENTRY("%p, %p", this, string); - for (;(ch = *string); string++) { - print_unicode_in_utf8(ch); - efi_con_mode.cursor_column++; - if (ch == '\n') { - efi_con_mode.cursor_column = 1; - efi_con_mode.cursor_row++; - } else if (efi_con_mode.cursor_column > mode->columns) { - efi_con_mode.cursor_column = 1; - efi_con_mode.cursor_row++; + + unsigned int n16 = utf16_strlen(string); + char buf[MAX_UTF8_PER_UTF16 * n16 + 1]; + char *p; + + *utf16_to_utf8((u8 *)buf, string, n16) = '\0'; + + fputs(stdout, buf); + + for (p = buf; *p; p++) { + switch (*p) { + case '\r': /* carriage-return */ + con->cursor_column = 0; + break; + case '\n': /* newline */ + con->cursor_column = 0; + con->cursor_row++; + break; + case '\t': /* tab, assume 8 char align */ + break; + case '\b': /* backspace */ + con->cursor_column = max(0, con->cursor_column - 1); + break; + default: + con->cursor_column++; + break; + } + if (con->cursor_column >= mode->columns) { + con->cursor_column = 0; + con->cursor_row++; } - if (efi_con_mode.cursor_row > mode->rows) - efi_con_mode.cursor_row = mode->rows; + con->cursor_row = min(con->cursor_row, (s32)mode->rows - 1); } return EFI_EXIT(EFI_SUCCESS); @@ -175,7 +187,7 @@ static efi_status_t EFIAPI efi_cout_output_string( static efi_status_t EFIAPI efi_cout_test_string( struct efi_simple_text_output_protocol *this, - const unsigned short *string) + const efi_string_t string) { EFI_ENTRY("%p, %p", this, string); return EFI_EXIT(EFI_SUCCESS); |