loader: use teken teminal emulator for x86 and uefi
Replace mini cons25 emulator with teken, this does enable us proper console terminal for loader and will make it possible to implement different back end callbacks to draw to screen. At this time we still only "draw" in text mode.
This commit is contained in:
parent
a6935d085c
commit
56758831fe
@ -180,6 +180,13 @@ CFLAGS+=-I.
|
||||
|
||||
all: ${PROG}
|
||||
|
||||
CLEANFILES+= teken_state.h
|
||||
teken.c: teken_state.h
|
||||
|
||||
teken_state.h: ${SYSDIR}/teken/sequences
|
||||
awk -f ${SYSDIR}/teken/gensequences \
|
||||
${SYSDIR}/teken/sequences > teken_state.h
|
||||
|
||||
.if !defined(NO_OBJ)
|
||||
_ILINKS=machine
|
||||
.if ${MACHINE} != ${MACHINE_CPUARCH} && ${MACHINE} != "arm64"
|
||||
|
@ -106,6 +106,7 @@ EFI_STATUS errno_to_efi_status(int errno);
|
||||
void efi_time_init(void);
|
||||
void efi_time_fini(void);
|
||||
|
||||
bool efi_cons_update_mode(void);
|
||||
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
|
||||
|
||||
EFI_STATUS main(int argc, CHAR16 *argv[]);
|
||||
|
@ -22,6 +22,9 @@ SRCS= delay.c \
|
||||
libefi.c \
|
||||
wchar.c
|
||||
|
||||
.PATH: ${SYSDIR}/teken
|
||||
SRCS+= teken.c
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
|
||||
SRCS+= time.c
|
||||
.elif ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
|
||||
@ -45,6 +48,8 @@ CFLAGS+= -fPIC -mno-red-zone
|
||||
.endif
|
||||
CFLAGS+= -I${EFIINC}
|
||||
CFLAGS+= -I${EFIINCMD}
|
||||
CFLAGS.efi_console.c+= -I${SRCTOP}/sys/teken
|
||||
CFLAGS.teken.c+= -I${SRCTOP}/sys/teken
|
||||
.if ${MK_LOADER_ZFS} != "no"
|
||||
CFLAGS+= -I${ZFSSRC}
|
||||
CFLAGS+= -DEFI_ZFS_BOOT
|
||||
@ -56,9 +61,4 @@ CFLAGS+= -I${LDRSRC}
|
||||
# Handle FreeBSD specific %b and %D printf format specifiers
|
||||
CFLAGS+= ${FORMAT_EXTENSIONS}
|
||||
|
||||
# Do not use TERM_EMU on arm and arm64 as it doesn't behave well with serial console
|
||||
.if ${MACHINE_CPUARCH} != "arm" && ${MACHINE_CPUARCH} != "aarch64"
|
||||
CFLAGS+= -DTERM_EMU
|
||||
.endif
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
#include <teken.h>
|
||||
|
||||
#include "bootstrap.h"
|
||||
|
||||
@ -37,26 +38,57 @@ static SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
|
||||
static SIMPLE_INPUT_INTERFACE *conin;
|
||||
static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *coninex;
|
||||
|
||||
#ifdef TERM_EMU
|
||||
#define DEFAULT_FGCOLOR EFI_LIGHTGRAY
|
||||
#define DEFAULT_BGCOLOR EFI_BLACK
|
||||
static tf_bell_t efi_cons_bell;
|
||||
static tf_cursor_t efi_text_cursor;
|
||||
static tf_putchar_t efi_text_putchar;
|
||||
static tf_fill_t efi_text_fill;
|
||||
static tf_copy_t efi_text_copy;
|
||||
static tf_param_t efi_text_param;
|
||||
static tf_respond_t efi_cons_respond;
|
||||
|
||||
#define MAXARGS 8
|
||||
static int args[MAXARGS], argc;
|
||||
static int fg_c, bg_c, curx, cury;
|
||||
static int esc;
|
||||
static teken_funcs_t tf = {
|
||||
.tf_bell = efi_cons_bell,
|
||||
.tf_cursor = efi_text_cursor,
|
||||
.tf_putchar = efi_text_putchar,
|
||||
.tf_fill = efi_text_fill,
|
||||
.tf_copy = efi_text_copy,
|
||||
.tf_param = efi_text_param,
|
||||
.tf_respond = efi_cons_respond,
|
||||
};
|
||||
|
||||
void get_pos(int *x, int *y);
|
||||
void curs_move(int *_x, int *_y, int x, int y);
|
||||
static void CL(int);
|
||||
void HO(void);
|
||||
void end_term(void);
|
||||
#endif
|
||||
teken_t teken;
|
||||
teken_pos_t tp;
|
||||
|
||||
struct text_pixel {
|
||||
teken_char_t c;
|
||||
teken_attr_t a;
|
||||
};
|
||||
|
||||
static struct text_pixel *buffer;
|
||||
|
||||
#define KEYBUFSZ 10
|
||||
static unsigned keybuf[KEYBUFSZ]; /* keybuf for extended codes */
|
||||
static int key_pending;
|
||||
|
||||
static const unsigned char teken_color_to_efi_color[16] = {
|
||||
EFI_BLACK,
|
||||
EFI_RED,
|
||||
EFI_GREEN,
|
||||
EFI_BROWN,
|
||||
EFI_BLUE,
|
||||
EFI_MAGENTA,
|
||||
EFI_CYAN,
|
||||
EFI_LIGHTGRAY,
|
||||
EFI_DARKGRAY,
|
||||
EFI_LIGHTRED,
|
||||
EFI_LIGHTGREEN,
|
||||
EFI_YELLOW,
|
||||
EFI_LIGHTBLUE,
|
||||
EFI_LIGHTMAGENTA,
|
||||
EFI_LIGHTCYAN,
|
||||
EFI_WHITE
|
||||
};
|
||||
|
||||
static void efi_cons_probe(struct console *);
|
||||
static int efi_cons_init(int);
|
||||
void efi_cons_putchar(int);
|
||||
@ -75,378 +107,319 @@ struct console efi_console = {
|
||||
efi_cons_poll
|
||||
};
|
||||
|
||||
#ifdef TERM_EMU
|
||||
|
||||
/* Get cursor position. */
|
||||
void
|
||||
get_pos(int *x, int *y)
|
||||
/*
|
||||
* Not implemented.
|
||||
*/
|
||||
static void
|
||||
efi_cons_bell(void *s __unused)
|
||||
{
|
||||
*x = conout->Mode->CursorColumn;
|
||||
*y = conout->Mode->CursorRow;
|
||||
}
|
||||
|
||||
/* Move cursor to x rows and y cols (0-based). */
|
||||
void
|
||||
curs_move(int *_x, int *_y, int x, int y)
|
||||
static void
|
||||
efi_text_cursor(void *s __unused, const teken_pos_t *p)
|
||||
{
|
||||
conout->SetCursorPosition(conout, x, y);
|
||||
if (_x != NULL)
|
||||
*_x = conout->Mode->CursorColumn;
|
||||
if (_y != NULL)
|
||||
*_y = conout->Mode->CursorRow;
|
||||
UINTN row, col;
|
||||
|
||||
(void) conout->QueryMode(conout, conout->Mode->Mode, &col, &row);
|
||||
|
||||
if (p->tp_col == col)
|
||||
col = p->tp_col - 1;
|
||||
else
|
||||
col = p->tp_col;
|
||||
|
||||
if (p->tp_row == row)
|
||||
row = p->tp_row - 1;
|
||||
else
|
||||
row = p->tp_row;
|
||||
|
||||
conout->SetCursorPosition(conout, col, row);
|
||||
}
|
||||
|
||||
/* Clear internal state of the terminal emulation code. */
|
||||
void
|
||||
end_term(void)
|
||||
static void
|
||||
efi_text_printchar(const teken_pos_t *p)
|
||||
{
|
||||
esc = 0;
|
||||
argc = -1;
|
||||
UINTN a, attr;
|
||||
struct text_pixel *px;
|
||||
teken_color_t fg, bg, tmp;
|
||||
|
||||
px = buffer + p->tp_col + p->tp_row * tp.tp_col;
|
||||
a = conout->Mode->Attribute;
|
||||
|
||||
fg = teken_256to16(px->a.ta_fgcolor);
|
||||
bg = teken_256to16(px->a.ta_bgcolor);
|
||||
if (px->a.ta_format & TF_BOLD)
|
||||
fg |= TC_LIGHT;
|
||||
if (px->a.ta_format & TF_BLINK)
|
||||
bg |= TC_LIGHT;
|
||||
|
||||
if (px->a.ta_format & TF_REVERSE) {
|
||||
tmp = fg;
|
||||
fg = bg;
|
||||
bg = tmp;
|
||||
}
|
||||
|
||||
attr = EFI_TEXT_ATTR(teken_color_to_efi_color[fg],
|
||||
teken_color_to_efi_color[bg]);
|
||||
|
||||
conout->SetCursorPosition(conout, p->tp_col, p->tp_row);
|
||||
|
||||
/* to prvent autoscroll, skip print of lower right char */
|
||||
if (p->tp_row == tp.tp_row - 1 &&
|
||||
p->tp_col == tp.tp_col - 1)
|
||||
return;
|
||||
|
||||
(void) conout->SetAttribute(conout, attr);
|
||||
efi_cons_efiputchar(px->c);
|
||||
(void) conout->SetAttribute(conout, a);
|
||||
}
|
||||
|
||||
#endif
|
||||
static void
|
||||
efi_text_putchar(void *s __unused, const teken_pos_t *p, teken_char_t c,
|
||||
const teken_attr_t *a)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
int idx;
|
||||
|
||||
idx = p->tp_col + p->tp_row * tp.tp_col;
|
||||
buffer[idx].c = c;
|
||||
buffer[idx].a = *a;
|
||||
efi_text_printchar(p);
|
||||
}
|
||||
|
||||
static void
|
||||
efi_text_fill(void *s, const teken_rect_t *r, teken_char_t c,
|
||||
const teken_attr_t *a)
|
||||
{
|
||||
teken_pos_t p;
|
||||
UINTN row, col;
|
||||
|
||||
(void) conout->QueryMode(conout, conout->Mode->Mode, &col, &row);
|
||||
|
||||
conout->EnableCursor(conout, FALSE);
|
||||
for (p.tp_row = r->tr_begin.tp_row; p.tp_row < r->tr_end.tp_row;
|
||||
p.tp_row++)
|
||||
for (p.tp_col = r->tr_begin.tp_col;
|
||||
p.tp_col < r->tr_end.tp_col; p.tp_col++)
|
||||
efi_text_putchar(s, &p, c, a);
|
||||
conout->EnableCursor(conout, TRUE);
|
||||
}
|
||||
|
||||
static bool
|
||||
efi_same_pixel(struct text_pixel *px1, struct text_pixel *px2)
|
||||
{
|
||||
if (px1->c != px2->c)
|
||||
return (false);
|
||||
|
||||
if (px1->a.ta_format != px2->a.ta_format)
|
||||
return (false);
|
||||
if (px1->a.ta_fgcolor != px2->a.ta_fgcolor)
|
||||
return (false);
|
||||
if (px1->a.ta_bgcolor != px2->a.ta_bgcolor)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static void
|
||||
efi_text_copy(void *ptr __unused, const teken_rect_t *r, const teken_pos_t *p)
|
||||
{
|
||||
int srow, drow;
|
||||
int nrow, ncol, x, y; /* Has to be signed - >= 0 comparison */
|
||||
teken_pos_t d, s;
|
||||
|
||||
/*
|
||||
* Copying is a little tricky. We must make sure we do it in
|
||||
* correct order, to make sure we don't overwrite our own data.
|
||||
*/
|
||||
|
||||
nrow = r->tr_end.tp_row - r->tr_begin.tp_row;
|
||||
ncol = r->tr_end.tp_col - r->tr_begin.tp_col;
|
||||
|
||||
conout->EnableCursor(conout, FALSE);
|
||||
if (p->tp_row < r->tr_begin.tp_row) {
|
||||
/* Copy from bottom to top. */
|
||||
for (y = 0; y < nrow; y++) {
|
||||
d.tp_row = p->tp_row + y;
|
||||
s.tp_row = r->tr_begin.tp_row + y;
|
||||
drow = d.tp_row * tp.tp_col;
|
||||
srow = s.tp_row * tp.tp_col;
|
||||
for (x = 0; x < ncol; x++) {
|
||||
d.tp_col = p->tp_col + x;
|
||||
s.tp_col = r->tr_begin.tp_col + x;
|
||||
|
||||
if (!efi_same_pixel(
|
||||
&buffer[d.tp_col + drow],
|
||||
&buffer[s.tp_col + srow])) {
|
||||
buffer[d.tp_col + drow] =
|
||||
buffer[s.tp_col + srow];
|
||||
efi_text_printchar(&d);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Copy from top to bottom. */
|
||||
if (p->tp_col < r->tr_begin.tp_col) {
|
||||
/* Copy from right to left. */
|
||||
for (y = nrow - 1; y >= 0; y--) {
|
||||
d.tp_row = p->tp_row + y;
|
||||
s.tp_row = r->tr_begin.tp_row + y;
|
||||
drow = d.tp_row * tp.tp_col;
|
||||
srow = s.tp_row * tp.tp_col;
|
||||
for (x = 0; x < ncol; x++) {
|
||||
d.tp_col = p->tp_col + x;
|
||||
s.tp_col = r->tr_begin.tp_col + x;
|
||||
|
||||
if (!efi_same_pixel(
|
||||
&buffer[d.tp_col + drow],
|
||||
&buffer[s.tp_col + srow])) {
|
||||
buffer[d.tp_col + drow] =
|
||||
buffer[s.tp_col + srow];
|
||||
efi_text_printchar(&d);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Copy from left to right. */
|
||||
for (y = nrow - 1; y >= 0; y--) {
|
||||
d.tp_row = p->tp_row + y;
|
||||
s.tp_row = r->tr_begin.tp_row + y;
|
||||
drow = d.tp_row * tp.tp_col;
|
||||
srow = s.tp_row * tp.tp_col;
|
||||
for (x = ncol - 1; x >= 0; x--) {
|
||||
d.tp_col = p->tp_col + x;
|
||||
s.tp_col = r->tr_begin.tp_col + x;
|
||||
|
||||
if (!efi_same_pixel(
|
||||
&buffer[d.tp_col + drow],
|
||||
&buffer[s.tp_col + srow])) {
|
||||
buffer[d.tp_col + drow] =
|
||||
buffer[s.tp_col + srow];
|
||||
efi_text_printchar(&d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
conout->EnableCursor(conout, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
efi_text_param(void *s __unused, int cmd, unsigned int value)
|
||||
{
|
||||
switch (cmd) {
|
||||
case TP_SETLOCALCURSOR:
|
||||
/*
|
||||
* 0 means normal (usually block), 1 means hidden, and
|
||||
* 2 means blinking (always block) for compatibility with
|
||||
* syscons. We don't support any changes except hiding,
|
||||
* so must map 2 to 0.
|
||||
*/
|
||||
value = (value == 1) ? 0 : 1;
|
||||
/* FALLTHROUGH */
|
||||
case TP_SHOWCURSOR:
|
||||
if (value == 1)
|
||||
conout->EnableCursor(conout, TRUE);
|
||||
else
|
||||
conout->EnableCursor(conout, FALSE);
|
||||
break;
|
||||
default:
|
||||
/* Not yet implemented */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Not implemented.
|
||||
*/
|
||||
static void
|
||||
efi_cons_respond(void *s __unused, const void *buf __unused,
|
||||
size_t len __unused)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
efi_cons_probe(struct console *cp)
|
||||
{
|
||||
conout = ST->ConOut;
|
||||
conin = ST->ConIn;
|
||||
cp->c_flags |= C_PRESENTIN | C_PRESENTOUT;
|
||||
}
|
||||
|
||||
bool
|
||||
efi_cons_update_mode(void)
|
||||
{
|
||||
UINTN cols, rows;
|
||||
const teken_attr_t *a;
|
||||
EFI_STATUS status;
|
||||
char env[8];
|
||||
|
||||
status = conout->QueryMode(conout, conout->Mode->Mode, &cols, &rows);
|
||||
if (EFI_ERROR(status)) {
|
||||
cols = 80;
|
||||
rows = 24;
|
||||
}
|
||||
|
||||
if (buffer != NULL) {
|
||||
if (tp.tp_row == rows && tp.tp_col == cols)
|
||||
return (true);
|
||||
free(buffer);
|
||||
} else {
|
||||
teken_init(&teken, &tf, NULL);
|
||||
}
|
||||
|
||||
tp.tp_row = rows;
|
||||
tp.tp_col = cols;
|
||||
buffer = malloc(rows * cols * sizeof(*buffer));
|
||||
if (buffer == NULL)
|
||||
return (false);
|
||||
|
||||
teken_set_winsize(&teken, &tp);
|
||||
a = teken_get_defattr(&teken);
|
||||
|
||||
for (int row = 0; row < rows; row++)
|
||||
for (int col = 0; col < cols; col++) {
|
||||
buffer[col + row * tp.tp_col].c = ' ';
|
||||
buffer[col + row * tp.tp_col].a = *a;
|
||||
}
|
||||
|
||||
snprintf(env, sizeof (env), "%u", (unsigned)rows);
|
||||
setenv("LINES", env, 1);
|
||||
snprintf(env, sizeof (env), "%u", (unsigned)cols);
|
||||
setenv("COLUMNS", env, 1);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static int
|
||||
efi_cons_init(int arg)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
|
||||
#ifdef TERM_EMU
|
||||
conout->SetAttribute(conout, EFI_TEXT_ATTR(DEFAULT_FGCOLOR,
|
||||
DEFAULT_BGCOLOR));
|
||||
end_term();
|
||||
get_pos(&curx, &cury);
|
||||
curs_move(&curx, &cury, curx, cury);
|
||||
fg_c = DEFAULT_FGCOLOR;
|
||||
bg_c = DEFAULT_BGCOLOR;
|
||||
#endif
|
||||
if (conin != NULL)
|
||||
return (0);
|
||||
|
||||
conout = ST->ConOut;
|
||||
conin = ST->ConIn;
|
||||
|
||||
conout->EnableCursor(conout, TRUE);
|
||||
status = BS->OpenProtocol(ST->ConsoleInHandle, &simple_input_ex_guid,
|
||||
(void **)&coninex, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (status != EFI_SUCCESS)
|
||||
coninex = NULL;
|
||||
return (0);
|
||||
|
||||
if (efi_cons_update_mode())
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
efi_cons_rawputchar(int c)
|
||||
{
|
||||
int i;
|
||||
UINTN x, y;
|
||||
conout->QueryMode(conout, conout->Mode->Mode, &x, &y);
|
||||
|
||||
if (c == '\t') {
|
||||
int n;
|
||||
|
||||
n = 8 - ((conout->Mode->CursorColumn + 8) % 8);
|
||||
for (i = 0; i < n; i++)
|
||||
efi_cons_rawputchar(' ');
|
||||
} else {
|
||||
#ifndef TERM_EMU
|
||||
if (c == '\n')
|
||||
efi_cons_efiputchar('\r');
|
||||
efi_cons_efiputchar(c);
|
||||
#else
|
||||
switch (c) {
|
||||
case '\r':
|
||||
curx = 0;
|
||||
efi_cons_efiputchar('\r');
|
||||
return;
|
||||
case '\n':
|
||||
efi_cons_efiputchar('\n');
|
||||
efi_cons_efiputchar('\r');
|
||||
cury++;
|
||||
if (cury >= y)
|
||||
cury--;
|
||||
curx = 0;
|
||||
return;
|
||||
case '\b':
|
||||
if (curx > 0) {
|
||||
efi_cons_efiputchar('\b');
|
||||
curx--;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
efi_cons_efiputchar(c);
|
||||
curx++;
|
||||
if (curx > x-1) {
|
||||
curx = 0;
|
||||
cury++;
|
||||
}
|
||||
if (cury > y-1) {
|
||||
curx = 0;
|
||||
cury--;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TERM_EMU
|
||||
/* Gracefully exit ESC-sequence processing in case of misunderstanding. */
|
||||
static void
|
||||
bail_out(int c)
|
||||
{
|
||||
char buf[16], *ch;
|
||||
int i;
|
||||
|
||||
if (esc) {
|
||||
efi_cons_rawputchar('\033');
|
||||
if (esc != '\033')
|
||||
efi_cons_rawputchar(esc);
|
||||
for (i = 0; i <= argc; ++i) {
|
||||
sprintf(buf, "%d", args[i]);
|
||||
ch = buf;
|
||||
while (*ch)
|
||||
efi_cons_rawputchar(*ch++);
|
||||
}
|
||||
}
|
||||
efi_cons_rawputchar(c);
|
||||
end_term();
|
||||
}
|
||||
|
||||
/* Clear display from current position to end of screen. */
|
||||
static void
|
||||
CD(void) {
|
||||
int i;
|
||||
UINTN x, y;
|
||||
|
||||
get_pos(&curx, &cury);
|
||||
if (curx == 0 && cury == 0) {
|
||||
conout->ClearScreen(conout);
|
||||
end_term();
|
||||
return;
|
||||
}
|
||||
|
||||
conout->QueryMode(conout, conout->Mode->Mode, &x, &y);
|
||||
CL(0); /* clear current line from cursor to end */
|
||||
for (i = cury + 1; i < y-1; i++) {
|
||||
curs_move(NULL, NULL, 0, i);
|
||||
CL(0);
|
||||
}
|
||||
curs_move(NULL, NULL, curx, cury);
|
||||
end_term();
|
||||
}
|
||||
|
||||
/*
|
||||
* Absolute cursor move to args[0] rows and args[1] columns
|
||||
* (the coordinates are 1-based).
|
||||
*/
|
||||
static void
|
||||
CM(void)
|
||||
{
|
||||
if (args[0] > 0)
|
||||
args[0]--;
|
||||
if (args[1] > 0)
|
||||
args[1]--;
|
||||
curs_move(&curx, &cury, args[1], args[0]);
|
||||
end_term();
|
||||
}
|
||||
|
||||
/* Home cursor (left top corner), also called from mode command. */
|
||||
void
|
||||
HO(void)
|
||||
{
|
||||
argc = 1;
|
||||
args[0] = args[1] = 1;
|
||||
CM();
|
||||
}
|
||||
|
||||
/* Clear line from current position to end of line */
|
||||
static void
|
||||
CL(int direction)
|
||||
{
|
||||
int i, len;
|
||||
UINTN x, y;
|
||||
CHAR16 *line;
|
||||
|
||||
conout->QueryMode(conout, conout->Mode->Mode, &x, &y);
|
||||
switch (direction) {
|
||||
case 0: /* from cursor to end */
|
||||
len = x - curx + 1;
|
||||
break;
|
||||
case 1: /* from beginning to cursor */
|
||||
len = curx;
|
||||
break;
|
||||
case 2: /* entire line */
|
||||
len = x;
|
||||
break;
|
||||
default: /* NOTREACHED */
|
||||
__unreachable();
|
||||
}
|
||||
|
||||
if (cury == y - 1)
|
||||
len--;
|
||||
|
||||
line = malloc(len * sizeof (CHAR16));
|
||||
if (line == NULL) {
|
||||
printf("out of memory\n");
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < len; i++)
|
||||
line[i] = ' ';
|
||||
line[len-1] = 0;
|
||||
|
||||
if (direction != 0)
|
||||
curs_move(NULL, NULL, 0, cury);
|
||||
|
||||
conout->OutputString(conout, line);
|
||||
/* restore cursor position */
|
||||
curs_move(NULL, NULL, curx, cury);
|
||||
free(line);
|
||||
end_term();
|
||||
}
|
||||
|
||||
static void
|
||||
get_arg(int c)
|
||||
{
|
||||
if (argc < 0)
|
||||
argc = 0;
|
||||
args[argc] *= 10;
|
||||
args[argc] += c - '0';
|
||||
}
|
||||
|
||||
/* Emulate basic capabilities of cons25 terminal */
|
||||
static void
|
||||
efi_term_emu(int c)
|
||||
{
|
||||
static int ansi_col[] = {
|
||||
0, 4, 2, 6, 1, 5, 3, 7
|
||||
};
|
||||
int t, i;
|
||||
|
||||
switch (esc) {
|
||||
case 0:
|
||||
switch (c) {
|
||||
case '\033':
|
||||
esc = c;
|
||||
break;
|
||||
default:
|
||||
efi_cons_rawputchar(c);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '\033':
|
||||
switch (c) {
|
||||
case '[':
|
||||
esc = c;
|
||||
args[0] = 0;
|
||||
argc = -1;
|
||||
break;
|
||||
default:
|
||||
bail_out(c);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '[':
|
||||
switch (c) {
|
||||
case ';':
|
||||
if (argc < 0)
|
||||
argc = 0;
|
||||
else if (argc + 1 >= MAXARGS)
|
||||
bail_out(c);
|
||||
else
|
||||
args[++argc] = 0;
|
||||
break;
|
||||
case 'H': /* ho = \E[H */
|
||||
if (argc < 0)
|
||||
HO();
|
||||
else if (argc == 1)
|
||||
CM();
|
||||
else
|
||||
bail_out(c);
|
||||
break;
|
||||
case 'J': /* cd = \E[J */
|
||||
if (argc < 0)
|
||||
CD();
|
||||
else
|
||||
bail_out(c);
|
||||
break;
|
||||
case 'm':
|
||||
if (argc < 0) {
|
||||
fg_c = DEFAULT_FGCOLOR;
|
||||
bg_c = DEFAULT_BGCOLOR;
|
||||
}
|
||||
for (i = 0; i <= argc; ++i) {
|
||||
switch (args[i]) {
|
||||
case 0: /* back to normal */
|
||||
fg_c = DEFAULT_FGCOLOR;
|
||||
bg_c = DEFAULT_BGCOLOR;
|
||||
break;
|
||||
case 1: /* bold */
|
||||
fg_c |= 0x8;
|
||||
break;
|
||||
case 4: /* underline */
|
||||
case 5: /* blink */
|
||||
bg_c |= 0x8;
|
||||
break;
|
||||
case 7: /* reverse */
|
||||
t = fg_c;
|
||||
fg_c = bg_c;
|
||||
bg_c = t;
|
||||
break;
|
||||
case 22: /* normal intensity */
|
||||
fg_c &= ~0x8;
|
||||
break;
|
||||
case 24: /* not underline */
|
||||
case 25: /* not blinking */
|
||||
bg_c &= ~0x8;
|
||||
break;
|
||||
case 30: case 31: case 32: case 33:
|
||||
case 34: case 35: case 36: case 37:
|
||||
fg_c = ansi_col[args[i] - 30];
|
||||
break;
|
||||
case 39: /* normal */
|
||||
fg_c = DEFAULT_FGCOLOR;
|
||||
break;
|
||||
case 40: case 41: case 42: case 43:
|
||||
case 44: case 45: case 46: case 47:
|
||||
bg_c = ansi_col[args[i] - 40];
|
||||
break;
|
||||
case 49: /* normal */
|
||||
bg_c = DEFAULT_BGCOLOR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
conout->SetAttribute(conout, EFI_TEXT_ATTR(fg_c, bg_c));
|
||||
end_term();
|
||||
break;
|
||||
default:
|
||||
if (isdigit(c))
|
||||
get_arg(c);
|
||||
else
|
||||
bail_out(c);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bail_out(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void
|
||||
HO(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
efi_cons_putchar(int c)
|
||||
{
|
||||
#ifdef TERM_EMU
|
||||
efi_term_emu(c);
|
||||
#else
|
||||
efi_cons_rawputchar(c);
|
||||
#endif
|
||||
unsigned char ch = c;
|
||||
|
||||
if (buffer != NULL)
|
||||
teken_input(&teken, &ch, sizeof (ch));
|
||||
else
|
||||
efi_cons_efiputchar(c);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -624,31 +597,13 @@ void
|
||||
efi_cons_efiputchar(int c)
|
||||
{
|
||||
CHAR16 buf[2];
|
||||
EFI_STATUS status;
|
||||
|
||||
/*
|
||||
* translate box chars to unicode
|
||||
*/
|
||||
switch (c) {
|
||||
/* single frame */
|
||||
case 0xb3: buf[0] = BOXDRAW_VERTICAL; break;
|
||||
case 0xbf: buf[0] = BOXDRAW_DOWN_LEFT; break;
|
||||
case 0xc0: buf[0] = BOXDRAW_UP_RIGHT; break;
|
||||
case 0xc4: buf[0] = BOXDRAW_HORIZONTAL; break;
|
||||
case 0xda: buf[0] = BOXDRAW_DOWN_RIGHT; break;
|
||||
case 0xd9: buf[0] = BOXDRAW_UP_LEFT; break;
|
||||
|
||||
/* double frame */
|
||||
case 0xba: buf[0] = BOXDRAW_DOUBLE_VERTICAL; break;
|
||||
case 0xbb: buf[0] = BOXDRAW_DOUBLE_DOWN_LEFT; break;
|
||||
case 0xbc: buf[0] = BOXDRAW_DOUBLE_UP_LEFT; break;
|
||||
case 0xc8: buf[0] = BOXDRAW_DOUBLE_UP_RIGHT; break;
|
||||
case 0xc9: buf[0] = BOXDRAW_DOUBLE_DOWN_RIGHT; break;
|
||||
case 0xcd: buf[0] = BOXDRAW_DOUBLE_HORIZONTAL; break;
|
||||
|
||||
default:
|
||||
buf[0] = c;
|
||||
}
|
||||
buf[0] = c;
|
||||
buf[1] = 0; /* terminate string */
|
||||
|
||||
status = conout->TestString(conout, buf);
|
||||
if (EFI_ERROR(status))
|
||||
buf[0] = '?';
|
||||
conout->OutputString(conout, buf);
|
||||
}
|
||||
|
@ -11,5 +11,5 @@ SRCS+= nullconsole.c \
|
||||
comconsole.c \
|
||||
spinconsole.c
|
||||
|
||||
CFLAGS+= -fPIC -DTERM_EMU
|
||||
CFLAGS+= -fPIC
|
||||
LDFLAGS+= -Wl,-znocombreloc
|
||||
|
@ -9,5 +9,5 @@ SRCS+= nullconsole.c \
|
||||
comconsole.c \
|
||||
spinconsole.c
|
||||
|
||||
CFLAGS+= -fPIC -DTERM_EMU
|
||||
CFLAGS+= -fPIC
|
||||
LDFLAGS+= -Wl,-znocombreloc
|
||||
|
@ -1280,10 +1280,8 @@ command_mode(int argc, char *argv[])
|
||||
unsigned int mode;
|
||||
int i;
|
||||
char *cp;
|
||||
char rowenv[8];
|
||||
EFI_STATUS status;
|
||||
SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
|
||||
extern void HO(void);
|
||||
|
||||
conout = ST->ConOut;
|
||||
|
||||
@ -1303,9 +1301,7 @@ command_mode(int argc, char *argv[])
|
||||
printf("couldn't set mode %d\n", mode);
|
||||
return (CMD_ERROR);
|
||||
}
|
||||
sprintf(rowenv, "%u", (unsigned)rows);
|
||||
setenv("LINES", rowenv, 1);
|
||||
HO(); /* set cursor */
|
||||
(void) efi_cons_update_mode();
|
||||
return (CMD_OK);
|
||||
}
|
||||
|
||||
|
@ -47,32 +47,32 @@ variable fill
|
||||
43 constant ascii_plus
|
||||
|
||||
\ Single frames
|
||||
196 constant sh_el
|
||||
179 constant sv_el
|
||||
218 constant slt_el
|
||||
192 constant slb_el
|
||||
191 constant srt_el
|
||||
217 constant srb_el
|
||||
0x2500 constant sh_el
|
||||
0x2502 constant sv_el
|
||||
0x250c constant slt_el
|
||||
0x2514 constant slb_el
|
||||
0x2510 constant srt_el
|
||||
0x2518 constant srb_el
|
||||
\ Double frames
|
||||
205 constant dh_el
|
||||
186 constant dv_el
|
||||
201 constant dlt_el
|
||||
200 constant dlb_el
|
||||
187 constant drt_el
|
||||
188 constant drb_el
|
||||
0x2550 constant dh_el
|
||||
0x2551 constant dv_el
|
||||
0x2554 constant dlt_el
|
||||
0x255a constant dlb_el
|
||||
0x2557 constant drt_el
|
||||
0x255d constant drb_el
|
||||
\ Fillings
|
||||
0 constant fill_none
|
||||
32 constant fill_blank
|
||||
176 constant fill_dark
|
||||
177 constant fill_med
|
||||
178 constant fill_bright
|
||||
0x2591 constant fill_dark
|
||||
0x2592 constant fill_med
|
||||
0x2593 constant fill_bright
|
||||
|
||||
only forth definitions also frame-drawing
|
||||
|
||||
: hline ( len x y -- ) \ Draw horizontal single line
|
||||
at-xy \ move cursor
|
||||
0 do
|
||||
h_el @ emit
|
||||
h_el @ xemit
|
||||
loop
|
||||
;
|
||||
|
||||
@ -113,7 +113,7 @@ only forth definitions also frame-drawing
|
||||
2dup 4 pick
|
||||
0 do
|
||||
at-xy
|
||||
v_el @ emit
|
||||
v_el @ xemit
|
||||
1+
|
||||
2dup
|
||||
loop
|
||||
@ -129,10 +129,10 @@ only forth definitions also frame-drawing
|
||||
hline \ Draw top horiz line
|
||||
2dup swap 1+ swap 4 pick + 5 pick 1- -rot
|
||||
hline \ Draw bottom horiz line
|
||||
2dup at-xy lt_el @ emit \ Draw left-top corner
|
||||
2dup 4 pick + at-xy lb_el @ emit \ Draw left bottom corner
|
||||
2dup swap 5 pick + swap at-xy rt_el @ emit \ Draw right top corner
|
||||
2 pick + swap 3 pick + swap at-xy rb_el @ emit
|
||||
2dup at-xy lt_el @ xemit \ Draw left-top corner
|
||||
2dup 4 pick + at-xy lb_el @ xemit \ Draw left bottom corner
|
||||
2dup swap 5 pick + swap at-xy rt_el @ xemit \ Draw right top corner
|
||||
2 pick + swap 3 pick + swap at-xy rb_el @ xemit
|
||||
2drop
|
||||
;
|
||||
|
||||
|
@ -14,6 +14,9 @@ SRCS= bio.c biosacpi.c biosdisk.c biosmem.c biospnp.c \
|
||||
SRCS+= devicename_stubs.c
|
||||
CFLAGS+= -I${ZFSSRC}
|
||||
|
||||
.PATH: ${SYSDIR}/teken
|
||||
SRCS+= teken.c
|
||||
|
||||
BOOT_COMCONSOLE_PORT?= 0x3f8
|
||||
CFLAGS+= -DCOMPORT=${BOOT_COMCONSOLE_PORT}
|
||||
|
||||
@ -37,8 +40,9 @@ CFLAGS+= -DSMBIOS_NETWORK_ENDIAN_UUID
|
||||
.endif
|
||||
.endif
|
||||
|
||||
# Include simple terminal emulation (cons25-compatible)
|
||||
CFLAGS+= -DTERM_EMU
|
||||
# terminal emulation
|
||||
CFLAGS.vidconsole.c+= -I${SRCTOP}/sys/teken
|
||||
CFLAGS.teken.c+= -I${SRCTOP}/sys/teken
|
||||
|
||||
# XXX: make alloca() useable
|
||||
CFLAGS+= -Dalloca=__builtin_alloca
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -370,20 +370,20 @@ drawer.frame_styles = {
|
||||
bottom_right = "+",
|
||||
},
|
||||
["single"] = {
|
||||
horizontal = "\xC4",
|
||||
vertical = "\xB3",
|
||||
top_left = "\xDA",
|
||||
bottom_left = "\xC0",
|
||||
top_right = "\xBF",
|
||||
bottom_right = "\xD9",
|
||||
horizontal = "\xE2\x94\x80",
|
||||
vertical = "\xE2\x94\x82",
|
||||
top_left = "\xE2\x94\x8C",
|
||||
bottom_left = "\xE2\x94\x94",
|
||||
top_right = "\xE2\x94\x90",
|
||||
bottom_right = "\xE2\x94\x98",
|
||||
},
|
||||
["double"] = {
|
||||
horizontal = "\xCD",
|
||||
vertical = "\xBA",
|
||||
top_left = "\xC9",
|
||||
bottom_left = "\xC8",
|
||||
top_right = "\xBB",
|
||||
bottom_right = "\xBC",
|
||||
horizontal = "\xE2\x95\x90",
|
||||
vertical = "\xE2\x95\x91",
|
||||
top_left = "\xE2\x95\x94",
|
||||
bottom_left = "\xE2\x95\x9A",
|
||||
top_right = "\xE2\x95\x97",
|
||||
bottom_right = "\xE2\x95\x9D",
|
||||
},
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user