1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * efi_selftest_textoutput
4  *
5  * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
6  *
7  * Test the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
8  *
9  * The following services are tested:
10  * OutputString, TestString, SetAttribute.
11  */
12 
13 #include <efi_selftest.h>
14 
15 /*
16  * Execute unit test.
17  *
18  * @return:	EFI_ST_SUCCESS for success
19  */
20 static int execute(void)
21 {
22 	size_t foreground;
23 	size_t background;
24 	size_t attrib;
25 	efi_status_t ret;
26 	s16 col;
27 	u16 cr[] = { 0x0d, 0x00 };
28 	u16 lf[] = { 0x0a, 0x00 };
29 	u16 brahmi[] = { /* 2 Brahmi letters */
30 		0xD804, 0xDC05,
31 		0xD804, 0xDC22,
32 		0};
33 
34 	/* SetAttribute */
35 	efi_st_printf("\nColor palette\n");
36 	for (foreground = 0; foreground < 0x10; ++foreground) {
37 		for (background = 0; background < 0x80; background += 0x10) {
38 			attrib = foreground | background;
39 			con_out->set_attribute(con_out, attrib);
40 			efi_st_printf("%p", (void *)attrib);
41 		}
42 		con_out->set_attribute(con_out, 0);
43 		efi_st_printf("\n");
44 	}
45 	/* TestString */
46 	ret = con_out->test_string(con_out,
47 			L" !\"#$%&'()*+,-./0-9:;<=>?@A-Z[\\]^_`a-z{|}~\n");
48 	if (ret != EFI_ST_SUCCESS) {
49 		efi_st_error("TestString failed for ANSI characters\n");
50 		return EFI_ST_FAILURE;
51 	}
52 	/* OutputString */
53 	ret = con_out->output_string(con_out,
54 				     L"Testing cursor column update\n");
55 	if (ret != EFI_ST_SUCCESS) {
56 		efi_st_error("OutputString failed for ANSI characters");
57 		return EFI_ST_FAILURE;
58 	}
59 	col = con_out->mode->cursor_column;
60 	ret = con_out->output_string(con_out, lf);
61 	if (ret != EFI_ST_SUCCESS) {
62 		efi_st_error("OutputString failed for line feed\n");
63 		return EFI_ST_FAILURE;
64 	}
65 	if (con_out->mode->cursor_column != col) {
66 		efi_st_error("Cursor column changed by line feed\n");
67 		return EFI_ST_FAILURE;
68 	}
69 	ret = con_out->output_string(con_out, cr);
70 	if (ret != EFI_ST_SUCCESS) {
71 		efi_st_error("OutputString failed for carriage return\n");
72 		return EFI_ST_FAILURE;
73 	}
74 	if (con_out->mode->cursor_column) {
75 		efi_st_error("Cursor column not 0 at beginning of line\n");
76 		return EFI_ST_FAILURE;
77 	}
78 	ret = con_out->output_string(con_out, L"123");
79 	if (ret != EFI_ST_SUCCESS) {
80 		efi_st_error("OutputString failed for ANSI characters\n");
81 		return EFI_ST_FAILURE;
82 	}
83 	if (con_out->mode->cursor_column != 3) {
84 		efi_st_error("Cursor column not incremented properly\n");
85 		return EFI_ST_FAILURE;
86 	}
87 	ret = con_out->output_string(con_out, L"\b");
88 	if (ret != EFI_ST_SUCCESS) {
89 		efi_st_error("OutputString failed for backspace\n");
90 		return EFI_ST_FAILURE;
91 	}
92 	if (con_out->mode->cursor_column != 2) {
93 		efi_st_error("Cursor column not decremented properly\n");
94 		return EFI_ST_FAILURE;
95 	}
96 	ret = con_out->output_string(con_out, L"\b\b");
97 	if (ret != EFI_ST_SUCCESS) {
98 		efi_st_error("OutputString failed for backspace\n");
99 		return EFI_ST_FAILURE;
100 	}
101 	if (con_out->mode->cursor_column) {
102 		efi_st_error("Cursor column not decremented properly\n");
103 		return EFI_ST_FAILURE;
104 	}
105 	ret = con_out->output_string(con_out, L"\b\b");
106 	if (ret != EFI_ST_SUCCESS) {
107 		efi_st_error("OutputString failed for backspace\n");
108 		return EFI_ST_FAILURE;
109 	}
110 	if (con_out->mode->cursor_column) {
111 		efi_st_error("Cursor column decremented past zero\n");
112 		return EFI_ST_FAILURE;
113 	}
114 	ret = con_out->output_string(con_out, brahmi);
115 	if (ret != EFI_ST_SUCCESS) {
116 		efi_st_todo("Unicode output not fully supported\n");
117 	} else if (con_out->mode->cursor_column != 2) {
118 		efi_st_printf("Unicode not handled properly\n");
119 		return EFI_ST_FAILURE;
120 	}
121 	efi_st_printf("\n");
122 
123 	return EFI_ST_SUCCESS;
124 }
125 
126 EFI_UNIT_TEST(textoutput) = {
127 	.name = "text output",
128 	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
129 	.execute = execute,
130 };
131