blob: 9c52e71adddb2ba474ad1c49134e96dce31bebcd [file] [log] [blame]
/*
* 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.h>
#include <stdio.h>
#include <video_console.h>
#include "base/algorithm.h"
#include "drivers/console/console.h"
static VideoConsole *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(console);
cursory--;
}
if (console->set_cursor)
console->set_cursor(console, cursorx, cursory);
}
void video_console_clear(void)
{
if (console)
console->clear(console);
cursorx = 0;
cursory = 0;
if (console && console->set_cursor)
console->set_cursor(console, cursorx, cursory);
}
void video_console_putc(uint32_t row, uint32_t col, uint16_t ch)
{
if (console)
console->putc(console, row, col, ch);
}
void video_console_putchar(uint16_t 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(console, cursory, cursorx++,
(ch & 0xFF00) | ' ');
break;
default:
console->putc(console, cursory, cursorx++, ch);
break;
}
video_console_fixup_cursor();
}
static void _video_console_putchar(ConsoleOutputOps *me, unsigned int ch)
{
video_console_putchar(ch);
}
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_set_cursor(uint32_t x, uint32_t y)
{
cursorx = x;
cursory = y;
video_console_fixup_cursor();
}
static Console cons = {
.output = {
.putchar = &_video_console_putchar
}
};
#if CONFIG_COREBOOT_VIDEO_CONSOLE
extern VideoConsole *coreboot_video_console;
#endif
int video_init(void)
{
VideoConsole *video_console_list[] =
{
#if CONFIG_COREBOOT_VIDEO_CONSOLE
coreboot_video_console,
#endif
};
for (int i = 0; i < ARRAY_SIZE(video_console_list); i++) {
if (video_console_list[i]->init(video_console_list[i]))
continue;
console = video_console_list[i];
if (console->get_cursor) {
uint32_t x, y;
console->get_cursor(console, &x, &y);
cursorx = x;
cursory = y;
}
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;
list_insert_after(&cons.list_node, &console_list);
return 0;
}