summaryrefslogtreecommitdiff
path: root/config/u-boot/default/patches/0002-video-improve-UEFI-experience-on-DM_VIDEO.patch
blob: cd5a2751ac9c3dd600bf533a2ccf75b4531eca03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
From ac31b6bc4bcfc328342ec1677db5b80548d43b35 Mon Sep 17 00:00:00 2001
From: Andre Przywara <andre.przywara@arm.com>
Date: Mon, 10 Jan 2022 00:56:31 +0000
Subject: [PATCH 1/4] 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 <andre.przywara@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
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 <alpernebiyasak@gmail.com>
---
 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 b5d0e3dceca3..60de5fcacb82 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 b5b3b6625902..a6d994bd637c 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -56,6 +56,26 @@ static 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)
 {
@@ -63,6 +83,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)
@@ -89,6 +111,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;
 
@@ -282,6 +306,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;
 
@@ -456,6 +488,11 @@ int vidconsole_put_char(struct udevice *dev, char ch)
 	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
 	int 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;
@@ -470,6 +507,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':
@@ -477,6 +515,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;
 
@@ -494,6 +533,8 @@ int vidconsole_put_char(struct udevice *dev, char ch)
 		break;
 	}
 
+	draw_cursor(dev, true);
+
 	return 0;
 }
 
@@ -646,6 +687,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 2694e44f6ecf..949abb3861e7 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -59,6 +59,7 @@ struct vidconsole_priv {
 	int escape_len;
 	int row_saved;
 	int col_saved;
+	bool cursor_visible;
 	char escape_buf[32];
 };
 
-- 
2.42.0


From ab8ddf81c1442717f6ffddc3460d4e4adbd5b570 Mon Sep 17 00:00:00 2001
From: Andre Przywara <andre.przywara@arm.com>
Date: Mon, 10 Jan 2022 00:56:36 +0000
Subject: [PATCH 2/4] 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 <andre.przywara@arm.com>
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 cc44b38bc23a..175731ae96b6 100644
--- a/lib/efi_selftest/efi_selftest_textoutput.c
+++ b/lib/efi_selftest/efi_selftest_textoutput.c
@@ -118,6 +118,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");
 
 	return EFI_ST_SUCCESS;
-- 
2.42.0


From 48e918c31a46815325ffd7a77eb7a3ffedf8e59c Mon Sep 17 00:00:00 2001
From: Andre Przywara <andre.przywara@arm.com>
Date: Mon, 10 Jan 2022 00:56:37 +0000
Subject: [PATCH 3/4] 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 <andre.przywara@arm.com>
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 175731ae96b6..3c6870f74241 100644
--- a/lib/efi_selftest/efi_selftest_textoutput.c
+++ b/lib/efi_selftest/efi_selftest_textoutput.c
@@ -123,6 +123,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");
 
 	return EFI_ST_SUCCESS;
-- 
2.42.0


From 407ca7e821aabf240c2602dd0db56d6398a0c03b Mon Sep 17 00:00:00 2001
From: Andre Przywara <andre.przywara@arm.com>
Date: Mon, 10 Jan 2022 00:56:38 +0000
Subject: [PATCH 4/4] video: Convert UTF-8 input stream to the 437 code page

The bitmap fonts (VGA 8x16 and friends) we import from Linux use the
437 code page to map their glyphs. For U-Boot's own purposes this is
probably fine, but UEFI applications output Unicode, which only matches
in the very basic first 127 characters.

Add a function that converts UTF-8 character sequences into the
respective CP437 code point, as far as the characters defined in there
allow this. This includes quite some international and box drawing
characters, which are used by UEFI applications.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Link: https://lore.kernel.org/r/20220110005638.21599-9-andre.przywara@arm.com
[Alper: Rebase for makefile changes, use $(SPL_TPL_)VIDEO]
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
---
 drivers/video/Makefile            |   1 +
 drivers/video/utf8_cp437.c        | 169 ++++++++++++++++++++++++++++++
 drivers/video/vidconsole-uclass.c |   6 +-
 include/video_console.h           |   9 ++
 4 files changed, 184 insertions(+), 1 deletion(-)
 create mode 100644 drivers/video/utf8_cp437.c

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index d13af9f3b19b..4b1983990aba 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_DISPLAY) += display-uclass.o
 obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi-host-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)VIDEO) += video-uclass.o vidconsole-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)VIDEO) += video_bmp.o
+obj-$(CONFIG_$(SPL_TPL_)VIDEO) += utf8_cp437.o
 obj-$(CONFIG_$(SPL_TPL_)PANEL) += panel-uclass.o
 obj-$(CONFIG_PANEL_HX8238D) += hx8238d.o
 obj-$(CONFIG_$(SPL_TPL_)SIMPLE_PANEL) += simple_panel.o
diff --git a/drivers/video/utf8_cp437.c b/drivers/video/utf8_cp437.c
new file mode 100644
index 000000000000..cab68b92b6e3
--- /dev/null
+++ b/drivers/video/utf8_cp437.c
@@ -0,0 +1,169 @@
+/*
+ * Convert UTF-8 bytes into a code page 437 character.
+ * Based on the table in the Code_page_437 Wikipedia page.
+ */
+
+#include <linux/types.h>
+
+uint8_t code_points_00a0[] = {
+	255, 173, 155, 156,   7, 157,   7,  21,
+	  7,   7, 166, 174, 170,   7,   7,   7,
+	248, 241, 253,   7,   7, 230,  20, 250,
+	  7,   7, 167, 175, 172, 171,   7, 168,
+	  7,   7,   7,   7, 142, 143, 146, 128,
+	  7, 144,   7,   7,   7,   7,   7,   7,
+	  7, 165,   7,   7,   7,   7, 153,   7,
+	  7,   7,   7,   7, 154,   7,   7, 225,
+	133, 160, 131,   7, 132, 134, 145, 135,
+	138, 130, 136, 137, 141, 161, 140, 139,
+	  7, 164, 149, 162, 147,   7, 148, 246,
+	  7, 151, 163, 150, 129,   7,   7, 152,
+};
+
+uint8_t code_points_2550[] = {
+	205, 186, 213, 214, 201, 184, 183, 187,
+	212, 211, 200, 190, 189, 188, 198, 199,
+	204, 181, 182, 185, 209, 210, 203, 207,
+	208, 202, 216, 215, 206
+};
+
+static uint8_t utf8_convert_11bit(uint16_t code)
+{
+	switch (code) {
+	case 0x0192: return 159;
+	case 0x0393: return 226;
+	case 0x0398: return 233;
+	case 0x03A3: return 228;
+	case 0x03A6: return 232;
+	case 0x03A9: return 234;
+	case 0x03B1: return 224;
+	case 0x03B4: return 235;
+	case 0x03B5: return 238;
+	case 0x03C0: return 227;
+	case 0x03C3: return 229;
+	case 0x03C4: return 231;
+	case 0x03C6: return 237;
+	}
+
+	return 0;
+};
+
+static uint8_t utf8_convert_2xxx(uint16_t code)
+{
+	switch (code) {
+	case 0x2022: return 7;
+	case 0x203C: return 19;
+	case 0x207F: return 252;
+	case 0x20A7: return 158;
+	case 0x2190: return 27;
+	case 0x2191: return 24;
+	case 0x2192: return 26;
+	case 0x2193: return 25;
+	case 0x2194: return 29;
+	case 0x2195: return 18;
+	case 0x21A8: return 23;
+	case 0x2219: return 249;
+	case 0x221A: return 251;
+	case 0x221E: return 236;
+	case 0x221F: return 28;
+	case 0x2229: return 239;
+	case 0x2248: return 247;
+	case 0x2261: return 240;
+	case 0x2264: return 243;
+	case 0x2265: return 242;
+	case 0x2310: return 169;
+	case 0x2320: return 244;
+	case 0x2321: return 245;
+	case 0x2500: return 196;
+	case 0x2502: return 179;
+	case 0x250C: return 218;
+	case 0x2510: return 191;
+	case 0x2514: return 192;
+	case 0x2518: return 217;
+	case 0x251C: return 195;
+	case 0x2524: return 180;
+	case 0x252C: return 194;
+	case 0x2534: return 193;
+	case 0x253C: return 197;
+	case 0x2580: return 223;
+	case 0x2584: return 220;
+	case 0x2588: return 219;
+	case 0x258C: return 221;
+	case 0x2590: return 222;
+	case 0x2591: return 176;
+	case 0x2592: return 177;
+	case 0x2593: return 178;
+	case 0x25A0: return 254;
+	case 0x25AC: return 22;
+	case 0x25B2: return 30;
+	case 0x25BA: return 16;
+	case 0x25BC: return 31;
+	case 0x25C4: return 17;
+	case 0x25CB: return 9;
+	case 0x25D8: return 8;
+	case 0x25D9: return 10;
+	case 0x263A: return 1;
+	case 0x263B: return 2;
+	case 0x263C: return 15;
+	case 0x2640: return 12;
+	case 0x2642: return 11;
+	case 0x2660: return 6;
+	case 0x2663: return 5;
+	case 0x2665: return 3;
+	case 0x2666: return 4;
+	case 0x266A: return 13;
+	case 0x266B: return 14;
+	}
+
+	return 0;
+}
+
+uint8_t convert_uc16_to_cp437(uint16_t code)
+{
+	if (code < 0x7f)		// ASCII
+		return code;
+	if (code < 0xa0)		// high control characters
+		return code;
+	if (code < 0x100)		// international characters
+		return code_points_00a0[code - 0xa0];
+	if (code < 0x800)
+		return utf8_convert_11bit(code);
+	if (code >= 0x2550 && code < 0x256d)	// block graphics
+		return code_points_2550[code - 0x2550];
+
+	return utf8_convert_2xxx(code);
+}
+
+uint8_t convert_utf8_to_cp437(uint8_t c, uint32_t *esc)
+{
+	int shift;
+	uint16_t ucs;
+
+	if (c < 127)			// ASCII
+		return c;
+	if (c == 127)
+		return 8;		// DEL (?)
+
+	switch (c & 0xf0) {
+	case 0xc0: case 0xd0:		// two bytes sequence
+		*esc = (1U << 24) | ((c & 0x1f) << 6);
+		return 0;
+	case 0xe0:			// three bytes sequence
+		*esc = (2U << 24) | ((c & 0x0f) << 12);
+		return 0;
+	case 0xf0:			// four bytes sequence
+		*esc = (3U << 24) | ((c & 0x07) << 18);
+		return 0;
+	case 0x80: case 0x90: case 0xa0: case 0xb0:	// continuation
+		shift = (*esc >> 24) - 1;
+		ucs = *esc & 0xffffff;
+		if (shift) {
+			*esc = (shift << 24) | ucs | (c & 0x3f) << (shift * 6);
+			return 0;
+		}
+		*esc = 0;
+		return convert_uc16_to_cp437(ucs | (c & 0x3f));
+	}
+
+	return 0;
+}
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index a6d994bd637c..a4029a58660b 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -486,6 +486,7 @@ static int vidconsole_output_glyph(struct udevice *dev, char ch)
 int vidconsole_put_char(struct udevice *dev, char ch)
 {
 	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+	uint8_t cp437;
 	int ret;
 
 	/*
@@ -527,7 +528,10 @@ int vidconsole_put_char(struct udevice *dev, char ch)
 		priv->last_ch = 0;
 		break;
 	default:
-		ret = vidconsole_output_glyph(dev, ch);
+		cp437 = convert_utf8_to_cp437(ch, &priv->ucs);
+		if (cp437 == 0)
+			return 0;
+		ret = vidconsole_output_glyph(dev, cp437);
 		if (ret < 0)
 			return ret;
 		break;
diff --git a/include/video_console.h b/include/video_console.h
index 949abb3861e7..dbfb389f324f 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -59,6 +59,7 @@ struct vidconsole_priv {
 	int escape_len;
 	int row_saved;
 	int col_saved;
+	u32 ucs;
 	bool cursor_visible;
 	char escape_buf[32];
 };
@@ -457,4 +458,12 @@ static inline int vidconsole_memmove(struct udevice *dev, void *dst,
 
 #endif
 
+/*
+ * Convert an UTF-8 byte into the corresponding character in the CP437
+ * code page. Returns 0 if that character is part of a multi-byte sequence.
+ * for which *esc holds the state of. Repeatedly feed in more bytes until
+ * the return value returns a non-0 character.
+ */
+uint8_t convert_utf8_to_cp437(uint8_t c, uint32_t *esc);
+
 #endif
-- 
2.42.0