From 03750188cbe305cd8383178a1ee476de2aa5953e Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 10 Jan 2022 00:56:31 +0000 Subject: [PATCH 1/3] video: Add cursor support for video consoles So far the video console is completely lacking any cursor, which makes typing and correcting quite irritating. Add a simple cursor display by writing a SPACE glyph in the background colour to the next character position on the screen. Any typed character will naturally overwrite it, so we need to only explicitly clear it if the next character will appear somewhere else (newline, backspace). Signed-off-by: Andre Przywara Reviewed-by: Simon Glass Tested-by: Simon Glass Link: https://lore.kernel.org/r/20220110005638.21599-2-andre.przywara@arm.com [Alper: Rebase for console_set_font(), reword for CONFIG_VIDEO] Signed-off-by: Alper Nebi Yasak --- drivers/video/console_core.c | 1 + drivers/video/vidconsole-uclass.c | 42 +++++++++++++++++++++++++++++++ include/video_console.h | 1 + 3 files changed, 44 insertions(+) diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c index 939363653f6c..6b531718276f 100644 --- a/drivers/video/console_core.c +++ b/drivers/video/console_core.c @@ -30,6 +30,7 @@ static int console_set_font(struct udevice *dev, struct video_fontdata *fontdata debug("height: %d\n", fontdata->height); priv->fontdata = fontdata; + vc_priv->cursor_visible = true; vc_priv->x_charsize = fontdata->width; vc_priv->y_charsize = fontdata->height; if (vid_priv->rot % 2) { diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 80e7adf6a1a4..8b2ef51f1b3b 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -57,6 +57,26 @@ int vidconsole_entry_start(struct udevice *dev) return ops->entry_start(dev); } +static void draw_cursor(struct udevice *dev, bool state) +{ + struct vidconsole_priv *priv = dev_get_uclass_priv(dev); + struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + u32 tmp; + + if (!priv->cursor_visible) + return; + + if (state) { + tmp = vid_priv->colour_bg; + vid_priv->colour_bg = vid_priv->colour_fg; + } + + vidconsole_putc_xy(dev, priv->xcur_frac, priv->ycur, ' '); + + if (state) + vid_priv->colour_bg = tmp; +} + /* Move backwards one space */ static int vidconsole_back(struct udevice *dev) { @@ -64,6 +84,8 @@ static int vidconsole_back(struct udevice *dev) struct vidconsole_ops *ops = vidconsole_get_ops(dev); int ret; + draw_cursor(dev, false); + if (ops->backspace) { ret = ops->backspace(dev); if (ret != -ENOSYS) @@ -90,6 +112,8 @@ static void vidconsole_newline(struct udevice *dev) const int rows = CONFIG_VAL(CONSOLE_SCROLL_LINES); int i, ret; + draw_cursor(dev, false); + priv->xcur_frac = priv->xstart_frac; priv->ycur += priv->y_charsize; @@ -284,6 +308,14 @@ static void vidconsole_escape_char(struct udevice *dev, char ch) break; } + case 'l': + draw_cursor(dev, false); + priv->cursor_visible = 0; + break; + case 'h': + priv->cursor_visible = 1; + draw_cursor(dev, true); + break; case 'J': { int mode; @@ -458,6 +490,11 @@ int vidconsole_put_char(struct udevice *dev, char ch) struct vidconsole_priv *priv = dev_get_uclass_priv(dev); int cp, ret; + /* + * We don't need to clear the cursor since we are going to overwrite + * that character anyway. + */ + if (priv->escape) { vidconsole_escape_char(dev, ch); return 0; @@ -472,6 +509,7 @@ int vidconsole_put_char(struct udevice *dev, char ch) /* beep */ break; case '\r': + draw_cursor(dev, false); priv->xcur_frac = priv->xstart_frac; break; case '\n': @@ -479,6 +517,7 @@ int vidconsole_put_char(struct udevice *dev, char ch) vidconsole_entry_start(dev); break; case '\t': /* Tab (8 chars alignment) */ + draw_cursor(dev, false); priv->xcur_frac = ((priv->xcur_frac / priv->tab_width_frac) + 1) * priv->tab_width_frac; @@ -503,6 +542,8 @@ int vidconsole_put_char(struct udevice *dev, char ch) break; } + draw_cursor(dev, true); + return 0; } @@ -723,6 +764,7 @@ static int vidconsole_pre_probe(struct udevice *dev) struct video_priv *vid_priv = dev_get_uclass_priv(vid); priv->xsize_frac = VID_TO_POS(vid_priv->xsize); + priv->cursor_visible = false; return 0; } diff --git a/include/video_console.h b/include/video_console.h index 8b5928dc5ebb..00c5ecb664b9 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -66,6 +66,7 @@ struct vidconsole_priv { int escape_len; int row_saved; int col_saved; + bool cursor_visible; char escape_buf[32]; char utf8_buf[5]; }; -- 2.45.2 From f63a54996fdaac7ff995e26fd4318a09a9c14dff Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 10 Jan 2022 00:56:36 +0000 Subject: [PATCH 2/3] efi-selftest: Add international characters test UEFI relies entirely on unicode output, which actual fonts displayed on the screen might not be ready for. Add a test displaying some international characters, to reveal missing glyphs, especially in our builtin fonts. This would be needed to be manually checked on the screen for correctness. Signed-off-by: Andre Przywara Link: https://lore.kernel.org/r/20220110005638.21599-7-andre.przywara@arm.com --- lib/efi_selftest/efi_selftest_textoutput.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index a3023c82567c..2f8d8d323c2b 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -154,6 +154,11 @@ static int execute(void) efi_st_printf("Unicode not handled properly\n"); return EFI_ST_FAILURE; } + ret = con_out->output_string(con_out, L"Österreich Edelweiß Smørrebrød Smörgås Niño René >Ἑλλάς<\n"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for international chars\n"); + return EFI_ST_FAILURE; + } efi_st_printf("\n"); ret = con_out->output_string(con_out, text); if (ret != EFI_ST_SUCCESS) { -- 2.45.2 From cc05aa26c43c35e9155d958400532005ae7eeede Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 10 Jan 2022 00:56:37 +0000 Subject: [PATCH 3/3] efi_selftest: Add box drawing character selftest UEFI applications rely on Unicode output capability, and might use that for drawing pseudo-graphical interfaces using Unicode defined box drawing characters. Add a simple test to display the most basic box characters, which would need to be checked manually on the screen for correctness. To facilitate this, add a three second delay after the output at this point. Signed-off-by: Andre Przywara Link: https://lore.kernel.org/r/20220110005638.21599-8-andre.przywara@arm.com --- lib/efi_selftest/efi_selftest_textoutput.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c index 2f8d8d323c2b..02209a5bf224 100644 --- a/lib/efi_selftest/efi_selftest_textoutput.c +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -159,6 +159,17 @@ static int execute(void) efi_st_error("OutputString failed for international chars\n"); return EFI_ST_FAILURE; } + ret = con_out->output_string(con_out, L"┌─┬─┐\n"); + ret |= con_out->output_string(con_out, L"│ │ │\n"); + ret |= con_out->output_string(con_out, L"├─┼─┤\n"); + ret |= con_out->output_string(con_out, L"│ │ │\n"); + ret |= con_out->output_string(con_out, L"└─┴─┘\n"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("OutputString failed for box drawing chars\n"); + return EFI_ST_FAILURE; + } + con_out->output_string(con_out, L"waiting for admiration...\n"); + EFI_CALL(systab.boottime->stall(3000000)); efi_st_printf("\n"); ret = con_out->output_string(con_out, text); if (ret != EFI_ST_SUCCESS) { -- 2.45.2