* x86 serial support
@ 2005-02-21 12:38 Omniflux
2005-03-02 21:33 ` Yoshinori K. Okuji
0 siblings, 1 reply; 15+ messages in thread
From: Omniflux @ 2005-02-21 12:38 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 607 bytes --]
Here is a patch to add serial support to x86.
It is a porting of grub-legacy's serial support, copies of grub-legacy's
tparms.{c,h} and terminfo.{c.h} and modifications based on grub2's
term/i386/pc/vga.c, disk/loopback.c (to add a grub command), and
util/console.c
It still needs a lot of work (it does not even let you specify serial
port settings yet), but I don't want to spend any more time on it if it
is not going to be used.
If this is headed in the right direction, and likely to be accepted for
merging with a little more work, I'll keep working on it.
Please let me know.
--
Omniflux
[-- Attachment #2: serial-x86-support.diff --]
[-- Type: text/plain, Size: 49715 bytes --]
diff -uNr grub2/conf/i386-pc.mk grub2.newserial/conf/i386-pc.mk
--- grub2/conf/i386-pc.mk 2005-02-19 20:56:06.000000000 +0000
+++ grub2.newserial/conf/i386-pc.mk 2005-02-21 12:20:18.044758032 +0000
@@ -253,7 +253,7 @@
file.h fs.h kernel.h loader.h misc.h mm.h net.h rescue.h symbol.h \
term.h types.h machine/biosdisk.h machine/boot.h \
machine/console.h machine/init.h machine/memory.h \
- machine/loader.h partition.h pc_partition.h machine/time.h machine/vga.h
+ machine/loader.h partition.h pc_partition.h machine/time.h machine/vga.h machine/serial.h
kernel_img_CFLAGS = $(COMMON_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8200
@@ -902,7 +902,7 @@
pkgdata_MODULES = _chain.mod _linux.mod linux.mod fat.mod ufs.mod ext2.mod minix.mod \
hfs.mod jfs.mod normal.mod hello.mod vga.mod font.mod _multiboot.mod ls.mod \
boot.mod cmp.mod cat.mod terminal.mod fshelp.mod chain.mod multiboot.mod \
- amiga.mod apple.mod pc.mod loopback.mod reboot.mod halt.mod help.mod
+ amiga.mod apple.mod pc.mod loopback.mod reboot.mod halt.mod help.mod serial.mod
# For _chain.mod.
_chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -1817,6 +1817,51 @@
vga_mod_CFLAGS = $(COMMON_CFLAGS)
+# For serial.mod.
+serial_mod_SOURCES = term/i386/pc/serial.c term/tparm.c term/terminfo.c
+CLEANFILES += serial.mod mod-serial.o mod-serial.c pre-serial.o serial_mod-term_i386_pc_serial.o def-serial.lst und-serial.lst
+MOSTLYCLEANFILES += serial_mod-term_i386_pc_serial.d
+DEFSYMFILES += def-serial.lst
+UNDSYMFILES += und-serial.lst
+
+serial.mod: pre-serial.o mod-serial.o
+ -rm -f $@
+ $(LD) -r -d -o $@ $^
+ $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
+
+pre-serial.o: serial_mod-term_i386_pc_serial.o serial_mod-term_i386_pc_terminfo.o serial_mod-term_i386_pc_tparm.o
+ -rm -f $@
+ $(LD) -r -d -o $@ $^
+
+mod-serial.o: mod-serial.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(serial_mod_CFLAGS) -c -o $@ $<
+
+mod-serial.c: moddep.lst genmodsrc.sh
+ sh $(srcdir)/genmodsrc.sh 'serial' $< > $@ || (rm -f $@; exit 1)
+
+def-serial.lst: pre-serial.o
+ $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 serial/' > $@
+
+und-serial.lst: pre-serial.o
+ echo 'serial' > $@
+ $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+serial_mod-term_i386_pc_serial.o: term/i386/pc/serial.c
+ $(CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(CPPFLAGS) $(CFLAGS) $(serial_mod_CFLAGS) -c -o $@ $<
+
+serial_mod-term_i386_pc_serial.d: term/i386/pc/serial.c
+ set -e; $(CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(CPPFLAGS) $(CFLAGS) $(serial_mod_CFLAGS) -M $< | sed 's,serial\.o[ :]*,serial_mod-term_i386_pc_serial.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
+
+serial_mod-term_i386_pc_terminfo.o: term/terminfo.c
+ $(CC) -Iterm -I$(srcdir)/term $(CPPFLAGS) $(CFLAGS) $(serial_mod_CFLAGS) -c -o $@ $<
+
+serial_mod-term_i386_pc_tparm.o: term/tparm.c
+ $(CC) -Iterm -I$(srcdir)/term $(CPPFLAGS) $(CFLAGS) $(serial_mod_CFLAGS) -c -o $@ $<
+
+-include serial_mod-term_i386_pc_serial.d
+
+serial_mod_CFLAGS = $(COMMON_CFLAGS)
+
# For font.mod.
font_mod_SOURCES = font/manager.c
CLEANFILES += font.mod mod-font.o mod-font.c pre-font.o font_mod-font_manager.o def-font.lst und-font.lst
diff -uNr grub2/conf/i386-pc.rmk grub2.newserial/conf/i386-pc.rmk
--- grub2/conf/i386-pc.rmk 2005-02-19 20:56:06.000000000 +0000
+++ grub2.newserial/conf/i386-pc.rmk 2005-02-21 12:21:03.387864832 +0000
@@ -33,7 +33,8 @@
file.h fs.h kernel.h loader.h misc.h mm.h net.h rescue.h symbol.h \
term.h types.h machine/biosdisk.h machine/boot.h \
machine/console.h machine/init.h machine/memory.h \
- machine/loader.h partition.h pc_partition.h machine/time.h machine/vga.h
+ machine/loader.h partition.h pc_partition.h machine/time.h machine/vga.h machine/serial.h
+
kernel_img_CFLAGS = $(COMMON_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8200
@@ -187,6 +188,10 @@
vga_mod_SOURCES = term/i386/pc/vga.c
vga_mod_CFLAGS = $(COMMON_CFLAGS)
+# For serial.mod.
+serial_mod_SOURCES = term/i386/pc/serial.c term/tparm.c term/terminfo.c
+serial_mod_CFLAGS = $(COMMON_CFLAGS)
+
# For font.mod.
font_mod_SOURCES = font/manager.c
font_mod_CFLAGS = $(COMMON_CFLAGS)
diff -uNr grub2/include/grub/i386/pc/serial.h grub2.newserial/include/grub/i386/pc/serial.h
--- grub2/include/grub/i386/pc/serial.h 1970-01-01 00:00:00.000000000 +0000
+++ grub2.newserial/include/grub/i386/pc/serial.h 2005-02-20 17:43:42.000000000 +0000
@@ -0,0 +1,85 @@
+/* serial.h - serial device interface */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_SERIAL_MACHINE_HEADER
+#define GRUB_SERIAL_MACHINE_HEADER 1
+
+/* Macros. */
+
+/* The offsets of UART registers. */
+#define UART_TX 0
+#define UART_RX 0
+#define UART_DLL 0
+#define UART_IER 1
+#define UART_DLH 1
+#define UART_IIR 2
+#define UART_FCR 2
+#define UART_LCR 3
+#define UART_MCR 4
+#define UART_LSR 5
+#define UART_MSR 6
+#define UART_SR 7
+
+/* For LSR bits. */
+#define UART_DATA_READY 0x01
+#define UART_EMPTY_TRANSMITTER 0x20
+
+/* The type of parity. */
+#define UART_NO_PARITY 0x00
+#define UART_ODD_PARITY 0x08
+#define UART_EVEN_PARITY 0x18
+
+/* The type of word length. */
+#define UART_5BITS_WORD 0x00
+#define UART_6BITS_WORD 0x01
+#define UART_7BITS_WORD 0x02
+#define UART_8BITS_WORD 0x03
+
+/* The type of the length of stop bit. */
+#define UART_1_STOP_BIT 0x00
+#define UART_2_STOP_BITS 0x04
+
+/* the switch of DLAB. */
+#define UART_DLAB 0x80
+
+/* Enable the FIFO. */
+#define UART_ENABLE_FIFO 0xC7
+
+/* Turn on DTR, RTS, and OUT2. */
+#define UART_ENABLE_MODEM 0x0B
+
+\f
+/* Function prototypes. */
+
+/* Return the port number for the UNITth serial device. */
+unsigned short serial_hw_get_port (int unit);
+
+/* Initialize a serial device. */
+int serial_hw_init (void);
+
+int fill_input_buf (int nowait);
+
+int grub_serial_getkey (void);
+
+int grub_serial_checkkey (void);
+
+void grub_setup_defaults (void);
+
+#endif /* ! GRUB_SERIAL_MACHINE_HEADER */
diff -uNr grub2/include/grub/terminfo.h grub2.newserial/include/grub/terminfo.h
--- grub2/include/grub/terminfo.h 1970-01-01 00:00:00.000000000 +0000
+++ grub2.newserial/include/grub/terminfo.h 2005-02-20 17:45:33.000000000 +0000
@@ -0,0 +1,53 @@
+/* terminfo.h - read a terminfo entry from the command line */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_TERMCAP_HEADER
+#define GRUB_TERMCAP_HEADER 1
+
+#define TERMINFO_LEN 40
+
+typedef struct terminfo
+{
+ char name[TERMINFO_LEN];
+ char cursor_address[TERMINFO_LEN];
+ char clear_screen[TERMINFO_LEN];
+ char enter_standout_mode[TERMINFO_LEN];
+ char exit_standout_mode[TERMINFO_LEN];
+}
+terminfo;
+
+\f
+/* Function prototypes. */
+char *ti_escape_memory (const char *in, const char *end);
+char *ti_escape_string (const char *in);
+char *ti_unescape_memory (const char *in, const char *end);
+char *ti_unescape_string (const char *in);
+
+void ti_set_term (const struct terminfo *new);
+void ti_get_term (struct terminfo *copy);
+
+void ti_cursor_address (int x, int y);
+void ti_clear_screen (void);
+void ti_enter_standout_mode (void);
+void ti_exit_standout_mode (void);
+void ti_cursor_on (void);
+void ti_cursor_off (void);
+
+#endif /* ! GRUB_TERMCAP_HEADER */
diff -uNr grub2/include/grub/tparm.h grub2.newserial/include/grub/tparm.h
--- grub2/include/grub/tparm.h 1970-01-01 00:00:00.000000000 +0000
+++ grub2.newserial/include/grub/tparm.h 2005-02-20 17:46:09.000000000 +0000
@@ -0,0 +1,28 @@
+/* tparm.h - parameter formatting of terminfo */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_TPARM_HEADER
+#define GRUB_TPARM_HEADER 1
+
+\f
+/* Function prototypes. */
+char *grub_tparm (const char *string, ...);
+
+#endif /* ! GRUB_TERMCAP_HEADER */
diff -uNr grub2/term/i386/pc/serial.c grub2.newserial/term/i386/pc/serial.c
--- grub2/term/i386/pc/serial.c 1970-01-01 00:00:00.000000000 +0000
+++ grub2.newserial/term/i386/pc/serial.c 2005-02-20 18:00:43.000000000 +0000
@@ -0,0 +1,592 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/machine/serial.h>
+#include <grub/machine/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/arg.h>
+#include <grub/terminfo.h>
+
+#define DEBUG_SERIAL 0
+
+#define TEXT_WIDTH 80
+#define TEXT_HEIGHT 25
+
+
+static grub_dl_t my_mod;
+static unsigned xpos, ypos;
+static int cursor_state = 1;
+static int keep_track = 1;
+
+/* An input buffer. */
+static char input_buf[8];
+static unsigned int npending = 0;
+
+/* Argument options. */
+static const struct grub_arg_option options[] =
+{
+ {"port", 'p', 0, "Set the serial port", 0, ARG_TYPE_INT},
+ {"address", 'a', 0, "Set the serial port address", 0, ARG_TYPE_STRING},
+ {"speed", 's', 0, "Set the serial port speed", 0, ARG_TYPE_INT},
+ {"word", 'w', 0, "Set the serial port word length", 0, ARG_TYPE_INT},
+ {"parity", 'r', 0, "Set the serial port parity", 0, ARG_TYPE_STRING},
+ {"stop", 't', 0, "Set the serial port stop bits", 0, ARG_TYPE_INT},
+ {0, 0, 0, 0, 0, 0}
+};
+
+/* Serial port settings. */
+struct serial_port
+{
+ unsigned short port;
+ unsigned int speed;
+ int word_len;
+ int parity;
+ int stop_bit_len;
+};
+
+/* The structure for speed vs. divisor. */
+struct divisor
+{
+ unsigned int speed;
+ unsigned short div;
+};
+
+/* Store the serial port settings. */
+static struct serial_port serial_settings;
+
+/* Store the port number of a serial unit. */
+static unsigned short serial_hw_port = 0;
+
+/* The table which lists common configurations. */
+/* 1843200 / (speed * 16) */
+static struct divisor divisor_tab[] =
+{
+ { 2400, 0x0030 },
+ { 4800, 0x0018 },
+ { 9600, 0x000C },
+ { 19200, 0x0006 },
+ { 38400, 0x0003 },
+ { 57600, 0x0002 },
+ { 115200, 0x0001 },
+};
+
+static grub_err_t
+grub_cmd_serial (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ unsigned short port;
+ unsigned int speed;
+ int word_len, parity, stop_bit_len;
+
+ if (serial_settings.port == 0)
+ grub_setup_defaults ();
+
+ /* Load current settings. */
+ port = serial_settings.port;
+ speed = serial_settings.speed;
+ word_len = serial_settings.word_len;
+ parity = serial_settings.parity;
+ stop_bit_len = serial_settings.stop_bit_len;
+
+ /* TODO parse cmd line parameters and validate. */
+
+ /* Save current settings. */
+ serial_settings.port = port;
+ serial_settings.speed = speed;
+ serial_settings.word_len = word_len;
+ serial_settings.parity = parity;
+ serial_settings.stop_bit_len = stop_bit_len;
+
+ serial_hw_init ();
+
+ return GRUB_ERR_NONE;
+}
+
+/* Read a byte from a port. */
+static inline unsigned char
+inb (unsigned short port)
+{
+ unsigned char value;
+
+ asm volatile ("inb %w1, %0" : "=a" (value) : "Nd" (port));
+ asm volatile ("outb %%al, $0x80" : : );
+
+ return value;
+}
+
+/* Write a byte to a port. */
+static inline void
+outb (unsigned short port, unsigned char value)
+{
+ asm volatile ("outb %b0, %w1" : : "a" (value), "Nd" (port));
+ asm volatile ("outb %%al, $0x80" : : );
+}
+
+/* Fetch a key. */
+static int
+serial_hw_fetch (void)
+{
+ if (inb (serial_hw_port + UART_LSR) & UART_DATA_READY)
+ return inb (serial_hw_port + UART_RX);
+
+ return -1;
+}
+
+/* Put a chararacter. */
+static void
+serial_hw_put (int c)
+{
+ int timeout = 100000;
+
+ /* Wait until the transmitter holding register is empty. */
+ while ((inb (serial_hw_port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0)
+ {
+ if (--timeout == 0)
+ /* There is something wrong. But what can I do? */
+ return;
+ }
+
+ outb (serial_hw_port + UART_TX, c);
+}
+
+/* Return the port number for the UNITth serial device. */
+unsigned short
+serial_hw_get_port (int unit)
+{
+ /* The BIOS data area. */
+ const unsigned short *addr = (const unsigned short *) 0x0400;
+
+ return addr[unit];
+}
+
+/* Initialize a serial device. PORT is the port number for a serial device.
+ SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600,
+ 19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used
+ for the device. Likewise, PARITY is the type of the parity and
+ STOP_BIT_LEN is the length of the stop bit. The possible values for
+ WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as
+ macros. */
+int
+serial_hw_init (void)
+{
+ unsigned int i;
+ unsigned short port;
+ unsigned short div = 0;
+ unsigned char status = 0;
+
+ /* Select the port. */
+ port = serial_settings.port;
+
+ /* Turn off the interupt. */
+ outb (port + UART_IER, 0);
+
+ /* Set DLAB. */
+ outb (port + UART_LCR, UART_DLAB);
+
+ /* Set the baud rate. */
+ for (i = 0; i < sizeof (divisor_tab) / sizeof (divisor_tab[0]); i++)
+ if (divisor_tab[i].speed == serial_settings.speed)
+ {
+ div = divisor_tab[i].div;
+ break;
+ }
+
+ if (div == 0)
+ return 0;
+
+ outb (port + UART_DLL, div & 0xFF);
+ outb (port + UART_DLH, div >> 8 );
+
+ /* Set the line status. */
+ status |= serial_settings.parity
+ | serial_settings.word_len
+ | serial_settings.stop_bit_len;
+ outb (port + UART_LCR, status);
+
+ /* Enable the FIFO. */
+ outb (port + UART_FCR, UART_ENABLE_FIFO);
+
+ /* Turn on DTR, RTS, and OUT2. */
+ outb (port + UART_MCR, UART_ENABLE_MODEM);
+
+ /* Store the port number. */
+ serial_hw_port = port;
+
+ /* Drain the input buffer. */
+ while (grub_serial_checkkey () != -1)
+ (void) grub_serial_getkey ();
+
+ cursor_state = 1;
+
+ /* FIXME: should check if the serial terminal was found. */
+
+ return 1;
+}
+
+static void
+serial_translate_key_sequence (void)
+{
+ const struct
+ {
+ char key;
+ char ascii;
+ }
+ three_code_table[] =
+ {
+ {'A', 16},
+ {'B', 14},
+ {'C', 6},
+ {'D', 2},
+ {'F', 5},
+ {'H', 1},
+ {'4', 4}
+ };
+
+ const struct
+ {
+ short key;
+ char ascii;
+ }
+ four_code_table[] =
+ {
+ {('1' | ('~' << 8)), 1},
+ {('3' | ('~' << 8)), 4},
+ {('5' | ('~' << 8)), 7},
+ {('6' | ('~' << 8)), 3}
+ };
+
+ /* The buffer must start with ``ESC [''. */
+ if (*((unsigned short *) input_buf) != ('\e' | ('[' << 8)))
+ return;
+
+ if (npending >= 3)
+ {
+ unsigned int i;
+
+ for (i = 0; i < sizeof (three_code_table) / sizeof (three_code_table[0]); i++)
+ if (three_code_table[i].key == input_buf[2])
+ {
+ input_buf[0] = three_code_table[i].ascii;
+ npending -= 2;
+ grub_memmove (input_buf + 1, input_buf + 3, npending - 1);
+ return;
+ }
+ }
+
+ if (npending >= 4)
+ {
+ unsigned int i;
+ short key = *((short *) (input_buf + 2));
+
+ for (i = 0; i < sizeof (four_code_table) / sizeof (four_code_table[0]); i++)
+ if (four_code_table[i].key == key)
+ {
+ input_buf[0] = four_code_table[i].ascii;
+ npending -= 3;
+ grub_memmove (input_buf + 1, input_buf + 4, npending - 1);
+ return;
+ }
+ }
+}
+
+int
+fill_input_buf (int nowait)
+{
+ int i;
+
+ for (i = 0; i < 10000 && npending < sizeof (input_buf); i++)
+ {
+ int c;
+
+ c = serial_hw_fetch ();
+ if (c >= 0)
+ {
+ input_buf[npending++] = c;
+
+ /* Reset the counter to zero, to wait for the same interval. */
+ i = 0;
+ }
+
+ if (nowait)
+ break;
+ }
+
+ /* Translate some key sequences. */
+ serial_translate_key_sequence ();
+
+ return npending;
+}
+
+/* Setup serial port defaults. */
+void
+grub_setup_defaults (void)
+{
+ serial_settings.port = serial_hw_get_port (0);
+ serial_settings.speed = 9600;
+ serial_settings.word_len = UART_8BITS_WORD;
+ serial_settings.parity = UART_NO_PARITY;
+ serial_settings.stop_bit_len = UART_1_STOP_BIT;
+}
+
+static grub_err_t
+grub_serial_init (void)
+{
+ if (serial_settings.port == 0)
+ {
+ grub_setup_defaults ();
+ serial_hw_init ();
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/* The serial version of getkey. */
+int
+grub_serial_getkey (void)
+{
+ int c;
+
+ while (! fill_input_buf (0))
+ ;
+
+ c = input_buf[0];
+ npending--;
+ grub_memmove (input_buf, input_buf + 1, npending);
+
+ return c;
+}
+
+/* The serial version of checkkey. */
+int
+grub_serial_checkkey (void)
+{
+ if (fill_input_buf (1))
+ return input_buf[0];
+
+ return -1;
+}
+
+/* The serial version of putchar. */
+static void
+grub_serial_putchar (grub_uint32_t c)
+{
+#if DEBUG_SERIAL
+ static int show = 1;
+#endif
+
+ /* Keep track of the cursor. */
+ if (keep_track)
+ {
+ /* The serial terminal does not have VGA fonts. */
+ if (c > 0x7F)
+ {
+ /* Better than nothing. */
+ switch (c)
+ {
+ case GRUB_TERM_DISP_LEFT:
+ c = '<';
+ break;
+
+ case GRUB_TERM_DISP_UP:
+ c = '^';
+ break;
+
+ case GRUB_TERM_DISP_RIGHT:
+ c = '>';
+ break;
+
+ case GRUB_TERM_DISP_DOWN:
+ c = 'v';
+ break;
+
+ case GRUB_TERM_DISP_HLINE:
+ c = '-';
+ break;
+
+ case GRUB_TERM_DISP_VLINE:
+ c = '|';
+ break;
+
+ case GRUB_TERM_DISP_UL:
+ case GRUB_TERM_DISP_UR:
+ case GRUB_TERM_DISP_LL:
+ case GRUB_TERM_DISP_LR:
+ c = '+';
+ break;
+
+ default:
+ break;
+ }
+ }
+ switch (c)
+ {
+ case '\a':
+ break;
+
+ case '\b':
+ case 127:
+ if (xpos > 0)
+ xpos--;
+ break;
+
+ case '\n':
+ if (ypos < TEXT_HEIGHT)
+ ypos++;
+ break;
+
+ case '\r':
+ xpos = 0;
+ break;
+
+ default:
+ if (xpos >= TEXT_WIDTH)
+ {
+ grub_putchar ('\r');
+ grub_putchar ('\n');
+ }
+ xpos++;
+ break;
+ }
+ }
+ serial_hw_put (c);
+
+#if DEBUG_SERIAL
+ if (show)
+ {
+ grub_uint16_t pos = grub_getxy ();
+
+ show = 0;
+ grub_gotoxy (0, 0);
+ grub_printf ("[%u:%u]", (unsigned) (pos >> 8), (unsigned) (pos & 0xff));
+ grub_gotoxy (pos >> 8, pos & 0xff);
+ show = 1;
+ }
+#endif
+}
+
+static grub_uint16_t
+grub_serial_getxy (void)
+{
+ return ((xpos << 8) | ypos);
+}
+
+static void
+grub_serial_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+ if (x > TEXT_WIDTH || y > TEXT_HEIGHT)
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)",
+ (unsigned) x, (unsigned) y);
+ return;
+ }
+
+ keep_track = 0;
+ ti_cursor_address (x,y);
+ keep_track = 1;
+
+ xpos = x;
+ ypos = y;
+}
+
+static void
+grub_serial_cls (void)
+{
+ keep_track = 0;
+ ti_clear_screen ();
+ keep_track = 1;
+
+ xpos = ypos = 0;
+}
+
+static void
+grub_serial_setcolorstate (grub_term_color_state state)
+{
+ keep_track = 0;
+ switch (state)
+ {
+ case GRUB_TERM_COLOR_STANDARD:
+ case GRUB_TERM_COLOR_NORMAL:
+ ti_exit_standout_mode ();
+ break;
+ case GRUB_TERM_COLOR_HIGHLIGHT:
+ ti_enter_standout_mode ();
+ break;
+ default:
+ break;
+ }
+ keep_track = 1;
+}
+
+static void
+grub_serial_setcolor (grub_uint8_t normal_color __attribute__ ((unused)),
+ grub_uint8_t highlight_color __attribute__ ((unused)))
+{
+ /* FIXME */
+}
+
+static void
+grub_serial_setcursor (int new_state)
+{
+ if (cursor_state != new_state)
+ {
+ if (cursor_state)
+ ti_cursor_off ();
+ else
+ ti_cursor_on ();
+ cursor_state = new_state;
+ }
+}
+
+static struct grub_term grub_serial_term =
+{
+ .name = "serial",
+ .init = grub_serial_init,
+ .fini = 0,
+ .putchar = grub_serial_putchar,
+ .checkkey = grub_serial_checkkey,
+ .getkey = grub_serial_getkey,
+ .getxy = grub_serial_getxy,
+ .gotoxy = grub_serial_gotoxy,
+ .cls = grub_serial_cls,
+ .setcolorstate = grub_serial_setcolorstate,
+ .setcolor = grub_serial_setcolor,
+ .setcursor = grub_serial_setcursor,
+ .flags = 0,
+ .next = 0
+};
+
+\f
+
+GRUB_MOD_INIT
+{
+ my_mod = mod;
+ grub_register_command ("serial", grub_cmd_serial, GRUB_COMMAND_FLAG_BOTH,
+ "serial [OPTIONS...]", "Configure serial port.", options);
+ grub_term_register (&grub_serial_term);
+}
+
+GRUB_MOD_FINI
+{
+ grub_unregister_command ("serial");
+ grub_term_unregister (&grub_serial_term);
+}
diff -uNr grub2/term/terminfo.c grub2.newserial/term/terminfo.c
--- grub2/term/terminfo.c 1970-01-01 00:00:00.000000000 +0000
+++ grub2.newserial/term/terminfo.c 2005-02-20 17:49:05.000000000 +0000
@@ -0,0 +1,279 @@
+/* terminfo.c - read a terminfo entry from the command line */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2004 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * ######################################################################
+ *
+ * This file contains various functions dealing with different
+ * terminal capabilities. It knows the difference between a vt52 and vt100
+ * terminal (and much more) and is mainly used the terminal emulation
+ * in the serial driver.
+ */
+
+#include <grub/misc.h>
+#include <grub/terminfo.h>
+#include <grub/tparm.h>
+#include <grub/machine/serial.h>
+
+/* Current terminal capabilities. Default is "vt100". */
+struct terminfo term =
+ {
+ .name = "vt100",
+ .cursor_address = "\e[%i%p1%d;%p2%dH",
+ .clear_screen = "\e[H\e[J",
+ .enter_standout_mode = "\e[7m",
+ .exit_standout_mode = "\e[m"
+ };
+
+/* A number of escape sequences are provided in the string valued
+ capabilities for easy encoding of characters there. Both \E and \e
+ map to an ESCAPE character, ^x maps to a control-x for any
+ appropriate x, and the sequences \n \l \r \t \b \f \s give a
+ newline, line-feed, return, tab, backspace, form-feed, and space.
+ Other escapes include \^ for ^, \\ for \, \, for comma, \: for :,
+ and \0 for null. (\0 will produce \200, which does not terminate a
+ string but behaves as a null character on most terminals, provid
+ ing CS7 is specified. See stty(1).) Finally, characters may be
+ given as three octal digits after a \. */
+
+void putstr (const char *str)
+{
+ while (*str)
+ grub_putchar (*str++);
+}
+
+char *
+ti_unescape_memory (const char *in, const char *end)
+{
+ static char out_buffer[256];
+ char c;
+ char *out;
+
+ out = out_buffer;
+ do
+ {
+ c = *(in++);
+ switch (c)
+ {
+ case '^':
+ if (*in >= 'A' && *in <= 'Z')
+ {
+ *out = (*in) - 'A';
+ in++;
+ }
+ else
+ {
+ *out = '^';
+ }
+ break;
+ case '\\':
+ c = *(in++);
+ if (c >= '0' && c <= '9')
+ {
+ // octal number
+ int n = 0;
+ do
+ {
+ n = (n << 4) | (c - '0');
+ c = *(in++);
+ }
+ while (c >= '0' && c <= '9');
+
+ *out++ = (char)(n & 0xff);
+
+ // redo last character
+ in--;
+
+ break;
+ }
+
+ switch (c)
+ {
+ case 'e':
+ case 'E':
+ *out++ = '\e';
+ break;
+ case 'n':
+ *out++ = '\n';
+ break;
+ case 'r':
+ *out++ = '\r';
+ break;
+ case 't':
+ *out++ = '\t';
+ break;
+ case 'b':
+ *out++ = '\b';
+ break;
+ case 'f':
+ *out++ = '\f';
+ break;
+ case 's':
+ *out++ = ' ';
+ break;
+ case '\\':
+ *out++ = '\\';
+ break;
+ case '^':
+ *out++ = '^';
+ break;
+ case ',':
+ *out++ = ',';
+ break;
+ case ':':
+ *out++ = ':';
+ break;
+ case '0':
+ *out++ = '\200';
+ break;
+ }
+ break;
+ default:
+ *out++ = c;
+ break;
+ }
+ }
+ while (in <= end);
+
+ return out_buffer;
+}
+
+char *
+ti_unescape_string (const char *in)
+{
+ return ti_unescape_memory (in, in + grub_strlen (in));
+}
+
+/* convert a memory region containing binary character into an external
+ * ascii representation. The binary characters will be replaced by an
+ * "ecsape notation". E.g. "033" will become "\e". */
+char *
+ti_escape_memory (const char *in, const char *end)
+{
+ static char out_buffer[256];
+ char c;
+ char *out;
+
+ out = out_buffer;
+ do
+ {
+ c = *(in++);
+ switch (c)
+ {
+ case '\e':
+ *out++ = '\\'; *out++ = 'e'; break;
+ case ' ':
+ *out++ = '\\'; *out++ = 's'; break;
+ case '\\':
+ *out++ = '\\'; *out++ = '\\'; break;
+ case '0' ... '9':
+ case 'a' ... 'z':
+ case 'A' ... 'Z':
+ case '%':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case ';':
+ case ':':
+ case '{':
+ case '}':
+ case '[':
+ case ']':
+ *out++ = c; break;
+ case 0 ... 25:
+ *out++ = '^'; *out++ = 'A' + c; break;
+ default:
+ *out++ = '\\';
+ *out++ = ((c >> 8) & 7) + '0';
+ *out++ = ((c >> 4) & 7) + '0';
+ *out++ = ((c >> 0) & 7) + '0';
+ break;
+ }
+ }
+ while (in < end);
+
+ *out++ = 0;
+
+ return out_buffer;
+}
+
+/* convert a string containing binary character into an external ascii
+ * representation. */
+char *
+ti_escape_string (const char *in)
+{
+ return ti_escape_memory (in, in + grub_strlen (in));
+}
+
+/* move the cursor to the given position starting with "0". */
+void
+ti_cursor_address (int x, int y)
+{
+ putstr (grub_tparm (term.cursor_address, y, x));
+}
+
+/* clear the screen. */
+void
+ti_clear_screen (void)
+{
+ putstr (grub_tparm (term.clear_screen));
+}
+
+/* enter reverse video */
+void
+ti_enter_standout_mode (void)
+{
+ putstr (grub_tparm (term.enter_standout_mode));
+}
+
+/* exit reverse video */
+void
+ti_exit_standout_mode (void)
+{
+ putstr (grub_tparm (term.exit_standout_mode));
+}
+
+/* set the current terminal emulation to use */
+void
+ti_set_term (const struct terminfo *new)
+{
+ grub_memmove (&term, new, sizeof (struct terminfo));
+}
+
+/* get the current terminal emulation */
+void
+ti_get_term(struct terminfo *copy)
+{
+ grub_memmove (copy, &term, sizeof (struct terminfo));
+}
+
+/* cursor on */
+void
+ti_cursor_on(void)
+{
+ putstr (grub_tparm ("\e[?25l"));
+}
+
+/* cursor off */
+void
+ti_cursor_off(void)
+{
+ putstr (grub_tparm ("\e[?25h"));
+}
+
diff -uNr grub2/term/tparm.c grub2.newserial/term/tparm.c
--- grub2/term/tparm.c 1970-01-01 00:00:00.000000000 +0000
+++ grub2.newserial/term/tparm.c 2005-02-20 17:49:13.000000000 +0000
@@ -0,0 +1,725 @@
+/****************************************************************************
+ * Copyright (c) 1998,2000,2002 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), to deal in the Software without restriction, including *
+ * without limitation the rights to use, copy, modify, merge, publish, *
+ * distribute, distribute with modifications, sublicense, and/or sell *
+ * copies of the Software, and to permit persons to whom the Software is *
+ * furnished to do so, subject to the following conditions: *
+ * *
+ * The above copyright notice and this permission notice shall be included *
+ * in all copies or substantial portions of the Software. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+ * *
+ * Except as contained in this notice, the name(s) of the above copyright *
+ * holders shall not be used in advertising or otherwise to promote the *
+ * sale, use or other dealings in this Software without prior written *
+ * authorization. *
+ ****************************************************************************/
+
+/**********************************************************************
+ * This code is a modification of lib_tparm.c found in ncurses-5.2. The
+ * modification are for use in grub by replacing all libc function through
+ * special grub functions. This also meant to delete all dynamic memory
+ * allocation and replace it by a number of fixed buffers.
+ *
+ * Modifications by Tilmann Bubeck <t.bubeck@reinform.de> 2002
+ **********************************************************************/
+
+/****************************************************************************
+ * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ ****************************************************************************/
+
+/*
+ * tparm.c
+ *
+ */
+
+#include <grub/misc.h>
+#include <grub/tparm.h>
+
+/*
+ * Common/troublesome character definitions
+ */
+typedef char grub_bool;
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+#ifndef FALSE
+# define FALSE (0)
+#endif
+#ifndef TRUE
+# define TRUE (!FALSE)
+#endif
+#define MAX_FORMAT_LEN 256
+#define max(a,b) ((a) > (b) ? (a) : (b))
+
+//MODULE_ID("$Id: tparm.c,v 1.1 2002/11/29 20:39:24 okuji Exp $")
+
+/*
+ * char *
+ * tparm(string, ...)
+ *
+ * Substitute the given parameters into the given string by the following
+ * rules (taken from terminfo(5)):
+ *
+ * Cursor addressing and other strings requiring parame-
+ * ters in the terminal are described by a parameterized string
+ * capability, with like escapes %x in it. For example, to
+ * address the cursor, the cup capability is given, using two
+ * parameters: the row and column to address to. (Rows and
+ * columns are numbered from zero and refer to the physical
+ * screen visible to the user, not to any unseen memory.) If
+ * the terminal has memory relative cursor addressing, that can
+ * be indicated by
+ *
+ * The parameter mechanism uses a stack and special %
+ * codes to manipulate it. Typically a sequence will push one
+ * of the parameters onto the stack and then print it in some
+ * format. Often more complex operations are necessary.
+ *
+ * The % encodings have the following meanings:
+ *
+ * %% outputs `%'
+ * %c print pop() like %c in printf()
+ * %s print pop() like %s in printf()
+ * %[[:]flags][width[.precision]][doxXs]
+ * as in printf, flags are [-+#] and space
+ * The ':' is used to avoid making %+ or %-
+ * patterns (see below).
+ *
+ * %p[1-9] push ith parm
+ * %P[a-z] set dynamic variable [a-z] to pop()
+ * %g[a-z] get dynamic variable [a-z] and push it
+ * %P[A-Z] set static variable [A-Z] to pop()
+ * %g[A-Z] get static variable [A-Z] and push it
+ * %l push strlen(pop)
+ * %'c' push char constant c
+ * %{nn} push integer constant nn
+ *
+ * %+ %- %* %/ %m
+ * arithmetic (%m is mod): push(pop() op pop())
+ * %& %| %^ bit operations: push(pop() op pop())
+ * %= %> %< logical operations: push(pop() op pop())
+ * %A %O logical and & or operations for conditionals
+ * %! %~ unary operations push(op pop())
+ * %i add 1 to first two parms (for ANSI terminals)
+ *
+ * %? expr %t thenpart %e elsepart %;
+ * if-then-else, %e elsepart is optional.
+ * else-if's are possible ala Algol 68:
+ * %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %;
+ *
+ * For those of the above operators which are binary and not commutative,
+ * the stack works in the usual way, with
+ * %gx %gy %m
+ * resulting in x mod y, not the reverse.
+ */
+
+#define STACKSIZE 20
+
+typedef struct {
+ union {
+ unsigned int num;
+ char *str;
+ } data;
+ grub_bool num_type;
+} stack_frame;
+
+static stack_frame stack[STACKSIZE];
+static int stack_ptr;
+
+static char out_buff[256];
+static int out_size = 256;
+static int out_used;
+
+static inline void
+get_space(int need)
+{
+ need += out_used;
+ if (need > out_size) {
+ // FIX ME! buffer full, what now?
+ ;
+ }
+}
+
+static inline void
+save_text(const char *fmt, const char *s, int len)
+{
+ int s_len = grub_strlen(s);
+ if (len > (int) s_len)
+ s_len = len;
+
+ get_space(s_len + 1);
+
+ (void) grub_sprintf(out_buff + out_used, fmt, s);
+ out_used += grub_strlen(out_buff + out_used);
+}
+
+static inline void
+save_number(const char *fmt, int number, int len)
+{
+ if (len < 30)
+ len = 30; /* actually log10(MAX_INT)+1 */
+
+ get_space(len + 1);
+
+ (void) grub_sprintf(out_buff + out_used, fmt, number);
+ out_used += grub_strlen(out_buff + out_used);
+}
+
+static inline void
+save_char(int c)
+{
+ if (c == 0)
+ c = 0200;
+ get_space(1);
+ out_buff[out_used++] = c;
+}
+
+static inline void
+npush(int x)
+{
+ if (stack_ptr < STACKSIZE) {
+ stack[stack_ptr].num_type = TRUE;
+ stack[stack_ptr].data.num = x;
+ stack_ptr++;
+ }
+}
+
+static inline int
+npop(void)
+{
+ int result = 0;
+ if (stack_ptr > 0) {
+ stack_ptr--;
+ if (stack[stack_ptr].num_type)
+ result = stack[stack_ptr].data.num;
+ }
+ return result;
+}
+
+static inline void
+spush(char *x)
+{
+ if (stack_ptr < STACKSIZE) {
+ stack[stack_ptr].num_type = FALSE;
+ stack[stack_ptr].data.str = x;
+ stack_ptr++;
+ }
+}
+
+static inline char *
+spop(void)
+{
+ static char dummy[] = ""; /* avoid const-cast */
+ char *result = dummy;
+ if (stack_ptr > 0) {
+ stack_ptr--;
+ if (!stack[stack_ptr].num_type && stack[stack_ptr].data.str != 0)
+ result = stack[stack_ptr].data.str;
+ }
+ return result;
+}
+
+static inline const char *
+parse_format(const char *s, char *format, int *len)
+{
+ grub_bool done = FALSE;
+ grub_bool allowminus = FALSE;
+ grub_bool dot = FALSE;
+ grub_bool err = FALSE;
+ char *fmt = format;
+ int prec = 0;
+ int width = 0;
+ int value = 0;
+
+ *len = 0;
+ *format++ = '%';
+ while (*s != '\0' && !done) {
+ switch (*s) {
+ case 'c': /* FALLTHRU */
+ case 'd': /* FALLTHRU */
+ case 'o': /* FALLTHRU */
+ case 'x': /* FALLTHRU */
+ case 'X': /* FALLTHRU */
+ case 's':
+ *format++ = *s;
+ done = TRUE;
+ break;
+ case '.':
+ *format++ = *s++;
+ if (dot) {
+ err = TRUE;
+ } else {
+ dot = TRUE;
+ prec = value;
+ }
+ value = 0;
+ break;
+ case '#':
+ *format++ = *s++;
+ break;
+ case ' ':
+ *format++ = *s++;
+ break;
+ case ':':
+ s++;
+ allowminus = TRUE;
+ break;
+ case '-':
+ if (allowminus) {
+ *format++ = *s++;
+ } else {
+ done = TRUE;
+ }
+ break;
+ default:
+ if (isdigit(*s)) {
+ value = (value * 10) + (*s - '0');
+ if (value > 10000)
+ err = TRUE;
+ *format++ = *s++;
+ } else {
+ done = TRUE;
+ }
+ }
+ }
+
+ /*
+ * If we found an error, ignore (and remove) the flags.
+ */
+ if (err) {
+ prec = width = value = 0;
+ format = fmt;
+ *format++ = '%';
+ *format++ = *s;
+ }
+
+ if (dot)
+ width = value;
+ else
+ prec = value;
+
+ *format = '\0';
+ /* return maximum string length in print */
+ *len = (prec > width) ? prec : width;
+ return s;
+}
+
+#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z')
+#define isLOWER(c) ((c) >= 'a' && (c) <= 'z')
+
+static inline char *
+tparam_internal(const char *string, int *dataptr)
+{
+#define NUM_VARS 26
+ char *p_is_s[9];
+ int param[9];
+ int lastpop;
+ int popcount;
+ int number;
+ int len;
+ int level;
+ int x, y;
+ int i;
+ int len2;
+ register const char *cp;
+ static int len_fmt = MAX_FORMAT_LEN;
+ static char dummy[] = "";
+ static char format[MAX_FORMAT_LEN];
+ static int dynamic_var[NUM_VARS];
+ static int static_vars[NUM_VARS];
+
+ out_used = 0;
+ if (string == 0)
+ return 0;
+
+ if ((len2 = grub_strlen(string)) > len_fmt) {
+ return 0;
+ }
+
+ /*
+ * Find the highest parameter-number referred to in the format string.
+ * Use this value to limit the number of arguments copied from the
+ * variable-length argument list.
+ */
+
+ number = 0;
+ lastpop = -1;
+ popcount = 0;
+ grub_memset(p_is_s, 0, sizeof(p_is_s));
+
+ /*
+ * Analyze the string to see how many parameters we need from the varargs
+ * list, and what their types are. We will only accept string parameters
+ * if they appear as a %l or %s format following an explicit parameter
+ * reference (e.g., %p2%s). All other parameters are numbers.
+ *
+ * 'number' counts coarsely the number of pop's we see in the string, and
+ * 'popcount' shows the highest parameter number in the string. We would
+ * like to simply use the latter count, but if we are reading termcap
+ * strings, there may be cases that we cannot see the explicit parameter
+ * numbers.
+ */
+ for (cp = string; (cp - string) < (int) len2;) {
+ if (*cp == '%') {
+ cp++;
+ cp = parse_format(cp, format, &len);
+ switch (*cp) {
+ default:
+ break;
+
+ case 'd': /* FALLTHRU */
+ case 'o': /* FALLTHRU */
+ case 'x': /* FALLTHRU */
+ case 'X': /* FALLTHRU */
+ case 'c': /* FALLTHRU */
+ number++;
+ lastpop = -1;
+ break;
+
+ case 'l':
+ case 's':
+ if (lastpop > 0)
+ p_is_s[lastpop - 1] = dummy;
+ ++number;
+ break;
+
+ case 'p':
+ cp++;
+ i = (*cp - '0');
+ if (i >= 0 && i <= 9) {
+ lastpop = i;
+ if (lastpop > popcount)
+ popcount = lastpop;
+ }
+ break;
+
+ case 'P':
+ case 'g':
+ cp++;
+ break;
+
+ case '\'':
+ cp += 2;
+ lastpop = -1;
+ break;
+
+ case '{':
+ cp++;
+ while (*cp >= '0' && *cp <= '9') {
+ cp++;
+ }
+ break;
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case 'm':
+ case 'A':
+ case 'O':
+ case '&':
+ case '|':
+ case '^':
+ case '=':
+ case '<':
+ case '>':
+ case '!':
+ case '~':
+ lastpop = -1;
+ number += 2;
+ break;
+
+ case 'i':
+ lastpop = -1;
+ if (popcount < 2)
+ popcount = 2;
+ break;
+ }
+ }
+ if (*cp != '\0')
+ cp++;
+ }
+
+ if (number > 9)
+ number = 9;
+ for (i = 0; i < max(popcount, number); i++) {
+ /*
+ * A few caps (such as plab_norm) have string-valued parms.
+ * We'll have to assume that the caller knows the difference, since
+ * a char* and an int may not be the same size on the stack.
+ */
+ if (p_is_s[i] != 0) {
+ p_is_s[i] = (char *)(*(dataptr++));
+ } else {
+ param[i] = (int)(*(dataptr++));
+ }
+ }
+
+ /*
+ * This is a termcap compatibility hack. If there are no explicit pop
+ * operations in the string, load the stack in such a way that
+ * successive pops will grab successive parameters. That will make
+ * the expansion of (for example) \E[%d;%dH work correctly in termcap
+ * style, which means tparam() will expand termcap strings OK.
+ */
+ stack_ptr = 0;
+ if (popcount == 0) {
+ popcount = number;
+ for (i = number - 1; i >= 0; i--)
+ npush(param[i]);
+ }
+
+ while (*string) {
+ /* skip delay timings */
+ if (*string == '$' && *(string + 1) == '<') {
+ while( *string && *string != '>')
+ string++;
+ if ( *string == '>' ) string++;
+ } else if ( *string == '%') {
+ string++;
+ string = parse_format(string, format, &len);
+ switch (*string) {
+ default:
+ break;
+ case '%':
+ save_char('%');
+ break;
+
+ case 'd': /* FALLTHRU */
+ case 'o': /* FALLTHRU */
+ case 'x': /* FALLTHRU */
+ case 'X': /* FALLTHRU */
+ case 'c': /* FALLTHRU */
+ save_number(format, npop(), len);
+ break;
+
+ case 'l':
+ save_number("%d", grub_strlen(spop()), 0);
+ break;
+
+ case 's':
+ save_text(format, spop(), len);
+ break;
+
+ case 'p':
+ string++;
+ i = (*string - '1');
+ if (i >= 0 && i < 9) {
+ if (p_is_s[i])
+ spush(p_is_s[i]);
+ else
+ npush(param[i]);
+ }
+ break;
+
+ case 'P':
+ string++;
+ if (isUPPER(*string)) {
+ i = (*string - 'A');
+ static_vars[i] = npop();
+ } else if (isLOWER(*string)) {
+ i = (*string - 'a');
+ dynamic_var[i] = npop();
+ }
+ break;
+
+ case 'g':
+ string++;
+ if (isUPPER(*string)) {
+ i = (*string - 'A');
+ npush(static_vars[i]);
+ } else if (isLOWER(*string)) {
+ i = (*string - 'a');
+ npush(dynamic_var[i]);
+ }
+ break;
+
+ case '\'':
+ string++;
+ npush(*string);
+ string++;
+ break;
+
+ case '{':
+ number = 0;
+ string++;
+ while (*string >= '0' && *string <= '9') {
+ number = number * 10 + *string - '0';
+ string++;
+ }
+ npush(number);
+ break;
+
+ case '+':
+ npush(npop() + npop());
+ break;
+
+ case '-':
+ y = npop();
+ x = npop();
+ npush(x - y);
+ break;
+
+ case '*':
+ npush(npop() * npop());
+ break;
+
+ case '/':
+ y = npop();
+ x = npop();
+ npush(y ? (x / y) : 0);
+ break;
+
+ case 'm':
+ y = npop();
+ x = npop();
+ npush(y ? (x % y) : 0);
+ break;
+
+ case 'A':
+ npush(npop() && npop());
+ break;
+
+ case 'O':
+ npush(npop() || npop());
+ break;
+
+ case '&':
+ npush(npop() & npop());
+ break;
+
+ case '|':
+ npush(npop() | npop());
+ break;
+
+ case '^':
+ npush(npop() ^ npop());
+ break;
+
+ case '=':
+ y = npop();
+ x = npop();
+ npush(x == y);
+ break;
+
+ case '<':
+ y = npop();
+ x = npop();
+ npush(x < y);
+ break;
+
+ case '>':
+ y = npop();
+ x = npop();
+ npush(x > y);
+ break;
+
+ case '!':
+ npush(!npop());
+ break;
+
+ case '~':
+ npush(~npop());
+ break;
+
+ case 'i':
+ if (p_is_s[0] == 0)
+ param[0]++;
+ if (p_is_s[1] == 0)
+ param[1]++;
+ break;
+
+ case '?':
+ break;
+
+ case 't':
+ x = npop();
+ if (!x) {
+ /* scan forward for %e or %; at level zero */
+ string++;
+ level = 0;
+ while (*string) {
+ if (*string == '%') {
+ string++;
+ if (*string == '?')
+ level++;
+ else if (*string == ';') {
+ if (level > 0)
+ level--;
+ else
+ break;
+ } else if (*string == 'e' && level == 0)
+ break;
+ }
+
+ if (*string)
+ string++;
+ }
+ }
+ break;
+
+ case 'e':
+ /* scan forward for a %; at level zero */
+ string++;
+ level = 0;
+ while (*string) {
+ if (*string == '%') {
+ string++;
+ if (*string == '?')
+ level++;
+ else if (*string == ';') {
+ if (level > 0)
+ level--;
+ else
+ break;
+ }
+ }
+
+ if (*string)
+ string++;
+ }
+ break;
+
+ case ';':
+ break;
+
+ } /* endswitch (*string) */
+ } else { /* endelse (*string == '%') */
+ save_char(*string);
+ }
+
+ if (*string == '\0')
+ break;
+
+ string++;
+ } /* endwhile (*string) */
+
+ get_space(1);
+ out_buff[out_used] = '\0';
+
+ return (out_buff);
+}
+
+char *
+grub_tparm(const char *string,...)
+{
+ char *result;
+ int *dataptr = (int *) &string;
+
+ dataptr++;
+
+ result = tparam_internal(string, dataptr);
+
+ return result;
+}
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-02-21 12:38 x86 serial support Omniflux
@ 2005-03-02 21:33 ` Yoshinori K. Okuji
2005-08-10 0:41 ` Omniflux
0 siblings, 1 reply; 15+ messages in thread
From: Yoshinori K. Okuji @ 2005-03-02 21:33 UTC (permalink / raw)
To: The development of GRUB 2
Sorry, I forgot to send a reply.
On Monday 21 February 2005 13:38, Omniflux wrote:
> Here is a patch to add serial support to x86.
Great.
> If this is headed in the right direction, and likely to be accepted
> for merging with a little more work, I'll keep working on it.
I think this is a good way. But some problems must be solved:
- Naming issues. Since you copied the code from GRUB Legacy, some names
are not appropriate in GRUB 2. For example, the global function
declared in terminfo.h do not use the prefix 'grub_' at all.
- Module separation. I think it would be better to have a separate
module for terminfo, because we might be able to use it for other
terminals as well as serial console, say, parallel console.
- ChangeLog. Please write ChangeLog entries for your changes.
BTW, do you have any suggestion about the so-called "dumb terminal"?
Because supporting dumb terminal is horrible, I hesitate to support it
in GRUB 2, if there is no clean way to do it.
Okuji
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-03-02 21:33 ` Yoshinori K. Okuji
@ 2005-08-10 0:41 ` Omniflux
2005-08-12 10:51 ` Vladimir Serbinenko
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Omniflux @ 2005-08-10 0:41 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 1175 bytes --]
It's been a few months, but here are some updated patches.
The terminfo patch probably needs to be applied first.
Yoshinori K. Okuji wrote:
> - Naming issues. Since you copied the code from GRUB Legacy, some names
> are not appropriate in GRUB 2. For example, the global function
> declared in terminfo.h do not use the prefix 'grub_' at all.
I think I have fixed these all correctly...
> - Module separation. I think it would be better to have a separate
> module for terminfo, because we might be able to use it for other
> terminals as well as serial console, say, parallel console.
Done.
> - ChangeLog. Please write ChangeLog entries for your changes.
Attached.
> BTW, do you have any suggestion about the so-called "dumb terminal"?
> Because supporting dumb terminal is horrible, I hesitate to support it
> in GRUB 2, if there is no clean way to do it.
The only thing I can think of is to disable the menu and replace clear
screen with a newline, which is what Legacy does IIRC.
I need some input on how to complete the function
grub_terminfo_set_current in term/terminfo.c.
Feedback on anything else would also be appreciated.
Thanks!
--
Omniflux
[-- Attachment #2: grub2.terminfo.diff --]
[-- Type: text/plain, Size: 27442 bytes --]
diff -uNr grub2/conf/i386-pc.rmk grub2.terminfo/conf/i386-pc.rmk
--- grub2/conf/i386-pc.rmk 2005-08-09 08:39:50.000000000 -0600
+++ grub2.terminfo/conf/i386-pc.rmk 2005-08-09 17:46:45.000000000 -0600
@@ -110,7 +110,7 @@
font.mod _multiboot.mod ls.mod boot.mod cmp.mod cat.mod \
terminal.mod fshelp.mod chain.mod multiboot.mod amiga.mod \
apple.mod pc.mod sun.mod loopback.mod reboot.mod halt.mod \
- help.mod default.mod timeout.mod configfile.mod
+ help.mod default.mod timeout.mod configfile.mod terminfo.mod
# For _chain.mod.
_chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -211,6 +211,10 @@
font_mod_SOURCES = font/manager.c
font_mod_CFLAGS = $(COMMON_CFLAGS)
+# For terminfo.mod.
+terminfo_mod_SOURCES = term/terminfo.c term/tparm.c
+terminfo_mod_CFLAGS = $(COMMON_CFLAGS)
+
# For _multiboot.mod.
_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c
_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
diff -uNr grub2/include/grub/terminfo.h grub2.terminfo/include/grub/terminfo.h
--- grub2/include/grub/terminfo.h 1969-12-31 17:00:00.000000000 -0700
+++ grub2.terminfo/include/grub/terminfo.h 2005-08-09 17:46:45.000000000 -0600
@@ -0,0 +1,49 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2005 Free Software Foundation, Inc.
+ *
+ * GRUB is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_TERMINFO_HEADER
+#define GRUB_TERMINFO_HEADER 1
+
+#include <grub/err.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+typedef struct terminfo
+{
+ char *name;
+
+ char *gotoxy;
+ char *cls;
+ char *reverse_video_on;
+ char *reverse_video_off;
+ char *cursor_on;
+ char *cursor_off;
+} terminfo;
+
+char * EXPORT_FUNC(grub_terminfo_get_current) (void);
+grub_err_t EXPORT_FUNC(grub_terminfo_set_current) (const char *);
+
+void EXPORT_FUNC(grub_terminfo_gotoxy) (const grub_uint8_t x, const grub_uint8_t y);
+void EXPORT_FUNC(grub_terminfo_cls) (void);
+void EXPORT_FUNC(grub_terminfo_reverse_video_on) (void);
+void EXPORT_FUNC(grub_terminfo_reverse_video_off) (void);
+void EXPORT_FUNC(grub_terminfo_cursor_on) (void);
+void EXPORT_FUNC(grub_terminfo_cursor_off) (void);
+
+#endif /* ! GRUB_TERMINFO_HEADER */
diff -uNr grub2/include/grub/tparm.h grub2.terminfo/include/grub/tparm.h
--- grub2/include/grub/tparm.h 1969-12-31 17:00:00.000000000 -0700
+++ grub2.terminfo/include/grub/tparm.h 2005-08-09 17:46:45.000000000 -0600
@@ -0,0 +1,28 @@
+/* tparm.h - parameter formatting of terminfo */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2005 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_TPARM_HEADER
+#define GRUB_TPARM_HEADER 1
+
+\f
+/* Function prototypes. */
+char *grub_terminfo_tparm (const char *string, ...);
+
+#endif /* ! GRUB_TPARM_HEADER */
diff -uNr grub2/term/terminfo.c grub2.terminfo/term/terminfo.c
--- grub2/term/terminfo.c 1969-12-31 17:00:00.000000000 -0700
+++ grub2.terminfo/term/terminfo.c 2005-08-09 17:46:45.000000000 -0600
@@ -0,0 +1,157 @@
+/* terminfo.c - simple terminfo module */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This file contains various functions dealing with different
+ * terminal capabilities. For example, vt52 and vt100.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/term.h>
+#include <grub/terminfo.h>
+#include <grub/tparm.h>
+
+static struct terminfo term;
+
+/* Get current terminfo name. */
+inline char *
+grub_terminfo_get_current (void)
+{
+ return term.name;
+}
+
+/* Set current terminfo type. */
+grub_err_t
+grub_terminfo_set_current (const char *str)
+{
+ /* TODO
+ * Lookup user specified terminfo type. If found, set term variables
+ * as appropriate. Otherwise return an error.
+ *
+ * How should this be done?
+ * a. A static table included in this module.
+ * - I do not like this idea.
+ * b. A table stored in the configuration directory.
+ * - Users must convert their terminfo settings if we have not already.
+ * c. Look for terminfo files in the configuration directory.
+ * - /usr/share/terminfo is 6.3M on my system.
+ * - /usr/share/terminfo is not on most users boot partition.
+ * + Copying the terminfo files you want to use to the grub
+ * configuration directory is easier then (b).
+ * d. Your idea here.
+ */
+
+ if (grub_strcmp ("vt100", str) == 0)
+ {
+ term.name = grub_strdup ("vt100");
+ term.gotoxy = grub_strdup ("\e[%i%p1%d;%p2%dH");
+ term.cls = grub_strdup ("\e[H\e[J");
+ term.reverse_video_on = grub_strdup ("\e[7m");
+ term.reverse_video_off = grub_strdup ("\e[m");
+ term.cursor_on = grub_strdup ("\e[?25l");
+ term.cursor_off = grub_strdup ("\e[?25h");
+ return GRUB_ERR_NONE;
+ }
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminfo type.");
+}
+
+/* Wrapper for grub_putchar to write strings. */
+static void putstr (const char *str)
+{
+ while (*str)
+ grub_putchar (*str++);
+}
+
+/* Move the cursor to the given position starting with "0". */
+void
+grub_terminfo_gotoxy (const grub_uint8_t x, const grub_uint8_t y)
+{
+ putstr (grub_terminfo_tparm (term.gotoxy, y, x));
+}
+
+/* Clear the screen. */
+void
+grub_terminfo_cls (void)
+{
+ putstr (grub_terminfo_tparm (term.cls));
+}
+
+/* Set reverse video mode on. */
+void
+grub_terminfo_reverse_video_on (void)
+{
+ putstr (grub_terminfo_tparm (term.reverse_video_on));
+}
+
+/* Set reverse video mode off. */
+void
+grub_terminfo_reverse_video_off (void)
+{
+ putstr (grub_terminfo_tparm (term.reverse_video_off));
+}
+
+/* Show cursor. */
+void
+grub_terminfo_cursor_on (void)
+{
+ putstr (grub_terminfo_tparm (term.cursor_on));
+}
+
+/* Hide cursor. */
+void
+grub_terminfo_cursor_off (void)
+{
+ putstr (grub_terminfo_tparm (term.cursor_off));
+}
+
+/* GRUB Command. */
+
+static grub_err_t
+grub_cmd_terminfo (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ if (argc == 0)
+ {
+ grub_printf ("Current terminfo type: %s\n", grub_terminfo_get_current());
+ return GRUB_ERR_NONE;
+ }
+ else if (argc != 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many parameters.");
+ else
+ return grub_terminfo_set_current (args[0]);
+}
+
+GRUB_MOD_INIT
+{
+ (void)mod; /* To stop warning. */
+ grub_register_command ("terminfo", grub_cmd_terminfo, GRUB_COMMAND_FLAG_BOTH,
+ "terminfo [TERM...]", "Set terminfo type.", 0);
+ grub_terminfo_set_current ("vt100");
+}
+
+GRUB_MOD_FINI
+{
+ grub_unregister_command ("terminfo");
+}
diff -uNr grub2/term/tparm.c grub2.terminfo/term/tparm.c
--- grub2/term/tparm.c 1969-12-31 17:00:00.000000000 -0700
+++ grub2.terminfo/term/tparm.c 2005-08-09 17:46:45.000000000 -0600
@@ -0,0 +1,769 @@
+/****************************************************************************
+ * Copyright (c) 1998-2003,2004,2005 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), to deal in the Software without restriction, including *
+ * without limitation the rights to use, copy, modify, merge, publish, *
+ * distribute, distribute with modifications, sublicense, and/or sell *
+ * copies of the Software, and to permit persons to whom the Software is *
+ * furnished to do so, subject to the following conditions: *
+ * *
+ * The above copyright notice and this permission notice shall be included *
+ * in all copies or substantial portions of the Software. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+ * *
+ * Except as contained in this notice, the name(s) of the above copyright *
+ * holders shall not be used in advertising or otherwise to promote the *
+ * sale, use or other dealings in this Software without prior written *
+ * authorization. *
+ ****************************************************************************/
+
+/**********************************************************************
+ * This code is a modification of lib_tparm.c found in ncurses-5.2. The
+ * modification are for use in grub by replacing all libc function through
+ * special grub functions. This also meant to delete all dynamic memory
+ * allocation and replace it by a number of fixed buffers.
+ *
+ * Modifications by Tilmann Bubeck <t.bubeck@reinform.de> 2002
+ *
+ * Resync with ncurses-5.4 by Omniflux <omniflux+devel@omniflux.com> 2005
+ **********************************************************************/
+
+/****************************************************************************
+ * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
+ * and: Eric S. Raymond <esr@snark.thyrsus.com> *
+ * and: Thomas E. Dickey, 1996 on *
+ ****************************************************************************/
+
+/*
+ * tparm.c
+ *
+ */
+
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/tparm.h>
+
+/*
+ * Common/troublesome character definitions
+ */
+typedef char grub_bool_t;
+#ifndef FALSE
+# define FALSE (0)
+#endif
+#ifndef TRUE
+# define TRUE (!FALSE)
+#endif
+
+#define NUM_PARM 9
+#define NUM_VARS 26
+#define STACKSIZE 20
+#define MAX_FORMAT_LEN 256
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z')
+#define isLOWER(c) ((c) >= 'a' && (c) <= 'z')
+
+#define UChar(c) ((unsigned char)(c))
+
+//MODULE_ID("$Id: tparm.c,v 1.1 2002/11/29 20:39:24 okuji Exp $")
+
+/*
+ * char *
+ * tparm(string, ...)
+ *
+ * Substitute the given parameters into the given string by the following
+ * rules (taken from terminfo(5)):
+ *
+ * Cursor addressing and other strings requiring parame-
+ * ters in the terminal are described by a parameterized string
+ * capability, with like escapes %x in it. For example, to
+ * address the cursor, the cup capability is given, using two
+ * parameters: the row and column to address to. (Rows and
+ * columns are numbered from zero and refer to the physical
+ * screen visible to the user, not to any unseen memory.) If
+ * the terminal has memory relative cursor addressing, that can
+ * be indicated by
+ *
+ * The parameter mechanism uses a stack and special %
+ * codes to manipulate it. Typically a sequence will push one
+ * of the parameters onto the stack and then print it in some
+ * format. Often more complex operations are necessary.
+ *
+ * The % encodings have the following meanings:
+ *
+ * %% outputs `%'
+ * %c print pop() like %c in printf()
+ * %s print pop() like %s in printf()
+ * %[[:]flags][width[.precision]][doxXs]
+ * as in printf, flags are [-+#] and space
+ * The ':' is used to avoid making %+ or %-
+ * patterns (see below).
+ *
+ * %p[1-9] push ith parm
+ * %P[a-z] set dynamic variable [a-z] to pop()
+ * %g[a-z] get dynamic variable [a-z] and push it
+ * %P[A-Z] set static variable [A-Z] to pop()
+ * %g[A-Z] get static variable [A-Z] and push it
+ * %l push strlen(pop)
+ * %'c' push char constant c
+ * %{nn} push integer constant nn
+ *
+ * %+ %- %* %/ %m
+ * arithmetic (%m is mod): push(pop() op pop())
+ * %& %| %^ bit operations: push(pop() op pop())
+ * %= %> %< logical operations: push(pop() op pop())
+ * %A %O logical and & or operations for conditionals
+ * %! %~ unary operations push(op pop())
+ * %i add 1 to first two parms (for ANSI terminals)
+ *
+ * %? expr %t thenpart %e elsepart %;
+ * if-then-else, %e elsepart is optional.
+ * else-if's are possible ala Algol 68:
+ * %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %;
+ *
+ * For those of the above operators which are binary and not commutative,
+ * the stack works in the usual way, with
+ * %gx %gy %m
+ * resulting in x mod y, not the reverse.
+ */
+
+typedef struct {
+ union {
+ int num;
+ char *str;
+ } data;
+ grub_bool_t num_type;
+} stack_frame;
+
+static stack_frame stack[STACKSIZE];
+static int stack_ptr;
+static const char *tparam_base = "";
+
+static char *out_buff;
+static grub_size_t out_size;
+static grub_size_t out_used;
+
+static char *fmt_buff;
+static grub_size_t fmt_size;
+
+static inline void
+get_space(grub_size_t need)
+{
+ need += out_used;
+ if (need > out_size) {
+ out_size = need * 2;
+ out_buff = grub_realloc(out_buff, out_size*sizeof(char));
+ if (out_buff == 0)
+ // FIX ME! OOM, what now?
+ ;
+ }
+}
+
+static inline void
+save_text(const char *fmt, const char *s, int len)
+{
+ grub_size_t s_len = grub_strlen(s);
+ if (len > (int) s_len)
+ s_len = len;
+
+ get_space(s_len + 1);
+
+ (void) grub_sprintf(out_buff + out_used, fmt, s);
+ out_used += grub_strlen(out_buff + out_used);
+}
+
+static inline void
+save_number(const char *fmt, int number, int len)
+{
+ if (len < 30)
+ len = 30; /* actually log10(MAX_INT)+1 */
+
+ get_space((unsigned) len + 1);
+
+ (void) grub_sprintf(out_buff + out_used, fmt, number);
+ out_used += grub_strlen(out_buff + out_used);
+}
+
+static inline void
+save_char(int c)
+{
+ if (c == 0)
+ c = 0200;
+ get_space(1);
+ out_buff[out_used++] = c;
+}
+
+static inline void
+npush(int x)
+{
+ if (stack_ptr < STACKSIZE) {
+ stack[stack_ptr].num_type = TRUE;
+ stack[stack_ptr].data.num = x;
+ stack_ptr++;
+ }
+}
+
+static inline int
+npop(void)
+{
+ int result = 0;
+ if (stack_ptr > 0) {
+ stack_ptr--;
+ if (stack[stack_ptr].num_type)
+ result = stack[stack_ptr].data.num;
+ }
+ return result;
+}
+
+static inline void
+spush(char *x)
+{
+ if (stack_ptr < STACKSIZE) {
+ stack[stack_ptr].num_type = FALSE;
+ stack[stack_ptr].data.str = x;
+ stack_ptr++;
+ }
+}
+
+static inline char *
+spop(void)
+{
+ static char dummy[] = ""; /* avoid const-cast */
+ char *result = dummy;
+ if (stack_ptr > 0) {
+ stack_ptr--;
+ if (!stack[stack_ptr].num_type && stack[stack_ptr].data.str != 0)
+ result = stack[stack_ptr].data.str;
+ }
+ return result;
+}
+
+static inline const char *
+parse_format(const char *s, char *format, int *len)
+{
+ *len = 0;
+ if (format != 0) {
+ grub_bool_t done = FALSE;
+ grub_bool_t allowminus = FALSE;
+ grub_bool_t dot = FALSE;
+ grub_bool_t err = FALSE;
+ char *fmt = format;
+ int my_width = 0;
+ int my_prec = 0;
+ int value = 0;
+
+ *len = 0;
+ *format++ = '%';
+ while (*s != '\0' && !done) {
+ switch (*s) {
+ case 'c': /* FALLTHRU */
+ case 'd': /* FALLTHRU */
+ case 'o': /* FALLTHRU */
+ case 'x': /* FALLTHRU */
+ case 'X': /* FALLTHRU */
+ case 's':
+ *format++ = *s;
+ done = TRUE;
+ break;
+ case '.':
+ *format++ = *s++;
+ if (dot) {
+ err = TRUE;
+ } else { /* value before '.' is the width */
+ dot = TRUE;
+ my_width = value;
+ }
+ value = 0;
+ break;
+ case '#':
+ *format++ = *s++;
+ break;
+ case ' ':
+ *format++ = *s++;
+ break;
+ case ':':
+ s++;
+ allowminus = TRUE;
+ break;
+ case '-':
+ if (allowminus) {
+ *format++ = *s++;
+ } else {
+ done = TRUE;
+ }
+ break;
+ default:
+ if (isdigit(UChar(*s))) {
+ value = (value * 10) + (*s - '0');
+ if (value > 10000)
+ err = TRUE;
+ *format++ = *s++;
+ } else {
+ done = TRUE;
+ }
+ }
+ }
+
+ /*
+ * If we found an error, ignore (and remove) the flags.
+ */
+ if (err) {
+ my_width = my_prec = value = 0;
+ format = fmt;
+ *format++ = '%';
+ *format++ = *s;
+ }
+
+ /*
+ * Any value after '.' is the precision. If we did not see '.', then
+ * the value is the width.
+ */
+ if (dot)
+ my_prec = value;
+ else
+ my_width = value;
+
+ *format = '\0';
+ /* return maximum string length in print */
+ *len = (my_width > my_prec) ? my_width : my_prec;
+ }
+ return s;
+}
+
+/*
+ * Analyze the string to see how many parameters we need from the varargs list,
+ * and what their types are. We will only accept string parameters if they
+ * appear as a %l or %s format following an explicit parameter reference (e.g.,
+ * %p2%s). All other parameters are numbers.
+ *
+ * 'number' counts coarsely the number of pop's we see in the string, and
+ * 'popcount' shows the highest parameter number in the string. We would like
+ * to simply use the latter count, but if we are reading termcap strings, there
+ * may be cases that we cannot see the explicit parameter numbers.
+ */
+static inline int
+analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount)
+{
+ grub_size_t len2;
+ int i;
+ int lastpop = -1;
+ int len;
+ int number = 0;
+ const char *cp = string;
+ static char dummy[] = "";
+
+ if (cp == 0)
+ return 0;
+
+ if ((len2 = grub_strlen(cp)) > fmt_size) {
+ fmt_size = len2 + fmt_size + 2;
+ if ((fmt_buff = grub_realloc(fmt_buff, fmt_size*sizeof(char))) == 0)
+ return 0;
+ }
+
+ grub_memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM);
+ *popcount = 0;
+
+ while ((cp - string) < (int) len2) {
+ if (*cp == '%') {
+ cp++;
+ cp = parse_format(cp, fmt_buff, &len);
+ switch (*cp) {
+ default:
+ break;
+
+ case 'd': /* FALLTHRU */
+ case 'o': /* FALLTHRU */
+ case 'x': /* FALLTHRU */
+ case 'X': /* FALLTHRU */
+ case 'c': /* FALLTHRU */
+ if (lastpop <= 0)
+ number++;
+ lastpop = -1;
+ break;
+
+ case 'l':
+ case 's':
+ if (lastpop > 0)
+ p_is_s[lastpop - 1] = dummy;
+ ++number;
+ break;
+
+ case 'p':
+ cp++;
+ i = (UChar(*cp) - '0');
+ if (i >= 0 && i <= NUM_PARM) {
+ lastpop = i;
+ if (lastpop > *popcount)
+ *popcount = lastpop;
+ }
+ break;
+
+ case 'P':
+ ++number;
+ ++cp;
+ break;
+
+ case 'g':
+ cp++;
+ break;
+
+ case '\'':
+ cp += 2;
+ lastpop = -1;
+ break;
+
+ case '{':
+ cp++;
+ while (isdigit(UChar(*cp))) {
+ cp++;
+ }
+ break;
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case 'm':
+ case 'A':
+ case 'O':
+ case '&':
+ case '|':
+ case '^':
+ case '=':
+ case '<':
+ case '>':
+ lastpop = -1;
+ number += 2;
+ break;
+
+ case '!':
+ case '~':
+ lastpop = -1;
+ ++number;
+ break;
+
+ case 'i':
+ /* will add 1 to first (usually two) parameters */
+ break;
+ }
+ }
+ if (*cp != '\0')
+ cp++;
+ }
+
+ if (number > NUM_PARM)
+ number = NUM_PARM;
+ return number;
+}
+
+static inline char *
+tparam_internal(const char *string, va_list ap)
+{
+ char *p_is_s[NUM_PARM];
+ long param[NUM_PARM];
+ int popcount;
+ int number;
+ int len;
+ int level;
+ int x, y;
+ int i;
+ const char *cp = string;
+ grub_size_t len2;
+ static int dynamic_var[NUM_VARS];
+ static int static_vars[NUM_VARS];
+
+ if (cp == 0)
+ return 0;
+
+ out_used = out_size = fmt_size = 0;
+
+ len2 = (int) grub_strlen(cp);
+
+ /*
+ * Find the highest parameter-number referred to in the format string.
+ * Use this value to limit the number of arguments copied from the
+ * variable-length argument list.
+ */
+ number = analyze(cp, p_is_s, &popcount);
+ if (fmt_buff == 0)
+ return 0;
+
+ for (i = 0; i < max(popcount, number); i++) {
+ /*
+ * A few caps (such as plab_norm) have string-valued parms.
+ * We'll have to assume that the caller knows the difference, since
+ * a char* and an int may not be the same size on the stack.
+ */
+ if (p_is_s[i] != 0) {
+ p_is_s[i] = va_arg(ap, char *);
+ } else {
+ param[i] = va_arg(ap, long int);
+ }
+ }
+
+ /*
+ * This is a termcap compatibility hack. If there are no explicit pop
+ * operations in the string, load the stack in such a way that
+ * successive pops will grab successive parameters. That will make
+ * the expansion of (for example) \E[%d;%dH work correctly in termcap
+ * style, which means tparam() will expand termcap strings OK.
+ */
+ stack_ptr = 0;
+ if (popcount == 0) {
+ popcount = number;
+ for (i = number - 1; i >= 0; i--)
+ npush(param[i]);
+ }
+
+ while ((cp - string) < (int) len2) {
+ if (*cp != '%') {
+ save_char(UChar(*cp));
+ } else {
+ tparam_base = cp++;
+ cp = parse_format(cp, fmt_buff, &len);
+ switch (*cp) {
+ default:
+ break;
+ case '%':
+ save_char('%');
+ break;
+
+ case 'd': /* FALLTHRU */
+ case 'o': /* FALLTHRU */
+ case 'x': /* FALLTHRU */
+ case 'X': /* FALLTHRU */
+ save_number(fmt_buff, npop(), len);
+ break;
+
+ case 'c': /* FALLTHRU */
+ save_char(npop());
+ break;
+
+ case 'l':
+ save_number("%d", (int) grub_strlen(spop()), 0);
+ break;
+
+ case 's':
+ save_text(fmt_buff, spop(), len);
+ break;
+
+ case 'p':
+ cp++;
+ i = (UChar(*cp) - '1');
+ if (i >= 0 && i < NUM_PARM) {
+ if (p_is_s[i])
+ spush(p_is_s[i]);
+ else
+ npush(param[i]);
+ }
+ break;
+
+ case 'P':
+ cp++;
+ if (isUPPER(*cp)) {
+ i = (UChar(*cp) - 'A');
+ static_vars[i] = npop();
+ } else if (isLOWER(*cp)) {
+ i = (UChar(*cp) - 'a');
+ dynamic_var[i] = npop();
+ }
+ break;
+
+ case 'g':
+ cp++;
+ if (isUPPER(*cp)) {
+ i = (UChar(*cp) - 'A');
+ npush(static_vars[i]);
+ } else if (isLOWER(*cp)) {
+ i = (UChar(*cp) - 'a');
+ npush(dynamic_var[i]);
+ }
+ break;
+
+ case '\'':
+ cp++;
+ npush(UChar(*cp));
+ cp++;
+ break;
+
+ case '{':
+ number = 0;
+ cp++;
+ while (isdigit(UChar(*cp))) {
+ number = (number * 10) + (UChar(*cp) - '0');
+ cp++;
+ }
+ npush(number);
+ break;
+
+ case '+':
+ npush(npop() + npop());
+ break;
+
+ case '-':
+ y = npop();
+ x = npop();
+ npush(x - y);
+ break;
+
+ case '*':
+ npush(npop() * npop());
+ break;
+
+ case '/':
+ y = npop();
+ x = npop();
+ npush(y ? (x / y) : 0);
+ break;
+
+ case 'm':
+ y = npop();
+ x = npop();
+ npush(y ? (x % y) : 0);
+ break;
+
+ case 'A':
+ npush(npop() && npop());
+ break;
+
+ case 'O':
+ npush(npop() || npop());
+ break;
+
+ case '&':
+ npush(npop() & npop());
+ break;
+
+ case '|':
+ npush(npop() | npop());
+ break;
+
+ case '^':
+ npush(npop() ^ npop());
+ break;
+
+ case '=':
+ y = npop();
+ x = npop();
+ npush(x == y);
+ break;
+
+ case '<':
+ y = npop();
+ x = npop();
+ npush(x < y);
+ break;
+
+ case '>':
+ y = npop();
+ x = npop();
+ npush(x > y);
+ break;
+
+ case '!':
+ npush(!npop());
+ break;
+
+ case '~':
+ npush(~npop());
+ break;
+
+ case 'i':
+ if (p_is_s[0] == 0)
+ param[0]++;
+ if (p_is_s[1] == 0)
+ param[1]++;
+ break;
+
+ case '?':
+ break;
+
+ case 't':
+ x = npop();
+ if (!x) {
+ /* scan forward for %e or %; at level zero */
+ cp++;
+ level = 0;
+ while (*cp) {
+ if (*cp == '%') {
+ cp++;
+ if (*cp == '?')
+ level++;
+ else if (*cp == ';') {
+ if (level > 0)
+ level--;
+ else
+ break;
+ } else if (*cp == 'e' && level == 0)
+ break;
+ }
+
+ if (*cp)
+ cp++;
+ }
+ }
+ break;
+
+ case 'e':
+ /* scan forward for a %; at level zero */
+ cp++;
+ level = 0;
+ while (*cp) {
+ if (*cp == '%') {
+ cp++;
+ if (*cp == '?')
+ level++;
+ else if (*cp == ';') {
+ if (level > 0)
+ level--;
+ else
+ break;
+ }
+ }
+
+ if (*cp)
+ cp++;
+ }
+ break;
+
+ case ';':
+ break;
+
+ } /* endswitch (*cp) */
+ } /* endelse (*cp == '%') */
+
+ if (*cp == '\0')
+ break;
+
+ cp++;
+ } /* endwhile (*cp) */
+
+ get_space(1);
+ out_buff[out_used] = '\0';
+
+ return (out_buff);
+}
+
+char *
+grub_terminfo_tparm(const char *string,...)
+{
+ va_list ap;
+ char *result;
+
+ va_start(ap, string);
+ result = tparam_internal(string, ap);
+ va_end(ap);
+ return result;
+}
[-- Attachment #3: grub2.serial.diff --]
[-- Type: text/plain, Size: 19381 bytes --]
diff -uNr grub2/conf/i386-pc.rmk grub2.serial/conf/i386-pc.rmk
--- grub2/conf/i386-pc.rmk 2005-08-09 17:37:01.000000000 -0600
+++ grub2.serial/conf/i386-pc.rmk 2005-08-09 17:32:00.000000000 -0600
@@ -110,7 +110,8 @@
font.mod _multiboot.mod ls.mod boot.mod cmp.mod cat.mod \
terminal.mod fshelp.mod chain.mod multiboot.mod amiga.mod \
apple.mod pc.mod sun.mod loopback.mod reboot.mod halt.mod \
- help.mod default.mod timeout.mod configfile.mod terminfo.mod
+ help.mod default.mod timeout.mod configfile.mod terminfo.mod \
+ serial.mod
# For _chain.mod.
_chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -215,6 +216,10 @@
terminfo_mod_SOURCES = term/terminfo.c term/tparm.c
terminfo_mod_CFLAGS = $(COMMON_CFLAGS)
+# For serial.mod.
+serial_mod_SOURCES = term/i386/pc/serial.c
+serial_mod_CFLAGS = $(COMMON_CFLAGS)
+
# For _multiboot.mod.
_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c
_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
diff -uNr grub2/conf/i386-pc.rmk.orig grub2.serial/conf/i386-pc.rmk.orig
--- grub2/conf/i386-pc.rmk.orig 2005-08-09 08:39:50.000000000 -0600
+++ grub2.serial/conf/i386-pc.rmk.orig 2005-08-09 17:31:56.000000000 -0600
@@ -110,7 +110,7 @@
font.mod _multiboot.mod ls.mod boot.mod cmp.mod cat.mod \
terminal.mod fshelp.mod chain.mod multiboot.mod amiga.mod \
apple.mod pc.mod sun.mod loopback.mod reboot.mod halt.mod \
- help.mod default.mod timeout.mod configfile.mod
+ help.mod default.mod timeout.mod configfile.mod terminfo.mod
# For _chain.mod.
_chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -211,6 +211,10 @@
font_mod_SOURCES = font/manager.c
font_mod_CFLAGS = $(COMMON_CFLAGS)
+# For terminfo.mod.
+terminfo_mod_SOURCES = term/terminfo.c term/tparm.c
+terminfo_mod_CFLAGS = $(COMMON_CFLAGS)
+
# For _multiboot.mod.
_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c
_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
diff -uNr grub2/include/grub/i386/pc/serial.h grub2.serial/include/grub/i386/pc/serial.h
--- grub2/include/grub/i386/pc/serial.h 1969-12-31 17:00:00.000000000 -0700
+++ grub2.serial/include/grub/i386/pc/serial.h 2005-08-09 17:32:00.000000000 -0600
@@ -0,0 +1,97 @@
+/* serial.h - serial device interface */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000,2001,2002,2005 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_SERIAL_MACHINE_HEADER
+#define GRUB_SERIAL_MACHINE_HEADER 1
+
+/* Macros. */
+
+/* The offsets of UART registers. */
+#define UART_TX 0
+#define UART_RX 0
+#define UART_DLL 0
+#define UART_IER 1
+#define UART_DLH 1
+#define UART_IIR 2
+#define UART_FCR 2
+#define UART_LCR 3
+#define UART_MCR 4
+#define UART_LSR 5
+#define UART_MSR 6
+#define UART_SR 7
+
+/* For LSR bits. */
+#define UART_DATA_READY 0x01
+#define UART_EMPTY_TRANSMITTER 0x20
+
+/* The type of parity. */
+#define UART_NO_PARITY 0x00
+#define UART_ODD_PARITY 0x08
+#define UART_EVEN_PARITY 0x18
+
+/* The type of word length. */
+#define UART_5BITS_WORD 0x00
+#define UART_6BITS_WORD 0x01
+#define UART_7BITS_WORD 0x02
+#define UART_8BITS_WORD 0x03
+
+/* The type of the length of stop bit. */
+#define UART_1_STOP_BIT 0x00
+#define UART_2_STOP_BITS 0x04
+
+/* the switch of DLAB. */
+#define UART_DLAB 0x80
+
+/* Enable the FIFO. */
+#define UART_ENABLE_FIFO 0xC7
+
+/* Turn on DTR, RTS, and OUT2. */
+#define UART_ENABLE_MODEM 0x0B
+
+/* Read a byte from a port. */
+static inline unsigned char
+inb (const unsigned short port)
+{
+ unsigned char value;
+
+ asm volatile ("inb %w1, %0" : "=a" (value) : "Nd" (port));
+ asm volatile ("outb %%al, $0x80" : : );
+
+ return value;
+}
+
+/* Write a byte to a port. */
+static inline void
+outb (const unsigned short port, const unsigned char value)
+{
+ asm volatile ("outb %b0, %w1" : : "a" (value), "Nd" (port));
+ asm volatile ("outb %%al, $0x80" : : );
+}
+
+/* Return the port number for the UNITth serial device. */
+static inline unsigned short
+serial_hw_get_port (const unsigned short unit)
+{
+ /* The BIOS data area. */
+ const unsigned short *addr = (const unsigned short *) 0x0400;
+ return addr[unit];
+}
+
+#endif /* ! GRUB_SERIAL_MACHINE_HEADER */
diff -uNr grub2/term/i386/pc/serial.c grub2.serial/term/i386/pc/serial.c
--- grub2/term/i386/pc/serial.c 1969-12-31 17:00:00.000000000 -0700
+++ grub2.serial/term/i386/pc/serial.c 2005-08-09 17:36:25.000000000 -0600
@@ -0,0 +1,575 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000,2001,2002,2003,2004,2005 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/machine/serial.h>
+#include <grub/machine/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/arg.h>
+#include <grub/terminfo.h>
+
+#define TEXT_WIDTH 80
+#define TEXT_HEIGHT 25
+
+static unsigned int xpos, ypos;
+static unsigned int keep_track = 1;
+static unsigned int registered = 0;
+
+/* An input buffer. */
+static char input_buf[8];
+static unsigned int npending = 0;
+
+/* Argument options. */
+static const struct grub_arg_option options[] =
+{
+ {"unit", 'u', 0, "Set the serial unit", 0, ARG_TYPE_INT},
+ {"port", 'p', 0, "Set the serial port address", 0, ARG_TYPE_STRING},
+ {"speed", 's', 0, "Set the serial port speed", 0, ARG_TYPE_INT},
+ {"word", 'w', 0, "Set the serial port word length", 0, ARG_TYPE_INT},
+ {"parity", 'r', 0, "Set the serial port parity", 0, ARG_TYPE_STRING},
+ {"stop", 't', 0, "Set the serial port stop bits", 0, ARG_TYPE_INT},
+ {0, 0, 0, 0, 0, 0}
+};
+
+/* Serial port settings. */
+struct serial_port
+{
+ unsigned short port;
+ unsigned short divisor;
+ unsigned short word_len;
+ unsigned int parity;
+ unsigned short stop_bits;
+};
+
+/* Serial port settings. */
+static struct serial_port serial_settings;
+
+/* Fetch a key. */
+static int
+serial_hw_fetch (void)
+{
+ if (inb (serial_settings.port + UART_LSR) & UART_DATA_READY)
+ return inb (serial_settings.port + UART_RX);
+
+ return -1;
+}
+
+/* Put a chararacter. */
+static void
+serial_hw_put (const int c)
+{
+ unsigned int timeout = 100000;
+
+ /* Wait until the transmitter holding register is empty. */
+ while ((inb (serial_settings.port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0)
+ {
+ if (--timeout == 0)
+ /* There is something wrong. But what can I do? */
+ return;
+ }
+
+ outb (serial_settings.port + UART_TX, c);
+}
+
+static void
+serial_translate_key_sequence (void)
+{
+ const struct
+ {
+ char key;
+ char ascii;
+ }
+
+ three_code_table[] =
+ {
+ {'A', 16},
+ {'B', 14},
+ {'C', 6},
+ {'D', 2},
+ {'F', 5},
+ {'H', 1},
+ {'4', 4}
+ };
+
+ const struct
+ {
+ short key;
+ char ascii;
+ }
+
+ four_code_table[] =
+ {
+ {('1' | ('~' << 8)), 1},
+ {('3' | ('~' << 8)), 4},
+ {('5' | ('~' << 8)), 7},
+ {('6' | ('~' << 8)), 3}
+ };
+
+ /* The buffer must start with "ESC [". */
+ if (*((unsigned short *) input_buf) != ('\e' | ('[' << 8)))
+ return;
+
+ if (npending >= 3)
+ {
+ unsigned int i;
+
+ for (i = 0; i < sizeof (three_code_table) / sizeof (three_code_table[0]); i++)
+ if (three_code_table[i].key == input_buf[2])
+ {
+ input_buf[0] = three_code_table[i].ascii;
+ npending -= 2;
+ grub_memmove (input_buf + 1, input_buf + 3, npending - 1);
+ return;
+ }
+ }
+
+ if (npending >= 4)
+ {
+ unsigned int i;
+ short key = *((short *) (input_buf + 2));
+
+ for (i = 0; i < sizeof (four_code_table) / sizeof (four_code_table[0]); i++)
+ if (four_code_table[i].key == key)
+ {
+ input_buf[0] = four_code_table[i].ascii;
+ npending -= 3;
+ grub_memmove (input_buf + 1, input_buf + 4, npending - 1);
+ return;
+ }
+ }
+}
+
+static int
+fill_input_buf (const int nowait)
+{
+ int i;
+
+ for (i = 0; i < 10000 && npending < sizeof (input_buf); i++)
+ {
+ int c;
+
+ c = serial_hw_fetch ();
+ if (c >= 0)
+ {
+ input_buf[npending++] = c;
+
+ /* Reset the counter to zero, to wait for the same interval. */
+ i = 0;
+ }
+
+ if (nowait)
+ break;
+ }
+
+ /* Translate some key sequences. */
+ serial_translate_key_sequence ();
+
+ return npending;
+}
+
+/* Convert speed to divisor. */
+static unsigned short
+serial_get_divisor (const unsigned int speed)
+{
+ unsigned int i;
+
+ /* The structure for speed vs. divisor. */
+ struct divisor
+ {
+ unsigned int speed;
+ unsigned short div;
+ };
+
+ /* The table which lists common configurations. */
+ /* 1843200 / (speed * 16) */
+ static struct divisor divisor_tab[] =
+ {
+ { 2400, 0x0030 },
+ { 4800, 0x0018 },
+ { 9600, 0x000C },
+ { 19200, 0x0006 },
+ { 38400, 0x0003 },
+ { 57600, 0x0002 },
+ { 115200, 0x0001 }
+ };
+
+ /* Set the baud rate. */
+ for (i = 0; i < sizeof (divisor_tab) / sizeof (divisor_tab[0]); i++)
+ if (divisor_tab[i].speed == speed)
+ return divisor_tab[i].div;
+ return 0;
+}
+
+/* The serial version of checkkey. */
+static int
+grub_serial_checkkey (void)
+{
+ if (fill_input_buf (1))
+ return input_buf[0];
+ else
+ return -1;
+}
+
+/* The serial version of getkey. */
+static int
+grub_serial_getkey (void)
+{
+ int c;
+
+ while (! fill_input_buf (0))
+ ;
+
+ c = input_buf[0];
+ grub_memmove (input_buf, input_buf + 1, --npending);
+
+ return c;
+}
+
+/* Initialize a serial device. PORT is the port number for a serial device.
+ SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600,
+ 19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used
+ for the device. Likewise, PARITY is the type of the parity and
+ STOP_BIT_LEN is the length of the stop bit. The possible values for
+ WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as
+ macros. */
+static grub_err_t
+serial_hw_init (void)
+{
+ unsigned char status = 0;
+
+ /* Turn off the interupt. */
+ outb (serial_settings.port + UART_IER, 0);
+
+ /* Set DLAB. */
+ outb (serial_settings.port + UART_LCR, UART_DLAB);
+
+ /* Set the baud rate. */
+ outb (serial_settings.port + UART_DLL, serial_settings.divisor & 0xFF);
+ outb (serial_settings.port + UART_DLH, serial_settings.divisor >> 8 );
+
+ /* Set the line status. */
+ status |= serial_settings.parity
+ | serial_settings.word_len
+ | serial_settings.stop_bits;
+ outb (serial_settings.port + UART_LCR, status);
+
+ /* Enable the FIFO. */
+ outb (serial_settings.port + UART_FCR, UART_ENABLE_FIFO);
+
+ /* Turn on DTR, RTS, and OUT2. */
+ outb (serial_settings.port + UART_MCR, UART_ENABLE_MODEM);
+
+ /* Drain the input buffer. */
+ while (grub_serial_checkkey () != -1)
+ (void) grub_serial_getkey ();
+
+ /* FIXME: should check if the serial terminal was found. */
+
+ return GRUB_ERR_NONE;
+}
+
+/* The serial version of putchar. */
+static void
+grub_serial_putchar (grub_uint32_t c)
+{
+ /* Keep track of the cursor. */
+ if (keep_track)
+ {
+ /* The serial terminal does not have VGA fonts. */
+ if (c > 0x7F)
+ {
+ /* Better than nothing. */
+ switch (c)
+ {
+ case GRUB_TERM_DISP_LEFT:
+ c = '<';
+ break;
+
+ case GRUB_TERM_DISP_UP:
+ c = '^';
+ break;
+
+ case GRUB_TERM_DISP_RIGHT:
+ c = '>';
+ break;
+
+ case GRUB_TERM_DISP_DOWN:
+ c = 'v';
+ break;
+
+ case GRUB_TERM_DISP_HLINE:
+ c = '-';
+ break;
+
+ case GRUB_TERM_DISP_VLINE:
+ c = '|';
+ break;
+
+ case GRUB_TERM_DISP_UL:
+ case GRUB_TERM_DISP_UR:
+ case GRUB_TERM_DISP_LL:
+ case GRUB_TERM_DISP_LR:
+ c = '+';
+ break;
+
+ default:
+ break;
+ }
+ }
+ switch (c)
+ {
+ case '\a':
+ break;
+
+ case '\b':
+ case 127:
+ if (xpos > 0)
+ xpos--;
+ break;
+
+ case '\n':
+ if (ypos < TEXT_HEIGHT)
+ ypos++;
+ break;
+
+ case '\r':
+ xpos = 0;
+ break;
+
+ default:
+ if (xpos >= TEXT_WIDTH)
+ {
+ grub_putchar ('\r');
+ grub_putchar ('\n');
+ }
+ xpos++;
+ break;
+ }
+ }
+ serial_hw_put (c);
+}
+
+static grub_uint16_t
+grub_serial_getwh (void)
+{
+ return (TEXT_WIDTH << 8) | TEXT_HEIGHT;
+}
+
+static grub_uint16_t
+grub_serial_getxy (void)
+{
+ return ((xpos << 8) | ypos);
+}
+
+static void
+grub_serial_gotoxy (const grub_uint8_t x, const grub_uint8_t y)
+{
+ if (x > TEXT_WIDTH || y > TEXT_HEIGHT)
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)", x, y);
+ }
+ else
+ {
+ keep_track = 0;
+ grub_terminfo_gotoxy (x, y);
+ keep_track = 1;
+
+ xpos = x;
+ ypos = y;
+ }
+}
+
+static void
+grub_serial_cls (void)
+{
+ keep_track = 0;
+ grub_terminfo_cls ();
+ keep_track = 1;
+
+ xpos = ypos = 0;
+}
+
+static void
+grub_serial_setcolorstate (const grub_term_color_state state)
+{
+ keep_track = 0;
+ switch (state)
+ {
+ case GRUB_TERM_COLOR_STANDARD:
+ case GRUB_TERM_COLOR_NORMAL:
+ grub_terminfo_reverse_video_off ();
+ break;
+ case GRUB_TERM_COLOR_HIGHLIGHT:
+ grub_terminfo_reverse_video_on ();
+ break;
+ default:
+ break;
+ }
+ keep_track = 1;
+}
+
+static void
+grub_serial_setcolor (const grub_uint8_t normal_color __attribute__ ((unused)),
+ const grub_uint8_t highlight_color __attribute__ ((unused)))
+{
+ /* FIXME */
+}
+
+static void
+grub_serial_setcursor (const int on)
+{
+ if (on)
+ grub_terminfo_cursor_on ();
+ else
+ grub_terminfo_cursor_off ();
+}
+
+static struct grub_term grub_serial_term =
+{
+ .name = "serial",
+ .init = 0,
+ .fini = 0,
+ .putchar = grub_serial_putchar,
+ .checkkey = grub_serial_checkkey,
+ .getkey = grub_serial_getkey,
+ .getwh = grub_serial_getwh,
+ .getxy = grub_serial_getxy,
+ .gotoxy = grub_serial_gotoxy,
+ .cls = grub_serial_cls,
+ .setcolorstate = grub_serial_setcolorstate,
+ .setcolor = grub_serial_setcolor,
+ .setcursor = grub_serial_setcursor,
+ .flags = 0,
+ .next = 0
+};
+
+static grub_err_t
+grub_cmd_serial (struct grub_arg_list *state,
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ struct serial_port backup_settings = serial_settings;
+ grub_err_t hwiniterr;
+ int arg;
+
+ if (state[0].set)
+ {
+ arg = grub_strtoul (state[0].arg, 0, 0);
+ if (arg >= 0 && arg < 4)
+ serial_settings.port = serial_hw_get_port ((int) arg);
+ else
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad unit number.");
+ }
+ if (state[1].set)
+ serial_settings.port = (unsigned short) grub_strtoul (state[1].arg, 0, 0);
+ if (state[2].set) {
+ serial_settings.divisor = serial_get_divisor ((unsigned int) grub_strtoul (state[2].arg, 0, 0));
+ if (serial_settings.divisor == 0 )
+ {
+ serial_settings = backup_settings;
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed.");
+ }
+ }
+ if (state[3].set)
+ {
+ if (!grub_strcmp (state[3].arg, "5"))
+ serial_settings.word_len = UART_5BITS_WORD;
+ else if (!grub_strcmp (state[3].arg, "6"))
+ serial_settings.word_len = UART_6BITS_WORD;
+ else if (!grub_strcmp (state[3].arg, "7"))
+ serial_settings.word_len = UART_7BITS_WORD;
+ else if (!grub_strcmp (state[3].arg, "8"))
+ serial_settings.word_len = UART_8BITS_WORD;
+ else
+ {
+ serial_settings = backup_settings;
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad word length.");
+ }
+ }
+ if (state[4].set)
+ {
+ if (!grub_strcmp (state[4].arg, "no"))
+ serial_settings.parity = UART_NO_PARITY;
+ else if (!grub_strcmp (state[4].arg, "odd"))
+ serial_settings.parity = UART_ODD_PARITY;
+ else if (!grub_strcmp (state[4].arg, "even"))
+ serial_settings.parity = UART_EVEN_PARITY;
+ else
+ {
+ serial_settings = backup_settings;
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad parity.");
+ }
+ }
+ if (state[5].set)
+ {
+ if (!grub_strcmp (state[5].arg, "1"))
+ serial_settings.stop_bits = UART_1_STOP_BIT;
+ else if (!grub_strcmp (state[5].arg, "2"))
+ serial_settings.stop_bits = UART_2_STOP_BITS;
+ else
+ {
+ serial_settings = backup_settings;
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad number of stop bits.");
+ }
+ }
+
+ hwiniterr = serial_hw_init (); /* Initialize with new settings. */
+ if (hwiniterr == GRUB_ERR_NONE)
+ {
+ if (registered == 0) /* Register terminal if not yet registered. */
+ {
+ grub_term_register (&grub_serial_term);
+ registered = 1;
+ }
+ }
+ else /* Initialization with new settings failed. */
+ if (registered == 1) /* If terminal is registered, attempt to restore previous settings. */
+ {
+ serial_settings = backup_settings;
+ if (serial_hw_init () != GRUB_ERR_NONE) /* If unable to restore settings, unregister terminal. */
+ {
+ grub_term_unregister (&grub_serial_term);
+ registered = 0;
+ }
+ }
+ return hwiniterr;
+}
+
+GRUB_MOD_INIT
+{
+ (void)mod; /* To stop warning. */
+ grub_register_command ("serial", grub_cmd_serial, GRUB_COMMAND_FLAG_BOTH,
+ "serial [OPTIONS...]", "Configure serial port.", options);
+ /* Set default settings. */
+ serial_settings.port = serial_hw_get_port (0);
+ serial_settings.divisor = serial_get_divisor (9600);
+ serial_settings.word_len = UART_8BITS_WORD;
+ serial_settings.parity = UART_NO_PARITY;
+ serial_settings.stop_bits = UART_1_STOP_BIT;
+}
+
+GRUB_MOD_FINI
+{
+ grub_unregister_command ("serial");
+ if (registered == 1) /* Unregister terminal only if registered. */
+ grub_term_unregister (&grub_serial_term);
+}
[-- Attachment #4: grub2.terminfo.changelog --]
[-- Type: text/plain, Size: 556 bytes --]
* term/terminfo.c: Copy from GRUB Legacy.
include/grub/terminfo.h: Likewise
Update for GRUB 2.
Remove unused functions.
Remove dependency on serial module.
Rename functions to match GRUB 2 coding style.
Add preliminary support for multiple terminfo types.
Add GRUB 2 command.
* term/tparm.c: Copy from GRUB Legacy.
include/grub/tparm.h: Likewise
Resync with ncurses-5.4.
Rename exported function to match GRUB 2 coding style
* conf/i386-pc.rmk (pkgdata_MODULES): Added terminfo.mod.
(terminfo_mod_SOURCES): New variable.
(terminfo_mod_CFLAGS): Likewise.
[-- Attachment #5: grub2.serial.changelog --]
[-- Type: text/plain, Size: 390 bytes --]
* term/i386/pc/serial.c: Copy from GRUB Legacy.
include/grub/i386/pc/serial.h: Likewise
Update for GRUB 2.
Rename functions to match GRUB 2 coding style.
Restructure code to minimize scopes and simplify functions.
Make assembly functions inline.
Add GRUB 2 command.
* conf/i386-pc.rmk (pkgdata_MODULES): Added serial.mod.
(serial_mod_SOURCES): New variable.
(serial_mod_CFLAGS): Likewise.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-08-10 0:41 ` Omniflux
@ 2005-08-12 10:51 ` Vladimir Serbinenko
2005-08-12 16:01 ` Marco Gerards
2005-09-03 17:08 ` Yoshinori K. Okuji
2 siblings, 0 replies; 15+ messages in thread
From: Vladimir Serbinenko @ 2005-08-12 10:51 UTC (permalink / raw)
To: The development of GRUB 2
>The only thing I can think of is to disable the menu and replace clear
>screen with a newline, which is what Legacy does IIRC.
>
>
>
But GRUB Legacy has also a dumb menu support even if it's horrible.
Perhaps we must do it like LILO does? Or should we do it more universally?
I propose to make menus like terms: you can have multiple menus registered
but only one chosen. Now we can have normal menu + lilo-like. Then we can
implement eye-candy menu (in VESA mode, perhaps with mouse support).
Another idea: it would be good if from normal menu one could go to
lilo-like
just with a key or key combination (what about 'l' key?) in case when
there is
no display attached or terminal problem.
What do you think about this?
Vladimir
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-08-10 0:41 ` Omniflux
2005-08-12 10:51 ` Vladimir Serbinenko
@ 2005-08-12 16:01 ` Marco Gerards
2005-08-12 20:17 ` Yoshinori K. Okuji
2005-08-12 22:18 ` Omniflux
2005-09-03 17:08 ` Yoshinori K. Okuji
2 siblings, 2 replies; 15+ messages in thread
From: Marco Gerards @ 2005-08-12 16:01 UTC (permalink / raw)
To: The development of GRUB 2
Omniflux <omniflux+lists@omniflux.com> writes:
Hi Omniflux,
> It's been a few months, but here are some updated patches.
>
> The terminfo patch probably needs to be applied first.
Thanks for your new patch! :)
>> BTW, do you have any suggestion about the so-called "dumb terminal"?
>> Because supporting dumb terminal is horrible, I hesitate to support it
>> in GRUB 2, if there is no clean way to do it.
>
> The only thing I can think of is to disable the menu and replace clear
> screen with a newline, which is what Legacy does IIRC.
Why can't we use a menu? Is it really that slow to update the menu
over a serial console?
I'll review your patch ASAP.
Thanks,
Marco
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-08-12 16:01 ` Marco Gerards
@ 2005-08-12 20:17 ` Yoshinori K. Okuji
2005-08-12 22:19 ` Douglas Wade Needham
2005-08-12 22:18 ` Omniflux
1 sibling, 1 reply; 15+ messages in thread
From: Yoshinori K. Okuji @ 2005-08-12 20:17 UTC (permalink / raw)
To: The development of GRUB 2
On Friday 12 August 2005 18:01, Marco Gerards wrote:
> Why can't we use a menu? Is it really that slow to update the menu
> over a serial console?
In a dumb terminal, the problem is that there is no way to go back to a
previous line.
Honestly, I do not want to support dumb terminals. They are rarely used
nowadays, even though the maintenance cost of an independent menu interface
is quite high. Today, even fancy serial terminals are also disappearing.
Since most embedded systems have ethernet interfaces, the future will be net
console rather than serial console.
Okuji
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-08-12 16:01 ` Marco Gerards
2005-08-12 20:17 ` Yoshinori K. Okuji
@ 2005-08-12 22:18 ` Omniflux
2005-08-14 13:03 ` Marco Gerards
1 sibling, 1 reply; 15+ messages in thread
From: Omniflux @ 2005-08-12 22:18 UTC (permalink / raw)
To: The development of GRUB 2
Marco Gerards wrote:
>>>BTW, do you have any suggestion about the so-called "dumb terminal"?
>>
>>The only thing I can think of is to disable the menu and replace clear
>>screen with a newline, which is what Legacy does IIRC.
>
> Why can't we use a menu? Is it really that slow to update the menu
> over a serial console?
This is a communication problem caused by the fact that dumb terminal
does not have a universally accepted definition. In this case, we are
talking about a terminal without cursor control, such as a glass tty or
teletype.
The following paragraph can be ignored if the above clarifies the issue.
It contains examples for anyone else.
To implement a menu for this terminal would entail redrawing the screen
each time something must be changed. This could be incredibly slow as
many of these terminals have speeds of less then 110 bps. This also
leaves the problem of marking the current menu selection, as we cannot
use either color or reverse video. We would also be unable to reposition
the cursor to (0,0) for the redraw, because we cannot be sure of the
display size and thus the number of newlines which must be sent to move
a line of text to that position. If the terminal is actually a display
on paper terminal, we also have the problem of the waste of paper
redisplaying the screen would create.
Why anyone would now be using such a terminal I do not know, but if we
do not mention the proper way to use such a terminal, or not to use such
a terminal at all, I'm sure someone will try it.
--
Omniflux
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-08-12 20:17 ` Yoshinori K. Okuji
@ 2005-08-12 22:19 ` Douglas Wade Needham
0 siblings, 0 replies; 15+ messages in thread
From: Douglas Wade Needham @ 2005-08-12 22:19 UTC (permalink / raw)
To: The development of GRUB 2
Gee...how long has it been since I threw out the old TTYs and LA120s
I used to use as consoles!!! But I know in the realm I work
(networking gear and telecom server), serial consoles will continue to
be there. Even the latest cPCI blade servers all have a serial port
for consoles, if for nothing else than to set parameters for things
like dhcp, long before the network is up. Indeed, the equipment one
of my employer's OEM partners is getting from Intel by default has a
serial console configured (9600 8N1) which allows you to get into the
BIOS or do anything else. And a PXE booted GRUB 1 worked great on it,
and was able to load the ISL image to prep the disk in these boxes
with our network switch software.
My personal opinion is to say that for serial ports, the minimum we
should consider should be ANSI or VT100. After all, who out there
cannot get their hands on a package such as Kermit. It has been an
age, but IIRC, even the program on Windows supports these two types.
But if you think about it, it should not be that hard to output 24 or
25 lines each time you need to redraw.
- Doug
Quoting Yoshinori K. Okuji (okuji@enbug.org):
> On Friday 12 August 2005 18:01, Marco Gerards wrote:
> > Why can't we use a menu? Is it really that slow to update the menu
> > over a serial console?
>
> In a dumb terminal, the problem is that there is no way to go back to a
> previous line.
>
> Honestly, I do not want to support dumb terminals. They are rarely used
> nowadays, even though the maintenance cost of an independent menu interface
> is quite high. Today, even fancy serial terminals are also disappearing.
> Since most embedded systems have ethernet interfaces, the future will be net
> console rather than serial console.
>
> Okuji
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
--
Douglas Wade Needham - KA8ZRT UN*X Consultant & UW/BSD kernel programmer
Email: cinnion @ ka8zrt . com http://cinnion.ka8zrt.com
Disclaimer: My opinions are my own. Since I don't want them, why
should my employer, or anybody else for that matter!
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-08-12 22:18 ` Omniflux
@ 2005-08-14 13:03 ` Marco Gerards
2005-08-14 14:54 ` Yoshinori K. Okuji
0 siblings, 1 reply; 15+ messages in thread
From: Marco Gerards @ 2005-08-14 13:03 UTC (permalink / raw)
To: The development of GRUB 2
Omniflux <omniflux+lists@omniflux.com> writes:
Hi,
> Why anyone would now be using such a terminal I do not know, but if we
> do not mention the proper way to use such a terminal, or not to use
> such a terminal at all, I'm sure someone will try it.
There are also people using 286 computers, etc. My opinion is that we
should focus on the most important things first. That is vt100/ansi
support first. If someone really wants dumb terminal support he can
explain why and he can implement it if it does not break anything
else. What do you think?
--
Marco
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-08-14 13:03 ` Marco Gerards
@ 2005-08-14 14:54 ` Yoshinori K. Okuji
0 siblings, 0 replies; 15+ messages in thread
From: Yoshinori K. Okuji @ 2005-08-14 14:54 UTC (permalink / raw)
To: The development of GRUB 2
On Sunday 14 August 2005 15:03, Marco Gerards wrote:
> There are also people using 286 computers, etc. My opinion is that we
> should focus on the most important things first. That is vt100/ansi
> support first. If someone really wants dumb terminal support he can
> explain why and he can implement it if it does not break anything
> else. What do you think?
"if it does not break anything else" would be quite hard. If someone really
wants to support dumb terminals, she must also modify the command-line
interface, like I did in GRUB Legacy.
I agree with you, however. Only if anyone absolutely needs dumb terminal
support, it should be implemented.
Okuji
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-08-10 0:41 ` Omniflux
2005-08-12 10:51 ` Vladimir Serbinenko
2005-08-12 16:01 ` Marco Gerards
@ 2005-09-03 17:08 ` Yoshinori K. Okuji
2005-09-03 23:12 ` Marco Gerards
2005-09-04 0:59 ` Omniflux
2 siblings, 2 replies; 15+ messages in thread
From: Yoshinori K. Okuji @ 2005-09-03 17:08 UTC (permalink / raw)
To: The development of GRUB 2
On Wednesday 10 August 2005 02:41, Omniflux wrote:
> It's been a few months, but here are some updated patches.
I've checked in your patch with some modification right now. I changed these
below:
- I removed EXPORT_FUNC from terminfo.h. EXPORT_FUNC is required only if you
want to export symbols from the kernel.
- I moved the inline functions in serial.h to serial.c, because they are not
used outside.
- I fixed bad indentation.
- I removed odd const qualifiers to integers.
- I fixed a memory leak in the serial command.
I might have changed some other minor things as well.
For now, terminfo.c has code of interpreting terminfo, but supports only
vt100. Do you intend to fix this?
Okuji
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-09-03 17:08 ` Yoshinori K. Okuji
@ 2005-09-03 23:12 ` Marco Gerards
2005-09-11 19:46 ` Yoshinori K. Okuji
2005-09-04 0:59 ` Omniflux
1 sibling, 1 reply; 15+ messages in thread
From: Marco Gerards @ 2005-09-03 23:12 UTC (permalink / raw)
To: The development of GRUB 2
"Yoshinori K. Okuji" <okuji@enbug.org> writes:
> On Wednesday 10 August 2005 02:41, Omniflux wrote:
>> It's been a few months, but here are some updated patches.
>
> I've checked in your patch with some modification right now. I changed these
> below:
[...]
Great! :-)
> vt100. Do you intend to fix this?
It would be nice if we could use terminfo for the open firmware
console, which is an ANSI console basically.
--
Marco
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-09-03 17:08 ` Yoshinori K. Okuji
2005-09-03 23:12 ` Marco Gerards
@ 2005-09-04 0:59 ` Omniflux
2005-09-11 19:52 ` Yoshinori K. Okuji
1 sibling, 1 reply; 15+ messages in thread
From: Omniflux @ 2005-09-04 0:59 UTC (permalink / raw)
To: The development of GRUB 2
Yoshinori K. Okuji wrote:
> For now, terminfo.c has code of interpreting terminfo, but supports only
> vt100. Do you intend to fix this?
Yes, but I do not know how I should do this. As the comment in the file
says...
/* TODO
* Lookup user specified terminfo type (escape code table). If found,
set term variables
* as appropriate. Otherwise return an error.
*
* How should this be done?
* a. A static table included in this module.
* - I do not like this idea.
* b. A table stored in the configuration directory.
* - Users must convert their terminfo settings if we have not
already.
* c. Look for terminfo files in the configuration directory.
* - /usr/share/terminfo is 6.3M on my system.
* - /usr/share/terminfo is not on most users boot partition.
* + Copying the terminfo files you want to use to the grub
* configuration directory is easier then (b).
* d. Your idea here.
*/
Option 'a' is certainly the easiest, but how do I choose which terminals
to support? How do I test them?
Option 'b', choosing which terminals and testing them is no longer my
problem, but this moves all the burden onto the user.
Option 'c', problems as listed above.
If you would like to choose one of these methods, or come up with option
'd', I'll implement it.
--
Omniflux
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-09-03 23:12 ` Marco Gerards
@ 2005-09-11 19:46 ` Yoshinori K. Okuji
0 siblings, 0 replies; 15+ messages in thread
From: Yoshinori K. Okuji @ 2005-09-11 19:46 UTC (permalink / raw)
To: The development of GRUB 2
On Sunday 04 September 2005 01:12 am, Marco Gerards wrote:
> It would be nice if we could use terminfo for the open firmware
> console, which is an ANSI console basically.
Isn't it vt100-compatible? vt100 is also based on ANSI.
Okuji
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: x86 serial support
2005-09-04 0:59 ` Omniflux
@ 2005-09-11 19:52 ` Yoshinori K. Okuji
0 siblings, 0 replies; 15+ messages in thread
From: Yoshinori K. Okuji @ 2005-09-11 19:52 UTC (permalink / raw)
To: The development of GRUB 2
On Sunday 04 September 2005 02:59 am, Omniflux wrote:
> Option 'a' is certainly the easiest, but how do I choose which terminals
> to support? How do I test them?
Having a static table (for all terminals) is clearly nonsense for tparm.c,
since the purpose of this file is to interpret a terminfo file. If we embed
binary code, there is no reason to have such interpretation code.
> Option 'b', choosing which terminals and testing them is no longer my
> problem, but this moves all the burden onto the user.
I think you know this, but GRUB Legacy uses this way. For now, I think this is
the best way, since most terminals are vt100-compatible, and the user does
not have to do anything in this case.
> Option 'c', problems as listed above.
For me, this sounds overkill.
Okuji
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2005-09-11 20:00 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-02-21 12:38 x86 serial support Omniflux
2005-03-02 21:33 ` Yoshinori K. Okuji
2005-08-10 0:41 ` Omniflux
2005-08-12 10:51 ` Vladimir Serbinenko
2005-08-12 16:01 ` Marco Gerards
2005-08-12 20:17 ` Yoshinori K. Okuji
2005-08-12 22:19 ` Douglas Wade Needham
2005-08-12 22:18 ` Omniflux
2005-08-14 13:03 ` Marco Gerards
2005-08-14 14:54 ` Yoshinori K. Okuji
2005-09-03 17:08 ` Yoshinori K. Okuji
2005-09-03 23:12 ` Marco Gerards
2005-09-11 19:46 ` Yoshinori K. Okuji
2005-09-04 0:59 ` Omniflux
2005-09-11 19:52 ` Yoshinori K. Okuji
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.