278 lines
5.7 KiB
C
278 lines
5.7 KiB
C
/*
|
|
*
|
|
* 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 CONFIG(LP_GEODELX_VIDEO_CONSOLE)
|
|
extern struct video_console geodelx_video_console;
|
|
#endif
|
|
|
|
#if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
|
|
extern struct video_console coreboot_video_console;
|
|
#endif
|
|
|
|
#if CONFIG(LP_VGA_VIDEO_CONSOLE)
|
|
extern struct video_console vga_video_console;
|
|
#endif
|
|
|
|
static struct video_console *console_list[] =
|
|
{
|
|
#if CONFIG(LP_GEODELX_VIDEO_CONSOLE)
|
|
&geodelx_video_console,
|
|
#endif
|
|
#if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
|
|
&coreboot_video_console,
|
|
#endif
|
|
#if 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++;
|
|
}
|
|
|
|
if (console->rows <= 0)
|
|
return;
|
|
|
|
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_move_cursor(int x, int y)
|
|
{
|
|
cursorx += x;
|
|
cursory += y;
|
|
video_console_fixup_cursor();
|
|
}
|
|
|
|
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;
|
|
}
|