libpayload: Support curses for serial
Support the curses interface over serial by supporting a minimal vt100 terminal. Signed-off-by: Jordan Crouse <jordan.crouse@amd.com> Acked-by: Ronald G. Minnich <rminnich@gmail.com> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3370 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
4e48408059
commit
3b4706591c
|
@ -43,11 +43,89 @@ static int _halfdelay = 0;
|
|||
|
||||
/* ============== Serial ==================== */
|
||||
|
||||
/* FIXME: Cook the serial correctly */
|
||||
/* We treat serial like a vt100 terminal. For now we
|
||||
do the cooking in here, but we should probably eventually
|
||||
pass it to dedicated vt100 code */
|
||||
|
||||
static int getkeyseq(char *buffer, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 75; i++) {
|
||||
if (serial_havechar())
|
||||
break;
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
if (i == 75)
|
||||
return len;
|
||||
|
||||
buffer[len++] = serial_getchar();
|
||||
return getkeyseq(buffer, len);
|
||||
}
|
||||
|
||||
static struct {
|
||||
char *seq;
|
||||
int key;
|
||||
} escape_codes[] = {
|
||||
{ "[A", KEY_UP },
|
||||
{ "[B", KEY_DOWN },
|
||||
{ "[C", KEY_RIGHT },
|
||||
{ "[D", KEY_LEFT },
|
||||
{ "OP", KEY_F(1) },
|
||||
{ "OQ", KEY_F(2) },
|
||||
{ "OR", KEY_F(3) },
|
||||
{ "OS", KEY_F(4) },
|
||||
{ "[15~", KEY_F(5) },
|
||||
{ "[17~", KEY_F(6) },
|
||||
{ "[18~", KEY_F(7) },
|
||||
{ "[19~", KEY_F(8) },
|
||||
{ "[20~", KEY_F(9) },
|
||||
{ "[21~", KEY_F(10) },
|
||||
{ "[24~", KEY_F(12) },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static int handle_escape(void)
|
||||
{
|
||||
char buffer[5];
|
||||
int len = getkeyseq(buffer, 0);
|
||||
int i, t;
|
||||
|
||||
if (len == 0)
|
||||
return 27;
|
||||
|
||||
for(i = 0; escape_codes[i].seq != NULL; i++) {
|
||||
char *p = escape_codes[i].seq;
|
||||
|
||||
for(t = 0; t < len; t++) {
|
||||
if (!*p || *p != buffer[t])
|
||||
break;
|
||||
p++;
|
||||
}
|
||||
|
||||
if (t == len)
|
||||
return escape_codes[i].key;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cook_serial(unsigned char ch)
|
||||
{
|
||||
return (int) ch;
|
||||
switch(ch) {
|
||||
case 8:
|
||||
return KEY_BACKSPACE;
|
||||
|
||||
case 13:
|
||||
return KEY_ENTER;
|
||||
|
||||
case 27:
|
||||
return handle_escape();
|
||||
|
||||
default:
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================ Keyboard ================ */
|
||||
|
|
|
@ -218,6 +218,10 @@ WINDOW *initscr(void)
|
|||
// newterm(name, stdout, stdin);
|
||||
// def_prog_mode();
|
||||
|
||||
if (curses_flags & F_ENABLE_SERIAL) {
|
||||
serial_clear();
|
||||
}
|
||||
|
||||
if (curses_flags & F_ENABLE_CONSOLE) {
|
||||
/* Clear the screen and kill the cursor */
|
||||
|
||||
|
@ -586,21 +590,49 @@ int whline(WINDOW *win, chtype ch, int n)
|
|||
win->_flags |= _HASMOVED;
|
||||
return OK;
|
||||
}
|
||||
|
||||
int wnoutrefresh(WINDOW *win)
|
||||
{
|
||||
// FIXME.
|
||||
int serial_is_bold = 0;
|
||||
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y <= win->_maxy; y++) {
|
||||
for (x = 0; x <= win->_maxx; x++) {
|
||||
if (curses_flags & F_ENABLE_SERIAL)
|
||||
serial_putchar(win->_line[y].text[x].chars[0]);
|
||||
serial_end_bold();
|
||||
|
||||
if (curses_flags & F_ENABLE_CONSOLE) {
|
||||
for (y = 0; y <= win->_maxy; y++) {
|
||||
|
||||
/* Position the serial cursor */
|
||||
|
||||
if (curses_flags & F_ENABLE_SERIAL)
|
||||
serial_set_cursor(win->_begy + y, win->_begx);
|
||||
|
||||
for (x = 0; x <= win->_maxx; x++) {
|
||||
attr_t attr = win->_line[y].text[x].attr;
|
||||
|
||||
unsigned int c =
|
||||
((int)color_pairs[PAIR_NUMBER(attr)]) << 8;
|
||||
|
||||
if (curses_flags & F_ENABLE_SERIAL) {
|
||||
|
||||
if (attr & A_BOLD) {
|
||||
if (!serial_is_bold) {
|
||||
serial_start_bold();
|
||||
serial_is_bold = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (serial_is_bold) {
|
||||
serial_end_bold();
|
||||
serial_is_bold = 0;
|
||||
}
|
||||
}
|
||||
|
||||
serial_putchar(win->_line[y].text[x].chars[0]);
|
||||
}
|
||||
|
||||
if (curses_flags & F_ENABLE_CONSOLE) {
|
||||
|
||||
/* Handle some of the attributes. */
|
||||
if (attr & A_BOLD)
|
||||
c |= 0x0800;
|
||||
|
|
|
@ -35,6 +35,25 @@
|
|||
#define DIVISOR (115200 / CONFIG_SERIAL_BAUD_RATE)
|
||||
#endif
|
||||
|
||||
/* This is a hack - we convert the drawing characters to ASCII */
|
||||
|
||||
static unsigned char translate_special_chars(unsigned char c)
|
||||
{
|
||||
switch(c) {
|
||||
case 196:
|
||||
return '-';
|
||||
case 179:
|
||||
return '|';
|
||||
case 218:
|
||||
case 191:
|
||||
case 192:
|
||||
case 217:
|
||||
return '+';
|
||||
default:
|
||||
return ' ';
|
||||
}
|
||||
}
|
||||
|
||||
void serial_init(void)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_SET_SPEED
|
||||
|
@ -61,6 +80,9 @@ void serial_init(void)
|
|||
|
||||
void serial_putchar(unsigned char c)
|
||||
{
|
||||
if (c > 127)
|
||||
c = translate_special_chars(c);
|
||||
|
||||
while ((inb(IOBASE + 0x05) & 0x20) == 0) ;
|
||||
outb(c, IOBASE);
|
||||
}
|
||||
|
@ -75,3 +97,38 @@ int serial_getchar(void)
|
|||
while (!serial_havechar()) ;
|
||||
return (int)inb(IOBASE);
|
||||
}
|
||||
|
||||
/* These are thinly veiled vt100 functions used by curses */
|
||||
|
||||
#define VT100_CLEAR "\e[H\e[J"
|
||||
#define VT100_SBOLD "\e[7m"
|
||||
#define VT100_EBOLD "\e[m"
|
||||
#define VT100_CURSOR_ADDR "\e[%d;%dH"
|
||||
|
||||
static void serial_putcmd(char *str)
|
||||
{
|
||||
while(*str)
|
||||
serial_putchar(*(str++));
|
||||
}
|
||||
|
||||
void serial_clear(void)
|
||||
{
|
||||
serial_putcmd(VT100_CLEAR);
|
||||
}
|
||||
|
||||
void serial_start_bold(void)
|
||||
{
|
||||
serial_putcmd(VT100_SBOLD);
|
||||
}
|
||||
|
||||
void serial_end_bold(void)
|
||||
{
|
||||
serial_putcmd(VT100_EBOLD);
|
||||
}
|
||||
|
||||
void serial_set_cursor(int y, int x)
|
||||
{
|
||||
char buffer[32];
|
||||
snprintf(buffer, sizeof(buffer), VT100_CURSOR_ADDR, y, x);
|
||||
serial_putcmd(buffer);
|
||||
}
|
||||
|
|
|
@ -107,6 +107,11 @@ void serial_putchar(unsigned char c);
|
|||
int serial_havechar(void);
|
||||
int serial_getchar(void);
|
||||
|
||||
void serial_clear(void);
|
||||
void serial_start_bold(void);
|
||||
void serial_end_bold(void);
|
||||
void serial_set_cursor(int y, int x);
|
||||
|
||||
/* drivers/speaker.c */
|
||||
void speaker_enable(u16 freq);
|
||||
void speaker_disable(void);
|
||||
|
|
Loading…
Reference in New Issue