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:
Toomas Soome 2019-09-05 22:15:50 +00:00
parent a6935d085c
commit 56758831fe
11 changed files with 1042 additions and 905 deletions

View File

@ -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"

View File

@ -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[]);

View File

@ -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>

View File

@ -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);
}

View File

@ -11,5 +11,5 @@ SRCS+= nullconsole.c \
comconsole.c \
spinconsole.c
CFLAGS+= -fPIC -DTERM_EMU
CFLAGS+= -fPIC
LDFLAGS+= -Wl,-znocombreloc

View File

@ -9,5 +9,5 @@ SRCS+= nullconsole.c \
comconsole.c \
spinconsole.c
CFLAGS+= -fPIC -DTERM_EMU
CFLAGS+= -fPIC
LDFLAGS+= -Wl,-znocombreloc

View File

@ -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);
}

View File

@ -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
;

View File

@ -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

View File

@ -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",
},
}