xref: /aosp_15_r20/external/coreboot/payloads/libpayload/drivers/video/video.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /*
2  *
3  * Copyright (C) 2008 Advanced Micro Devices, Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <libpayload-config.h>
30 #include <libpayload.h>
31 #include <video_console.h>
32 
33 #if CONFIG(LP_GEODELX_VIDEO_CONSOLE)
34 extern struct video_console geodelx_video_console;
35 #endif
36 
37 #if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
38 extern struct video_console coreboot_video_console;
39 #endif
40 
41 #if CONFIG(LP_VGA_VIDEO_CONSOLE)
42 extern struct video_console vga_video_console;
43 #endif
44 
45 static struct video_console *console_list[] =
46 {
47 #if CONFIG(LP_GEODELX_VIDEO_CONSOLE)
48 	&geodelx_video_console,
49 #endif
50 #if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
51 	&coreboot_video_console,
52 #endif
53 #if CONFIG(LP_VGA_VIDEO_CONSOLE)
54 	&vga_video_console,
55 #endif
56 };
57 
58 static struct video_console *console;
59 
60 static int cursorx;
61 static int cursory;
62 
video_get_rows_cols(unsigned int * rows,unsigned int * cols)63 void video_get_rows_cols(unsigned int *rows, unsigned int *cols)
64 {
65 	if (console) {
66 		*cols = console->columns;
67 		*rows = console->rows;
68 	} else {
69 		*cols = *rows = 0;
70 	}
71 }
72 
video_console_fixup_cursor(void)73 static void video_console_fixup_cursor(void)
74 {
75 	if (!console)
76 		return;
77 
78 	if (cursorx < 0)
79 		cursorx = 0;
80 
81 	if (cursory < 0)
82 		cursory = 0;
83 
84 	if (cursorx >= console->columns) {
85 		cursorx = 0;
86 		cursory++;
87 	}
88 
89 	if (console->rows <= 0)
90 		return;
91 
92 	while(cursory >= console->rows) {
93 		console->scroll_up();
94 		cursory--;
95 	}
96 
97 	if (console->set_cursor)
98 		console->set_cursor(cursorx, cursory);
99 }
100 
video_console_cursor_enable(int state)101 void video_console_cursor_enable(int state)
102 {
103 	if (console && console->enable_cursor)
104 		console->enable_cursor(state);
105 }
106 
video_console_clear(void)107 void video_console_clear(void)
108 {
109 	if (console)
110 		console->clear();
111 
112 	cursorx = 0;
113 	cursory = 0;
114 
115 	if (console && console->set_cursor)
116 		console->set_cursor(cursorx, cursory);
117 }
118 
video_console_putc(u8 row,u8 col,unsigned int ch)119 void video_console_putc(u8 row, u8 col, unsigned int ch)
120 {
121 	if (console)
122 		console->putc(row, col, ch);
123 }
124 
video_console_move_cursor(int x,int y)125 void video_console_move_cursor(int x, int y)
126 {
127 	cursorx += x;
128 	cursory += y;
129 	video_console_fixup_cursor();
130 }
131 
video_console_putchar(unsigned int ch)132 void video_console_putchar(unsigned int ch)
133 {
134 	if (!console)
135 		return;
136 
137 	/* replace black-on-black with light-gray-on-black.
138 	 * do it here, instead of in libc/console.c
139 	 */
140 	if ((ch & 0xFF00) == 0) {
141 		ch |= 0x0700;
142 	}
143 
144 	switch(ch & 0xFF) {
145 	case '\r':
146 		cursorx = 0;
147 		break;
148 
149 	case '\n':
150 		cursorx = 0;
151 		cursory++;
152 		break;
153 
154 	case '\b':
155 		cursorx--;
156 		if (cursorx < 0) {
157 			cursory--;
158 			cursorx = console->columns;
159 		}
160 		break;
161 
162 	case '\t':
163 		while(cursorx % 8 && cursorx < console->columns)
164 			console->putc(cursory, cursorx++, (ch & 0xFF00) | ' ');
165 		break;
166 	default:
167 		console->putc(cursory, cursorx++, ch);
168 		break;
169 	}
170 
171 	video_console_fixup_cursor();
172 }
173 
video_printf(int foreground,int background,enum video_printf_align align,const char * fmt,...)174 void video_printf(int foreground, int background, enum video_printf_align align,
175 		  const char *fmt, ...)
176 {
177 	int i = 0, len;
178 	char str[200];
179 
180 	va_list ap;
181 	va_start(ap, fmt);
182 	len = vsnprintf(str, ARRAY_SIZE(str), fmt, ap);
183 	va_end(ap);
184 	if (len <= 0)
185 		return;
186 
187 	/* vsnprintf can return len larger than size. when it happens,
188 	 * only size-1 characters have been actually written. */
189 	if (len >= ARRAY_SIZE(str))
190 		len = ARRAY_SIZE(str) - 1;
191 
192 	if (len > console->columns) {
193 		cursorx = 0;
194 	} else {
195 		switch (align) {
196 		case VIDEO_PRINTF_ALIGN_LEFT:
197 			cursorx = 0;
198 			break;
199 		case VIDEO_PRINTF_ALIGN_CENTER:
200 			cursorx = (console->columns - len) / 2;
201 			break;
202 		case VIDEO_PRINTF_ALIGN_RIGHT:
203 			cursorx = console->columns - len;
204 			break;
205 		default:
206 			break;
207 		}
208 	}
209 
210 	foreground &= 0xf;
211 	foreground <<= 8;
212 	background &= 0xf;
213 	background <<= 12;
214 
215 	while (str[i])
216 		video_console_putchar(str[i++] | foreground | background);
217 }
218 
video_console_get_cursor(unsigned int * x,unsigned int * y,unsigned int * en)219 void video_console_get_cursor(unsigned int *x, unsigned int *y, unsigned int *en)
220 {
221 	*x=0;
222 	*y=0;
223 	*en=0;
224 
225 	if (console && console->get_cursor)
226 		console->get_cursor(x, y, en);
227 
228 	*x = cursorx;
229 	*y = cursory;
230 }
231 
video_console_set_cursor(unsigned int x,unsigned int y)232 void video_console_set_cursor(unsigned int x, unsigned int y)
233 {
234 	cursorx = x;
235 	cursory = y;
236 	video_console_fixup_cursor();
237 }
238 
239 static struct console_output_driver cons = {
240 	.putchar = video_console_putchar
241 };
242 
video_init(void)243 int video_init(void)
244 {
245 	int i;
246 	unsigned int dummy_cursor_enabled;
247 
248 	for (i = 0; i < ARRAY_SIZE(console_list); i++) {
249 		if (console_list[i]->init())
250 			continue;
251 
252 		console = console_list[i];
253 
254 		if (console->get_cursor)
255 			console->get_cursor((unsigned int*)&cursorx,
256 					    (unsigned int*)&cursory,
257 					    &dummy_cursor_enabled);
258 
259 		if (cursorx) {
260 			cursorx = 0;
261 			cursory++;
262 		}
263 
264 		video_console_fixup_cursor();
265 		return 0;
266 	}
267 	return 1;
268 }
269 
video_console_init(void)270 int video_console_init(void)
271 {
272 	int ret = video_init();
273 	if (ret)
274 		return ret;
275 	console_add_output_driver(&cons);
276 	return 0;
277 }
278