diff --git a/conf/common.rmk b/conf/common.rmk index a1a39d723..3e22678ad 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -465,7 +465,7 @@ scsi_mod_LDFLAGS = $(COMMON_LDFLAGS) pkglib_MODULES += minicmd.mod extcmd.mod hello.mod handler.mod \ ls.mod cmp.mod cat.mod help.mod search.mod loopback.mod \ configfile.mod echo.mod \ - terminfo.mod test.mod blocklist.mod hexdump.mod \ + test.mod blocklist.mod hexdump.mod \ read.mod sleep.mod loadenv.mod crc.mod parttool.mod \ msdospart.mod memrw.mod normal.mod sh.mod \ gptsync.mod true.mod probe.mod password.mod \ @@ -596,10 +596,13 @@ configfile_mod_SOURCES = commands/configfile.c configfile_mod_CFLAGS = $(COMMON_CFLAGS) configfile_mod_LDFLAGS = $(COMMON_LDFLAGS) +ifneq ($(platform), ieee1275) # For terminfo.mod. +pkglib_MODULES += terminfo.mod terminfo_mod_SOURCES = term/terminfo.c term/tparm.c terminfo_mod_CFLAGS = $(COMMON_CFLAGS) terminfo_mod_LDFLAGS = $(COMMON_LDFLAGS) +endif # For blocklist.mod. blocklist_mod_SOURCES = commands/blocklist.c diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk index 05ba38a65..648205657 100644 --- a/conf/i386-ieee1275.rmk +++ b/conf/i386-ieee1275.rmk @@ -22,6 +22,7 @@ kernel_img_SOURCES = kern/i386/ieee1275/startup.S \ kern/generic/millisleep.c \ kern/ieee1275/ieee1275.c \ term/ieee1275/ofconsole.c \ + term/terminfo.c term/tparm.c \ disk/ieee1275/ofdisk.c \ symlist.c kernel_img_HEADERS += ieee1275/ieee1275.h diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index d5968ac8e..cd08770df 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -16,7 +16,7 @@ kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/ieee1275/init.c \ kern/ieee1275/mmap.c \ - term/ieee1275/ofconsole.c \ + term/ieee1275/ofconsole.c term/terminfo.c term/tparm.c \ kern/ieee1275/openfw.c disk/ieee1275/ofdisk.c \ kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ kern/generic/millisleep.c kern/time.c \ diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk index 49834a1fd..6fd7d0032 100644 --- a/conf/sparc64-ieee1275.rmk +++ b/conf/sparc64-ieee1275.rmk @@ -30,7 +30,8 @@ kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.S kern/ieee1275/cmain.c \ kern/sparc64/ieee1275/init.c \ kern/ieee1275/mmap.c \ term/ieee1275/ofconsole.c \ - kern/ieee1275/openfw.c disk/ieee1275/ofdisk.c \ + kern/ieee1275/openfw.c term/terminfo.c term/tparm.c \ + disk/ieee1275/ofdisk.c \ kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ kern/generic/millisleep.c kern/time.c \ symlist.c kern/$(target_cpu)/cache.S diff --git a/include/grub/terminfo.h b/include/grub/terminfo.h index e3a2c170a..84a6f6ab2 100644 --- a/include/grub/terminfo.h +++ b/include/grub/terminfo.h @@ -34,4 +34,7 @@ void grub_terminfo_reverse_video_off (grub_term_output_t oterm); void grub_terminfo_cursor_on (grub_term_output_t oterm); void grub_terminfo_cursor_off (grub_term_output_t oterm); +#define GRUB_TERMINFO_READKEY_MAX_LEN 4 +void grub_terminfo_readkey (int *keys, int *len, int (*readkey) (void)); + #endif /* ! GRUB_TERMINFO_HEADER */ diff --git a/term/ieee1275/ofconsole.c b/term/ieee1275/ofconsole.c index ce587d491..74de5806e 100644 --- a/term/ieee1275/ofconsole.c +++ b/term/ieee1275/ofconsole.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -34,7 +35,7 @@ static grub_uint8_t grub_ofconsole_height; static int grub_curr_x; static int grub_curr_y; -static int grub_keybuf; +static int grub_keybuf[GRUB_TERMINFO_READKEY_MAX_LEN]; static int grub_buflen; struct color @@ -149,116 +150,28 @@ grub_ofconsole_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_col *highlight_color = grub_ofconsole_highlight_color; } -#define ANSI_C0 0x9b - static int -grub_ofconsole_readkey (int *key) +readkey (void) { grub_uint8_t c; grub_ssize_t actual = 0; grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); if (actual > 0) - switch(c) - { - case 0x7f: - /* Backspace: Ctrl-h. */ - c = '\b'; - break; - case ANSI_C0: - case '\e': - { - grub_uint64_t start; - - if (c == '\e') - { - grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); - - /* On 9600 we have to wait up to 12 milliseconds. */ - start = grub_get_time_ms (); - while (actual <= 0 && grub_get_time_ms () - start < 12) - grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); - - if (actual <= 0) - { - *key = '\e'; - return 1; - } - - if (c != '[') - return 0; - } - - grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); - - /* On 9600 we have to wait up to 12 milliseconds. */ - start = grub_get_time_ms (); - while (actual <= 0 && grub_get_time_ms () - start < 12) - grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); - if (actual <= 0) - return 0; - - switch (c) - { - case 'A': - /* Up: Ctrl-p. */ - c = GRUB_TERM_UP; - break; - case 'B': - /* Down: Ctrl-n. */ - c = GRUB_TERM_DOWN; - break; - case 'C': - /* Right: Ctrl-f. */ - c = GRUB_TERM_RIGHT; - break; - case 'D': - /* Left: Ctrl-b. */ - c = GRUB_TERM_LEFT; - break; - case '3': - { - grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); - /* On 9600 we have to wait up to 12 milliseconds. */ - start = grub_get_time_ms (); - while (actual <= 0 && grub_get_time_ms () - start < 12) - grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); - - if (actual <= 0) - return 0; - - /* Delete: Ctrl-d. */ - if (c == '~') - c = GRUB_TERM_DC; - else - return 0; - break; - } - break; - } - } - } - - *key = c; - return actual > 0; + return c; + return -1; } static int grub_ofconsole_checkkey (void) { - int key; - int read; - if (grub_buflen) return 1; - read = grub_ofconsole_readkey (&key); - if (read) - { - grub_keybuf = key; - grub_buflen = 1; - return 1; - } + grub_terminfo_readkey (grub_keybuf, &grub_buflen, readkey); + + if (grub_buflen) + return 1; return -1; } @@ -266,17 +179,14 @@ grub_ofconsole_checkkey (void) static int grub_ofconsole_getkey (void) { - int key; + int ret; + while (! grub_buflen) + grub_terminfo_readkey (grub_keybuf, &grub_buflen, readkey); - if (grub_buflen) - { - grub_buflen =0; - return grub_keybuf; - } - - while (! grub_ofconsole_readkey (&key)); - - return key; + ret = grub_keybuf[0]; + grub_buflen--; + grub_memmove (grub_keybuf, grub_keybuf + 1, grub_buflen); + return ret; } static grub_uint16_t diff --git a/term/terminfo.c b/term/terminfo.c index 03a7dc2b6..ef713e151 100644 --- a/term/terminfo.c +++ b/term/terminfo.c @@ -32,6 +32,7 @@ #include #include #include +#include struct terminfo { @@ -167,6 +168,114 @@ grub_terminfo_cursor_off (grub_term_output_t oterm) putstr (grub_terminfo_tparm (term.cursor_off), oterm); } +#define ANSI_C0 0x9b + +void +grub_terminfo_readkey (int *keys, int *len, int (*readkey) (void)) +{ + int c; + +#define CONTINUE_READ \ + { \ + grub_uint64_t start; \ + /* On 9600 we have to wait up to 12 milliseconds. */ \ + start = grub_get_time_ms (); \ + do \ + c = readkey (); \ + while (c == -1 && grub_get_time_ms () - start < 12); \ + if (c == -1) \ + return; \ + \ + keys[*len] = c; \ + (*len)++; \ + } + + c = readkey (); + if (c < 0) + { + *len = 0; + return; + } + *len = 1; + keys[0] = c; + if (c != ANSI_C0 && c != '\e') + { + /* Backspace: Ctrl-h. */ + if (c == 0x7f) + c = '\b'; + *len = 1; + keys[0] = c; + return; + } + + { + static struct + { + char key; + char ascii; + } + three_code_table[] = + { + {'4', GRUB_TERM_DC}, + {'A', GRUB_TERM_UP}, + {'B', GRUB_TERM_DOWN}, + {'C', GRUB_TERM_RIGHT}, + {'D', GRUB_TERM_LEFT}, + {'F', GRUB_TERM_END}, + {'H', GRUB_TERM_HOME}, + {'K', GRUB_TERM_END}, + {'P', GRUB_TERM_DC}, + {'?', GRUB_TERM_PPAGE}, + {'/', GRUB_TERM_NPAGE} + }; + + static struct + { + char key; + char ascii; + } + four_code_table[] = + { + {'1', GRUB_TERM_HOME}, + {'3', GRUB_TERM_DC}, + {'5', GRUB_TERM_PPAGE}, + {'6', GRUB_TERM_NPAGE} + }; + unsigned i; + + if (c == '\e') + { + CONTINUE_READ; + + if (c != '[') + return; + } + + CONTINUE_READ; + + for (i = 0; i < ARRAY_SIZE (three_code_table); i++) + if (three_code_table[i].key == c) + { + keys[0] = three_code_table[i].ascii; + *len = 1; + return; + } + + for (i = 0; i < ARRAY_SIZE (four_code_table); i++) + if (four_code_table[i].key == c) + { + CONTINUE_READ; + if (c != '~') + return; + keys[0] = three_code_table[i].ascii; + *len = 1; + return; + } + return; + } +#undef CONTINUE_READ +} + /* GRUB Command. */ static grub_err_t