summaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2021-12-10 10:50:38 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2021-12-13 23:37:32 +0100
commite4a8037de80559271ff143bcd93540317422577a (patch)
tree4b3c5142df5a2967eed1ea840300834379ac2925 /drivers/serial
parenta6f2d7f4ace14abbfeb2fd297f56932f55fd221d (diff)
downloadbarebox-e4a8037de80559271ff143bcd93540317422577a.tar.gz
barebox-e4a8037de80559271ff143bcd93540317422577a.tar.xz
efi-stdio: improve escape sequence parsing
Instead of dispatching the escape sequences character by character, parse the number arguments upfront and use them later. Also parse background and foreground colours and also the inverse status correctly. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/efi-stdio.c155
1 files changed, 89 insertions, 66 deletions
diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c
index dc1b45340c..c2a29f8b2f 100644
--- a/drivers/serial/efi-stdio.c
+++ b/drivers/serial/efi-stdio.c
@@ -27,7 +27,9 @@ struct efi_console_priv {
unsigned long columns, rows;
- int current_color;
+ int fg;
+ int bg;
+ bool inverse;
s16 *blank_line;
};
@@ -134,11 +136,45 @@ static void clear_to_eol(struct efi_console_priv *priv)
priv->out->output_string(priv->out, priv->blank_line + pos);
}
+static int ansi_to_efi_color(int ansi)
+{
+ switch (ansi) {
+ case 30:
+ return EFI_BLACK;
+ case 31:
+ return EFI_RED;
+ case 32:
+ return EFI_GREEN;
+ case 33:
+ return EFI_YELLOW;
+ case 34:
+ return EFI_BLUE;
+ case 35:
+ return EFI_MAGENTA;
+ case 36:
+ return EFI_CYAN;
+ case 37:
+ return EFI_WHITE;
+ case 39:
+ return EFI_LIGHTGRAY;
+ }
+
+ return -1;
+}
+
+static void set_fg_bg_colors(struct efi_console_priv *priv)
+{
+ int fg = priv->inverse ? priv->bg : priv->fg;
+ int bg = priv->inverse ? priv->fg : priv->bg;
+
+ priv->out->set_attribute(priv->out, EFI_TEXT_ATTR(fg , bg));
+}
+
static int efi_process_square_bracket(struct efi_console_priv *priv, const char *inp)
{
- int x, y;
char *endp;
int retlen;
+ int arg0 = -1, arg1 = -1, arg2 = -1;
endp = strpbrk(inp, "ABCDEFGHJKmr");
if (!endp)
@@ -148,73 +184,59 @@ static int efi_process_square_bracket(struct efi_console_priv *priv, const char
inp++;
- switch (*endp) {
- case 'A':
- /* Cursor up */
- case 'B':
- /* Cursor down */
- case 'C':
- /* Cursor right */
- case 'D':
- /* Cursor left */
- case 'H':
- /* home */
- case 'F':
- /* end */
- return retlen;
- case 'K':
- clear_to_eol(priv);
- return retlen;
- }
-
- if (*inp == '2' && *(inp + 1) == 'J') {
- priv->out->clear_screen(priv->out);
- return retlen;
- }
-
- if (*inp == '0' && *(inp + 1) == 'm') {
- priv->out->set_attribute(priv->out,
- EFI_TEXT_ATTR(EFI_WHITE, EFI_BLACK));
- return retlen;
- }
-
- if (*inp == '7' && *(inp + 1) == 'm') {
- priv->out->set_attribute(priv->out,
- EFI_TEXT_ATTR(EFI_BLACK, priv->current_color));
- return retlen;
- }
-
- if (*inp == '1' &&
- *(inp + 1) == ';' &&
- *(inp + 2) == '3' &&
- *(inp + 3) &&
- *(inp + 4) == 'm') {
- int color;
- switch (*(inp + 3)) {
- case '1': color = EFI_RED; break;
- case '4': color = EFI_BLUE; break;
- case '2': color = EFI_GREEN; break;
- case '6': color = EFI_CYAN; break;
- case '3': color = EFI_YELLOW; break;
- case '5': color = EFI_MAGENTA; break;
- case '7': color = EFI_WHITE; break;
- default: color = EFI_WHITE; break;
+ if (isdigit(*inp)) {
+ char *e;
+ arg0 = simple_strtoul(inp, &e, 10);
+ if (*e == ';') {
+ arg1 = simple_strtoul(e + 1, &e, 10);
+ if (*e == ';')
+ arg2 = simple_strtoul(e + 1, &e, 10);
}
-
- priv->current_color = color;
-
- priv->out->set_attribute(priv->out,
- EFI_TEXT_ATTR(color, EFI_BLACK));
- return retlen;
}
- y = simple_strtoul(inp, &endp, 10);
- if (*endp == ';') {
- x = simple_strtoul(endp + 1, &endp, 10);
- if (*endp == 'H') {
- priv->out->set_cursor_position(priv->out, x - 1, y - 1);
- return retlen;
+ switch (*endp) {
+ case 'K':
+ switch (arg0) {
+ case 0:
+ case -1:
+ clear_to_eol(priv);
+ break;
+ }
+ break;
+ case 'J':
+ switch (arg0) {
+ case 2:
+ priv->out->clear_screen(priv->out);
+ break;
+ }
+ break;
+ case 'H':
+ if (arg0 >= 0 && arg1 >= 0)
+ priv->out->set_cursor_position(priv->out, arg1 - 1, arg0 - 1);
+ break;
+ case 'm':
+ switch (arg0) {
+ case 0:
+ priv->inverse = false;
+ priv->fg = EFI_LIGHTGRAY;
+ priv->bg = EFI_BLACK;
+ set_fg_bg_colors(priv);
+ break;
+ case 7:
+ priv->inverse = true;
+ set_fg_bg_colors(priv);
+ break;
+ case 1:
+ priv->fg = ansi_to_efi_color(arg1);
+ if (priv->fg < 0)
+ priv->fg = EFI_LIGHTGRAY;
+ priv->bg = ansi_to_efi_color(arg2);
+ if (priv->bg < 0)
+ priv->bg = EFI_BLACK;
+ set_fg_bg_colors(priv);
+ break;
}
+ break;
}
return retlen;
@@ -347,7 +369,8 @@ static int efi_console_probe(struct device_d *dev)
dev_dbg(dev, "Using simple_text_input_ex_protocol\n");
}
- priv->current_color = EFI_WHITE;
+ priv->fg = EFI_LIGHTGRAY;
+ priv->bg = EFI_BLACK;
efi_set_mode(priv);