This change allows video_printf to left/center/right-align text depending on the enum value provided by the caller. This is useful especially because usually the length of formatted string is unknown before calling video_printf. BUG=none BRANCH=smaug TEST=drew fastboot screens on Smaug CQ-DEPEND=CL:296460 Reviewed-on: https://chromium-review.googlesource.com/292929 Reviewed-by: Aaron Durbin <adurbin@chromium.org> (cherry picked from commit 436f05f60c1b88626740a35913e3ad37b5c777a3) Change-Id: If1d50b7d8ddaa86eddc1618946756184cb87bfe1 Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/295413 Reviewed-on: http://review.coreboot.org/11583 Tested-by: build bot (Jenkins)
		
			
				
	
	
		
			269 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			269 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * This file is part of the libpayload project.
 | |
|  *
 | |
|  * Copyright (C) 2008 Advanced Micro Devices, Inc.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions
 | |
|  * are met:
 | |
|  * 1. Redistributions of source code must retain the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer.
 | |
|  * 2. Redistributions in binary form must reproduce the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer in the
 | |
|  *    documentation and/or other materials provided with the distribution.
 | |
|  * 3. The name of the author may not be used to endorse or promote products
 | |
|  *    derived from this software without specific prior written permission.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 | |
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | |
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | |
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 | |
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | |
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | |
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | |
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | |
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | |
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | |
|  * SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| #include <libpayload-config.h>
 | |
| #include <libpayload.h>
 | |
| #include <video_console.h>
 | |
| 
 | |
| #if IS_ENABLED(CONFIG_LP_GEODELX_VIDEO_CONSOLE)
 | |
| extern struct video_console geodelx_video_console;
 | |
| #endif
 | |
| 
 | |
| #if IS_ENABLED(CONFIG_LP_COREBOOT_VIDEO_CONSOLE)
 | |
| extern struct video_console coreboot_video_console;
 | |
| #endif
 | |
| 
 | |
| #if IS_ENABLED(CONFIG_LP_VGA_VIDEO_CONSOLE)
 | |
| extern struct video_console vga_video_console;
 | |
| #endif
 | |
| 
 | |
| static struct video_console *console_list[] =
 | |
| {
 | |
| #if IS_ENABLED(CONFIG_LP_GEODELX_VIDEO_CONSOLE)
 | |
| 	&geodelx_video_console,
 | |
| #endif
 | |
| #if IS_ENABLED(CONFIG_LP_COREBOOT_VIDEO_CONSOLE)
 | |
| 	&coreboot_video_console,
 | |
| #endif
 | |
| #if IS_ENABLED(CONFIG_LP_VGA_VIDEO_CONSOLE)
 | |
| 	&vga_video_console,
 | |
| #endif
 | |
| };
 | |
| 
 | |
| static struct video_console *console;
 | |
| 
 | |
| static int cursorx;
 | |
| static int cursory;
 | |
| 
 | |
| void video_get_rows_cols(unsigned int *rows, unsigned int *cols)
 | |
| {
 | |
| 	if (console) {
 | |
| 		*cols = console->columns;
 | |
| 		*rows = console->rows;
 | |
| 	} else {
 | |
| 		*cols = *rows = 0;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void video_console_fixup_cursor(void)
 | |
| {
 | |
| 	if (!console)
 | |
| 		return;
 | |
| 
 | |
| 	if (cursorx < 0)
 | |
| 		cursorx = 0;
 | |
| 
 | |
| 	if (cursory < 0)
 | |
| 		cursory = 0;
 | |
| 
 | |
| 	if (cursorx >= console->columns) {
 | |
| 		cursorx = 0;
 | |
| 		cursory++;
 | |
| 	}
 | |
| 
 | |
| 	while(cursory >= console->rows) {
 | |
| 		console->scroll_up();
 | |
| 		cursory--;
 | |
| 	}
 | |
| 
 | |
| 	if (console->set_cursor)
 | |
| 		console->set_cursor(cursorx, cursory);
 | |
| }
 | |
| 
 | |
| void video_console_cursor_enable(int state)
 | |
| {
 | |
| 	if (console && console->enable_cursor)
 | |
| 		console->enable_cursor(state);
 | |
| }
 | |
| 
 | |
| void video_console_clear(void)
 | |
| {
 | |
| 	if (console)
 | |
| 		console->clear();
 | |
| 
 | |
| 	cursorx = 0;
 | |
| 	cursory = 0;
 | |
| 
 | |
| 	if (console && console->set_cursor)
 | |
| 		console->set_cursor(cursorx, cursory);
 | |
| }
 | |
| 
 | |
| void video_console_putc(u8 row, u8 col, unsigned int ch)
 | |
| {
 | |
| 	if (console)
 | |
| 		console->putc(row, col, ch);
 | |
| }
 | |
| 
 | |
| void video_console_putchar(unsigned int ch)
 | |
| {
 | |
| 	if (!console)
 | |
| 		return;
 | |
| 
 | |
| 	/* replace black-on-black with light-gray-on-black.
 | |
| 	 * do it here, instead of in libc/console.c
 | |
| 	 */
 | |
| 	if ((ch & 0xFF00) == 0) {
 | |
| 		ch |= 0x0700;
 | |
| 	}
 | |
| 
 | |
| 	switch(ch & 0xFF) {
 | |
| 	case '\r':
 | |
| 		cursorx = 0;
 | |
| 		break;
 | |
| 
 | |
| 	case '\n':
 | |
| 		cursorx = 0;
 | |
| 		cursory++;
 | |
| 		break;
 | |
| 
 | |
| 	case '\b':
 | |
| 		cursorx--;
 | |
| 		if (cursorx < 0) {
 | |
| 			cursory--;
 | |
| 			cursorx = console->columns;
 | |
| 		}
 | |
| 		break;
 | |
| 
 | |
| 	case '\t':
 | |
| 		while(cursorx % 8 && cursorx < console->columns)
 | |
| 			console->putc(cursory, cursorx++, (ch & 0xFF00) | ' ');
 | |
| 		break;
 | |
| 	default:
 | |
| 		console->putc(cursory, cursorx++, ch);
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	video_console_fixup_cursor();
 | |
| }
 | |
| 
 | |
| void video_printf(int foreground, int background, enum video_printf_align align,
 | |
| 		  const char *fmt, ...)
 | |
| {
 | |
| 	int i = 0, len;
 | |
| 	char str[200];
 | |
| 
 | |
| 	va_list ap;
 | |
| 	va_start(ap, fmt);
 | |
| 	len = vsnprintf(str, ARRAY_SIZE(str), fmt, ap);
 | |
| 	va_end(ap);
 | |
| 	if (len <= 0)
 | |
| 		return;
 | |
| 
 | |
| 	/* vsnprintf can return len larger than size. when it happens,
 | |
| 	 * only size-1 characters have been actually written. */
 | |
| 	if (len >= ARRAY_SIZE(str))
 | |
| 		len = ARRAY_SIZE(str) - 1;
 | |
| 
 | |
| 	if (len > console->columns) {
 | |
| 		cursorx = 0;
 | |
| 	} else {
 | |
| 		switch (align) {
 | |
| 		case VIDEO_PRINTF_ALIGN_LEFT:
 | |
| 			cursorx = 0;
 | |
| 			break;
 | |
| 		case VIDEO_PRINTF_ALIGN_CENTER:
 | |
| 			cursorx = (console->columns - len) / 2;
 | |
| 			break;
 | |
| 		case VIDEO_PRINTF_ALIGN_RIGHT:
 | |
| 			cursorx = console->columns - len;
 | |
| 			break;
 | |
| 		default:
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	foreground &= 0xf;
 | |
| 	foreground <<= 8;
 | |
| 	background &= 0xf;
 | |
| 	background <<= 12;
 | |
| 
 | |
| 	while (str[i])
 | |
| 		video_console_putchar(str[i++] | foreground | background);
 | |
| }
 | |
| 
 | |
| void video_console_get_cursor(unsigned int *x, unsigned int *y, unsigned int *en)
 | |
| {
 | |
| 	*x=0;
 | |
| 	*y=0;
 | |
| 	*en=0;
 | |
| 
 | |
| 	if (console && console->get_cursor)
 | |
| 		console->get_cursor(x, y, en);
 | |
| 
 | |
| 	*x = cursorx;
 | |
| 	*y = cursory;
 | |
| }
 | |
| 
 | |
| void video_console_set_cursor(unsigned int x, unsigned int y)
 | |
| {
 | |
| 	cursorx = x;
 | |
| 	cursory = y;
 | |
| 	video_console_fixup_cursor();
 | |
| }
 | |
| 
 | |
| static struct console_output_driver cons = {
 | |
| 	.putchar = video_console_putchar
 | |
| };
 | |
| 
 | |
| int video_init(void)
 | |
| {
 | |
| 	int i;
 | |
| 	unsigned int dummy_cursor_enabled;
 | |
| 
 | |
| 	for (i = 0; i < ARRAY_SIZE(console_list); i++) {
 | |
| 		if (console_list[i]->init())
 | |
| 			continue;
 | |
| 
 | |
| 		console = console_list[i];
 | |
| 
 | |
| 		if (console->get_cursor)
 | |
| 			console->get_cursor((unsigned int*)&cursorx,
 | |
| 					    (unsigned int*)&cursory,
 | |
| 					    &dummy_cursor_enabled);
 | |
| 
 | |
| 		if (cursorx) {
 | |
| 			cursorx = 0;
 | |
| 			cursory++;
 | |
| 		}
 | |
| 
 | |
| 		video_console_fixup_cursor();
 | |
| 		return 0;
 | |
| 	}
 | |
| 	return 1;
 | |
| }
 | |
| 
 | |
| int video_console_init(void)
 | |
| {
 | |
| 	int ret = video_init();
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 	console_add_output_driver(&cons);
 | |
| 	return 0;
 | |
| }
 |