aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark2017-09-13 18:05:44 -0400
committerAlexander Graf2017-09-20 11:29:35 +0200
commit3a45bc7faa5f93513369fc4447db2c379c19b2ca (patch)
treec218322a6b80d45756e0d2991e2dbe6bab4babf4
parenta18c5a8382284037ea8fa4742736a65317476d23 (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.h6
-rw-r--r--lib/efi_loader/efi_console.c58
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);