Replace libcurses with our own vt100 handling for the ease of testing

and decreasing prerequisites.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2013-04-27 00:02:23 +02:00
parent b24ca7cd89
commit db99fbe83f
9 changed files with 152 additions and 270 deletions

View file

@ -1,3 +1,8 @@
2013-04-26 Vladimir Serbinenko <phcoder@gmail.com>
Replace libcurses with our own vt100 handling for the ease of testing
and decreasing prerequisites.
2013-04-26 Vladimir Serbinenko <phcoder@gmail.com> 2013-04-26 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/Makefile.core.def: Fix grub-emu and grub-emu-lite sources. * grub-core/Makefile.core.def: Fix grub-emu and grub-emu-lite sources.

View file

@ -23,11 +23,11 @@ On GNU/Linux, you also need:
* libdevmapper 1.02.34 or later (recommended) * libdevmapper 1.02.34 or later (recommended)
To build grub-emu, you need: For optional grub-emu features, you need:
* ncurses
* libusb (recommended)
* SDL (recommended) * SDL (recommended)
* libpciaccess (optional)
* libusb (optional)
To build GRUB's graphical terminal (gfxterm), you need: To build GRUB's graphical terminal (gfxterm), you need:

View file

@ -842,22 +842,6 @@ AC_ARG_ENABLE([grub-emu-pci],
[build and install the `grub-emu' debugging utility with PCI support (potentially dangerous) (default=no)])]) [build and install the `grub-emu' debugging utility with PCI support (potentially dangerous) (default=no)])])
if test "$platform" = emu; then if test "$platform" = emu; then
missing_ncurses=
[# Check for curses libraries.]
AC_CHECK_LIB([ncurses], [wgetch], [LIBCURSES="-lncurses"],
[AC_CHECK_LIB([curses], [wgetch], [LIBCURSES="-lcurses"],
[missing_ncurses=[true]])])
AC_SUBST([LIBCURSES])
[if [ x"$missing_ncurses" = x ]; then ]
[# Check for headers.]
AC_CHECK_HEADERS([ncurses/curses.h], [],
[AC_CHECK_HEADERS([ncurses.h], [],
[AC_CHECK_HEADERS([curses.h], [],
[missing_ncurses=[true]])])])
[fi]
if test x"$missing_ncurses" = xtrue ; then
AC_MSG_ERROR([grub-emu can't be compiled without ncurses])
fi
if test x"$enable_grub_emu_usb" != xyes ; then if test x"$enable_grub_emu_usb" != xyes ; then
grub_emu_usb_excuse="not enabled" grub_emu_usb_excuse="not enabled"

View file

@ -4586,26 +4586,35 @@ On normalized ZFS subvolumes filenames out of normalisation are inaccessible.
@chapter Output terminal @chapter Output terminal
Firmware output console ``console'' on ARC and IEEE1275 are limited to ASCII. Firmware output console ``console'' on ARC and IEEE1275 are limited to ASCII.
BIOS firmware console and VGA text are limited to ASCII and some pseudographics. BIOS firmware console and VGA text are limited to ASCII and some pseudographics.
None of above mentioned is appropriate for displaying international and any None of above mentioned is appropriate for displaying international and any
unsupported character is replaced with question mark except pseudographics unsupported character is replaced with question mark except pseudographics
which we attempt to approximate with ASCII. EFI console on the other hand which we attempt to approximate with ASCII.
nominally supports UTF-16 but actual language coverage depends on firmware and
may be very limited. The encoding used on serial can be chosen with EFI console on the other hand nominally supports UTF-16 but actual language
@command{terminfo} as either ASCII, UTF-8 or ``visual UTF-8''. Last one is coverage depends on firmware and may be very limited.
against the specification but results in correct rendering of right-to-left
on some readers which don't have own bidi implementation. When using gfxterm The encoding used on serial can be chosen with @command{terminfo} as
or gfxmenu GRUB itself is responsible for rendering the text. In this case either ASCII, UTF-8 or ``visual UTF-8''. Last one is against the specification
GRUB is limited by loaded fonts. If fonts contain all required characters but results in correct rendering of right-to-left on some readers which don't
then bidirectional text, cursive variants and combining marks other than have own bidi implementation.
enclosing, half (e.g. left half tilde or combining overline) and double ones.
Ligatures aren't supported though. This should cover European, Middle Eastern On emu GRUB checks if charset is UTF-8 and uses it if so and uses ASCII
(if you don't mind lack of lam-alif ligature in Arabic) and East Asian scripts. otherwise.
Notable unsupported scripts are Brahmic family and derived as well as
Mongolian, Tifinagh, Korean Jamo (precomposed characters have no problem) When using gfxterm or gfxmenu GRUB itself is responsible for rendering the
and tonal writing (2e5-2e9). GRUB also ignores deprecated (as specified text. In this case GRUB is limited by loaded fonts. If fonts contain all
in Unicode) characters (e.g. tags). GRUB also doesn't handle so called required characters then bidirectional text, cursive variants and combining
``annotation characters'' If you can complete either of marks other than enclosing, half (e.g. left half tilde or combining overline)
and double ones. Ligatures aren't supported though. This should cover European,
Middle Eastern (if you don't mind lack of lam-alif ligature in Arabic) and
East Asian scripts. Notable unsupported scripts are Brahmic family and
derived as well as Mongolian, Tifinagh, Korean Jamo (precomposed characters
have no problem) and tonal writing (2e5-2e9). GRUB also ignores deprecated
(as specified in Unicode) characters (e.g. tags). GRUB also doesn't handle so
called ``annotation characters'' If you can complete either of
two lists or, better, propose a patch to improve rendering, please contact two lists or, better, propose a patch to improve rendering, please contact
developer team. developer team.
@ -4826,7 +4835,7 @@ and mips-qemu_mips can use only memory up to first hole.
@multitable @columnfractions .20 .20 .20 .20 .20 @multitable @columnfractions .20 .20 .20 .20 .20
@item @tab MIPS qemu @tab emu @item @tab MIPS qemu @tab emu
@item video @tab no @tab yes @item video @tab no @tab yes
@item console charset @tab CP437 @tab ASCII @item console charset @tab CP437 @tab Unicode (*)
@item network @tab no @tab yes @item network @tab no @tab yes
@item ATA/AHCI @tab yes @tab no @item ATA/AHCI @tab yes @tab no
@item AT keyboard @tab yes @tab no @item AT keyboard @tab yes @tab no

View file

@ -57,7 +57,7 @@ GROUPS["videomodules"] = GRUB_PLATFORMS[:];
for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)
# Similar for terminfo # Similar for terminfo
GROUPS["terminfoinkernel"] = ["mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["ieee1275"]; GROUPS["terminfoinkernel"] = [ "emu", "mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["ieee1275"];
GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; GROUPS["terminfomodule"] = GRUB_PLATFORMS[:];
for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i)

View file

@ -216,6 +216,7 @@ if COND_emu
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/export.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/export.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
if COND_GRUB_EMU_SDL if COND_GRUB_EMU_SDL
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
endif endif

View file

@ -250,7 +250,7 @@ program = {
ldadd = 'kernel.exec$(EXEEXT)'; ldadd = 'kernel.exec$(EXEEXT)';
ldadd = '$(MODULE_FILES)'; ldadd = '$(MODULE_FILES)';
ldadd = 'gnulib/libgnu.a $(LIBCURSES) $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; ldadd = 'gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
enable = emu; enable = emu;
}; };
@ -262,7 +262,7 @@ program = {
emu_nodist = symlist.c; emu_nodist = symlist.c;
ldadd = 'kernel.exec$(EXEEXT)'; ldadd = 'kernel.exec$(EXEEXT)';
ldadd = 'gnulib/libgnu.a $(LIBCURSES) $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; ldadd = 'gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
enable = emu; enable = emu;
}; };

View file

@ -1,7 +1,7 @@
/* console.c -- Ncurses console for GRUB. */ /* console.c -- console for GRUB. */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2005,2007,2008 Free Software Foundation, Inc. * Copyright (C) 2013 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,274 +20,159 @@
#include <config.h> #include <config.h>
#include <config-util.h> #include <config-util.h>
/* For compatibility. */
#ifndef A_NORMAL
# define A_NORMAL 0
#endif /* ! A_NORMAL */
#ifndef A_STANDOUT
# define A_STANDOUT 0
#endif /* ! A_STANDOUT */
#include <grub/emu/console.h>
#include <grub/term.h> #include <grub/term.h>
#include <grub/types.h> #include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/terminfo.h>
#include <grub/dl.h>
#if defined(HAVE_NCURSES_CURSES_H) #include <sys/types.h>
# include <ncurses/curses.h> #include <sys/stat.h>
#elif defined(HAVE_NCURSES_H) #include <fcntl.h>
# include <ncurses.h> #include <unistd.h>
#elif defined(HAVE_CURSES_H) #include <termios.h>
# include <curses.h> #include <stdlib.h>
#else #include <sys/ioctl.h>
#error What the hell? #include <langinfo.h>
#endif
static int grub_console_attr = A_NORMAL; #include <grub/emu/console.h>
grub_uint8_t grub_console_cur_color = 7; extern struct grub_terminfo_output_state grub_console_terminfo_output;
static int original_fl;
static const grub_uint8_t grub_console_standard_color = 0x7; static int saved_orig;
static struct termios orig_tty;
#define NUM_COLORS 8 static struct termios new_tty;
static grub_uint8_t color_map[NUM_COLORS] =
{
COLOR_BLACK,
COLOR_BLUE,
COLOR_GREEN,
COLOR_CYAN,
COLOR_RED,
COLOR_MAGENTA,
COLOR_YELLOW,
COLOR_WHITE
};
static int use_color;
static void static void
grub_ncurses_putchar (struct grub_term_output *term __attribute__ ((unused)), put (struct grub_term_output *term __attribute__ ((unused)), const int c)
const struct grub_unicode_glyph *c)
{ {
addch (c->base | grub_console_attr); char chr = c;
}
static void write (STDOUT_FILENO, &chr, 1);
grub_ncurses_setcolorstate (struct grub_term_output *term,
grub_term_color_state state)
{
switch (state)
{
case GRUB_TERM_COLOR_STANDARD:
grub_console_cur_color = grub_console_standard_color;
grub_console_attr = A_NORMAL;
break;
case GRUB_TERM_COLOR_NORMAL:
grub_console_cur_color = grub_term_normal_color;
grub_console_attr = A_NORMAL;
break;
case GRUB_TERM_COLOR_HIGHLIGHT:
grub_console_cur_color = grub_term_highlight_color;
grub_console_attr = A_STANDOUT;
break;
default:
break;
}
if (use_color)
{
grub_uint8_t fg, bg;
fg = (grub_console_cur_color & 7);
bg = (grub_console_cur_color >> 4) & 7;
grub_console_attr = (grub_console_cur_color & 8) ? A_BOLD : A_NORMAL;
color_set ((bg << 3) + fg, 0);
}
} }
static int static int
grub_ncurses_getkey (struct grub_term_input *term __attribute__ ((unused))) readkey (struct grub_term_input *term __attribute__ ((unused)))
{ {
int c; grub_uint8_t c;
ssize_t actual;
wtimeout (stdscr, 100);
c = getch ();
switch (c)
{
case ERR:
return GRUB_TERM_NO_KEY;
case KEY_LEFT:
c = GRUB_TERM_KEY_LEFT;
break;
case KEY_RIGHT:
c = GRUB_TERM_KEY_RIGHT;
break;
case KEY_UP:
c = GRUB_TERM_KEY_UP;
break;
case KEY_DOWN:
c = GRUB_TERM_KEY_DOWN;
break;
case KEY_IC:
c = 24;
break;
case KEY_DC:
c = GRUB_TERM_KEY_DC;
break;
case KEY_BACKSPACE:
/* XXX: For some reason ncurses on xterm does not return
KEY_BACKSPACE. */
case 127:
c = '\b';
break;
case KEY_HOME:
c = GRUB_TERM_KEY_HOME;
break;
case KEY_END:
c = GRUB_TERM_KEY_END;
break;
case KEY_NPAGE:
c = GRUB_TERM_KEY_NPAGE;
break;
case KEY_PPAGE:
c = GRUB_TERM_KEY_PPAGE;
break;
}
actual = read (STDIN_FILENO, &c, 1);
if (actual > 0)
return c; return c;
} return -1;
static grub_uint16_t
grub_ncurses_getxy (struct grub_term_output *term __attribute__ ((unused)))
{
int x;
int y;
getyx (stdscr, y, x);
return (x << 8) | y;
}
static grub_uint16_t
grub_ncurses_getwh (struct grub_term_output *term __attribute__ ((unused)))
{
int x;
int y;
getmaxyx (stdscr, y, x);
return (x << 8) | y;
}
static void
grub_ncurses_gotoxy (struct grub_term_output *term __attribute__ ((unused)),
grub_uint8_t x, grub_uint8_t y)
{
move (y, x);
}
static void
grub_ncurses_cls (struct grub_term_output *term __attribute__ ((unused)))
{
clear ();
refresh ();
}
static void
grub_ncurses_setcursor (struct grub_term_output *term __attribute__ ((unused)),
int on)
{
curs_set (on ? 1 : 0);
}
static void
grub_ncurses_refresh (struct grub_term_output *term __attribute__ ((unused)))
{
refresh ();
} }
static grub_err_t static grub_err_t
grub_ncurses_init (struct grub_term_output *term __attribute__ ((unused))) grub_console_init_input (struct grub_term_input *term)
{ {
initscr (); if (!saved_orig)
raw ();
noecho ();
scrollok (stdscr, TRUE);
nonl ();
intrflush (stdscr, FALSE);
keypad (stdscr, TRUE);
if (has_colors ())
{ {
start_color (); original_fl = fcntl (STDIN_FILENO, F_GETFL);
fcntl (STDIN_FILENO, F_SETFL, original_fl | O_NONBLOCK);
if ((COLORS >= NUM_COLORS) && (COLOR_PAIRS >= NUM_COLORS * NUM_COLORS))
{
int i, j, n;
n = 0;
for (i = 0; i < NUM_COLORS; i++)
for (j = 0; j < NUM_COLORS; j++)
init_pair(n++, color_map[j], color_map[i]);
use_color = 1;
}
} }
return 0; saved_orig = 1;
tcgetattr(STDIN_FILENO, &orig_tty);
new_tty = orig_tty;
new_tty.c_lflag &= ~(ICANON | ECHO);
new_tty.c_cc[VMIN] = 1;
tcsetattr(STDIN_FILENO, TCSANOW, &new_tty);
return grub_terminfo_input_init (term);
} }
static grub_err_t static grub_err_t
grub_ncurses_fini (struct grub_term_output *term __attribute__ ((unused))) grub_console_fini_input (struct grub_term_input *term
__attribute__ ((unused)))
{ {
endwin (); fcntl (STDIN_FILENO, F_SETFL, original_fl);
tcsetattr(STDIN_FILENO, TCSANOW, &orig_tty);
saved_orig = 0;
return GRUB_ERR_NONE;
}
static grub_err_t
grub_console_init_output (struct grub_term_output *term)
{
struct winsize size;
if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &size) >= 0)
{
grub_console_terminfo_output.width = size.ws_col;
grub_console_terminfo_output.height = size.ws_row;
}
else
{
grub_console_terminfo_output.width = 80;
grub_console_terminfo_output.height = 24;
}
grub_terminfo_output_init (term);
return 0; return 0;
} }
static struct grub_term_input grub_ncurses_term_input =
struct grub_terminfo_input_state grub_console_terminfo_input =
{ {
.name = "console", .readkey = readkey
.getkey = grub_ncurses_getkey,
}; };
static struct grub_term_output grub_ncurses_term_output = struct grub_terminfo_output_state grub_console_terminfo_output =
{
.put = put,
.width = 80,
.height = 24
};
static struct grub_term_input grub_console_term_input =
{ {
.name = "console", .name = "console",
.init = grub_ncurses_init, .init = grub_console_init_input,
.fini = grub_ncurses_fini, .fini = grub_console_fini_input,
.putchar = grub_ncurses_putchar, .getkey = grub_terminfo_getkey,
.getxy = grub_ncurses_getxy, .data = &grub_console_terminfo_input
.getwh = grub_ncurses_getwh, };
.gotoxy = grub_ncurses_gotoxy,
.cls = grub_ncurses_cls, static struct grub_term_output grub_console_term_output =
.setcolorstate = grub_ncurses_setcolorstate, {
.setcursor = grub_ncurses_setcursor, .name = "console",
.refresh = grub_ncurses_refresh, .init = grub_console_init_output,
.flags = GRUB_TERM_CODE_TYPE_ASCII .putchar = grub_terminfo_putchar,
.getxy = grub_terminfo_getxy,
.getwh = grub_terminfo_getwh,
.gotoxy = grub_terminfo_gotoxy,
.cls = grub_terminfo_cls,
.setcolorstate = grub_terminfo_setcolorstate,
.setcursor = grub_terminfo_setcursor,
.data = &grub_console_terminfo_output,
}; };
void void
grub_console_init (void) grub_console_init (void)
{ {
grub_term_register_output ("console", &grub_ncurses_term_output); const char *cs = nl_langinfo (CODESET);
grub_term_register_input ("console", &grub_ncurses_term_input); if (cs && grub_strcasecmp (cs, "UTF-8"))
grub_console_term_output.flags = GRUB_TERM_CODE_TYPE_UTF8_LOGICAL;
else
grub_console_term_output.flags = GRUB_TERM_CODE_TYPE_ASCII;
grub_term_register_input ("console", &grub_console_term_input);
grub_term_register_output ("console", &grub_console_term_output);
grub_terminfo_init ();
grub_terminfo_output_register (&grub_console_term_output, "vt100-color");
} }
void void
grub_console_fini (void) grub_console_fini (void)
{ {
grub_ncurses_fini (&grub_ncurses_term_output); if (saved_orig)
{
fcntl (STDIN_FILENO, F_SETFL, original_fl);
tcsetattr(STDIN_FILENO, TCSANOW, &orig_tty);
}
saved_orig = 0;
} }

View file

@ -82,9 +82,7 @@ grub_err_t EXPORT_FUNC (grub_terminfo_output_register) (struct grub_term_output
const char *type); const char *type);
grub_err_t EXPORT_FUNC (grub_terminfo_output_unregister) (struct grub_term_output *term); grub_err_t EXPORT_FUNC (grub_terminfo_output_unregister) (struct grub_term_output *term);
#ifndef GRUB_MACHINE_EMU
void grub_terminfo_init (void); void grub_terminfo_init (void);
void grub_terminfo_fini (void); void grub_terminfo_fini (void);
#endif
#endif /* ! GRUB_TERMINFO_HEADER */ #endif /* ! GRUB_TERMINFO_HEADER */