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 ==================== */
|
/* ============== 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)
|
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 ================ */
|
/* ================ Keyboard ================ */
|
||||||
|
|
|
@ -218,6 +218,10 @@ WINDOW *initscr(void)
|
||||||
// newterm(name, stdout, stdin);
|
// newterm(name, stdout, stdin);
|
||||||
// def_prog_mode();
|
// def_prog_mode();
|
||||||
|
|
||||||
|
if (curses_flags & F_ENABLE_SERIAL) {
|
||||||
|
serial_clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (curses_flags & F_ENABLE_CONSOLE) {
|
if (curses_flags & F_ENABLE_CONSOLE) {
|
||||||
/* Clear the screen and kill the cursor */
|
/* Clear the screen and kill the cursor */
|
||||||
|
|
||||||
|
@ -586,20 +590,48 @@ int whline(WINDOW *win, chtype ch, int n)
|
||||||
win->_flags |= _HASMOVED;
|
win->_flags |= _HASMOVED;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wnoutrefresh(WINDOW *win)
|
int wnoutrefresh(WINDOW *win)
|
||||||
{
|
{
|
||||||
// FIXME.
|
// FIXME.
|
||||||
|
int serial_is_bold = 0;
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
|
serial_end_bold();
|
||||||
|
|
||||||
for (y = 0; y <= win->_maxy; y++) {
|
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++) {
|
for (x = 0; x <= win->_maxx; x++) {
|
||||||
if (curses_flags & F_ENABLE_SERIAL)
|
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]);
|
serial_putchar(win->_line[y].text[x].chars[0]);
|
||||||
|
}
|
||||||
|
|
||||||
if (curses_flags & F_ENABLE_CONSOLE) {
|
if (curses_flags & F_ENABLE_CONSOLE) {
|
||||||
attr_t attr = win->_line[y].text[x].attr;
|
|
||||||
unsigned int c =
|
|
||||||
((int)color_pairs[PAIR_NUMBER(attr)]) << 8;
|
|
||||||
|
|
||||||
/* Handle some of the attributes. */
|
/* Handle some of the attributes. */
|
||||||
if (attr & A_BOLD)
|
if (attr & A_BOLD)
|
||||||
|
|
|
@ -35,6 +35,25 @@
|
||||||
#define DIVISOR (115200 / CONFIG_SERIAL_BAUD_RATE)
|
#define DIVISOR (115200 / CONFIG_SERIAL_BAUD_RATE)
|
||||||
#endif
|
#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)
|
void serial_init(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SERIAL_SET_SPEED
|
#ifdef CONFIG_SERIAL_SET_SPEED
|
||||||
|
@ -61,6 +80,9 @@ void serial_init(void)
|
||||||
|
|
||||||
void serial_putchar(unsigned char c)
|
void serial_putchar(unsigned char c)
|
||||||
{
|
{
|
||||||
|
if (c > 127)
|
||||||
|
c = translate_special_chars(c);
|
||||||
|
|
||||||
while ((inb(IOBASE + 0x05) & 0x20) == 0) ;
|
while ((inb(IOBASE + 0x05) & 0x20) == 0) ;
|
||||||
outb(c, IOBASE);
|
outb(c, IOBASE);
|
||||||
}
|
}
|
||||||
|
@ -75,3 +97,38 @@ int serial_getchar(void)
|
||||||
while (!serial_havechar()) ;
|
while (!serial_havechar()) ;
|
||||||
return (int)inb(IOBASE);
|
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_havechar(void);
|
||||||
int serial_getchar(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 */
|
/* drivers/speaker.c */
|
||||||
void speaker_enable(u16 freq);
|
void speaker_enable(u16 freq);
|
||||||
void speaker_disable(void);
|
void speaker_disable(void);
|
||||||
|
|
Loading…
Reference in New Issue