summaryrefslogtreecommitdiff
path: root/usr/src/grub
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2014-12-16 20:52:41 +0000
committerRobert Mustacchi <rm@joyent.com>2016-04-08 13:26:43 -0700
commit5626beece2e5dedec7197ecf325cfaa1854a6c2e (patch)
tree8a03ad469edde65a2a9b506c38f7245946d87eda /usr/src/grub
parent78c0f49e8991772ff264f861afa37ac436bf9b28 (diff)
downloadillumos-joyent-5626beece2e5dedec7197ecf325cfaa1854a6c2e.tar.gz
6834 GRUB tries to use nonexistent serial port
6835 GRUB should allow multiple serial consoles Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> Approved by: Richard Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src/grub')
-rw-r--r--usr/src/grub/grub-0.97/stage2/builtins.c92
-rw-r--r--usr/src/grub/grub-0.97/stage2/serial.c14
-rw-r--r--usr/src/grub/grub-0.97/stage2/serial.h6
3 files changed, 89 insertions, 23 deletions
diff --git a/usr/src/grub/grub-0.97/stage2/builtins.c b/usr/src/grub/grub-0.97/stage2/builtins.c
index 9cc05dc99b..77800ff4b1 100644
--- a/usr/src/grub/grub-0.97/stage2/builtins.c
+++ b/usr/src/grub/grub-0.97/stage2/builtins.c
@@ -4057,12 +4057,20 @@ static struct builtin builtin_savedefault =
static int
serial_func (char *arg, int flags)
{
- unsigned short port = serial_hw_get_port (0);
+ int i;
+ int units[SERIAL_MAX_PORTS];
+ unsigned short ports[SERIAL_MAX_PORTS];
unsigned int speed = 9600;
int word_len = UART_8BITS_WORD;
int parity = UART_NO_PARITY;
int stop_bit_len = UART_1_STOP_BIT;
+ for (i = 0; i < SERIAL_MAX_PORTS; ++i)
+ {
+ units[i] = -1;
+ ports[i] = 0;
+ }
+
/* Process GNU-style long options.
FIXME: We should implement a getopt-like function, to avoid
duplications. */
@@ -4072,17 +4080,28 @@ serial_func (char *arg, int flags)
{
char *p = arg + sizeof ("--unit=") - 1;
int unit;
-
- if (! safe_parse_maxint (&p, &unit))
- return 1;
-
- if (unit < 0 || unit > 3)
+
+ i = 0;
+ do
{
- errnum = ERR_DEV_VALUES;
- return 1;
- }
+ if (i >= SERIAL_MAX_PORTS)
+ {
+ errnum = ERR_DEV_FORMAT;
+ return 1;
+ }
+
+ if (! safe_parse_maxint (&p, &unit))
+ return 1;
+
+ if (unit < 0 || unit > 3)
+ {
+ errnum = ERR_DEV_VALUES;
+ return 1;
+ }
- port = serial_hw_get_port (unit);
+ units[i++] = unit;
+ }
+ while (*p++ == ',');
}
else if (grub_memcmp (arg, "--speed=", sizeof ("--speed=") - 1) == 0)
{
@@ -4098,11 +4117,28 @@ serial_func (char *arg, int flags)
{
char *p = arg + sizeof ("--port=") - 1;
int num;
-
- if (! safe_parse_maxint (&p, &num))
- return 1;
- port = (unsigned short) num;
+ i = 0;
+ do
+ {
+ if (i >= SERIAL_MAX_PORTS)
+ {
+ errnum = ERR_DEV_FORMAT;
+ return 1;
+ }
+
+ if (! safe_parse_maxint (&p, &num))
+ return 1;
+
+ if (num > 0xffff || num <= 0)
+ {
+ errnum = ERR_DEV_VALUES;
+ return 1;
+ }
+
+ ports[i++] = (unsigned short) num;
+ }
+ while (*p++ == ',');
}
else if (grub_memcmp (arg, "--word=", sizeof ("--word=") - 1) == 0)
{
@@ -4178,8 +4214,21 @@ serial_func (char *arg, int flags)
arg = skip_to (0, arg);
}
- /* Initialize the serial unit. */
- if (! serial_hw_init (port, speed, word_len, parity, stop_bit_len))
+ if (units[0] == -1 && ports[0] == 0)
+ units[0] = 0;
+
+ for (i = 0; i < SERIAL_MAX_PORTS; ++i)
+ {
+ if (units[i] != -1)
+ ports[i] = serial_hw_get_port (units[i]);
+ if (ports[i] == 0)
+ continue;
+
+ if (serial_hw_init (ports[i], speed, word_len, parity, stop_bit_len))
+ break;
+ }
+
+ if (i >= SERIAL_MAX_PORTS)
{
errnum = ERR_BAD_ARGUMENT;
return 1;
@@ -4193,14 +4242,17 @@ static struct builtin builtin_serial =
"serial",
serial_func,
BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
- "serial [--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]",
+ "serial [[--unit=UNIT[,UNIT...]] | [--port=PORT[,PORT...]]] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]",
"Initialize a serial device. UNIT is a digit that specifies which serial"
- " device is used (e.g. 0 == COM1). If you need to specify the port number,"
- " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length,"
+ " device is used (e.g. 0 == ttya (aka COM1)). If you need to specify the port"
+ " number, set it by --port. Either but not both of --unit and --port is"
+ " permitted; --unit takes precedence. Multiple devices may be specified,"
+ " separated by commas; the first working device in the list will be used"
+ " and the rest ignored. SPEED is the DTE-DTE speed. WORD is the word length,"
" PARITY is the type of parity, which is one of `no', `odd' and `even'."
" STOP is the length of stop bit(s). The option --device can be used only"
" in the grub shell, which specifies the file name of a tty device. The"
- " default values are COM1, 9600, 8N1."
+ " default values are ttya, 9600, 8N1."
};
#endif /* SUPPORT_SERIAL */
diff --git a/usr/src/grub/grub-0.97/stage2/serial.c b/usr/src/grub/grub-0.97/stage2/serial.c
index 4e120e000d..b9f27bc581 100644
--- a/usr/src/grub/grub-0.97/stage2/serial.c
+++ b/usr/src/grub/grub-0.97/stage2/serial.c
@@ -141,6 +141,16 @@ serial_hw_init (unsigned short port, unsigned int speed,
int i;
unsigned short div = 0;
unsigned char status = 0;
+
+ if (port == 0)
+ return 0;
+
+ /* Make sure the port actually exists. */
+ outb (port + UART_SR, UART_SR_TEST);
+ outb (port + UART_FCR, 0);
+ status = inb (port + UART_SR);
+ if (status != UART_SR_TEST)
+ return 0;
/* Turn off the interrupt. */
outb (port + UART_IER, 0);
@@ -163,7 +173,7 @@ serial_hw_init (unsigned short port, unsigned int speed,
outb (port + UART_DLH, div >> 8);
/* Set the line status. */
- status |= parity | word_len | stop_bit_len;
+ status = parity | word_len | stop_bit_len;
outb (port + UART_LCR, status);
/* Enable the FIFO. */
@@ -186,8 +196,6 @@ serial_hw_init (unsigned short port, unsigned int speed,
{
term_table[i].flags &= ~TERM_NEED_INIT;
}
-
- /* FIXME: should check if the serial terminal was found. */
return 1;
}
diff --git a/usr/src/grub/grub-0.97/stage2/serial.h b/usr/src/grub/grub-0.97/stage2/serial.h
index 76c222720d..19f7be6e63 100644
--- a/usr/src/grub/grub-0.97/stage2/serial.h
+++ b/usr/src/grub/grub-0.97/stage2/serial.h
@@ -23,6 +23,9 @@
/* Macros. */
+/* The maximum number of ports we ever try to use. */
+#define SERIAL_MAX_PORTS 4
+
/* The offsets of UART registers. */
#define UART_TX 0
#define UART_RX 0
@@ -65,6 +68,9 @@
/* Turn on DTR, RTS, and OUT2. */
#define UART_ENABLE_MODEM 0x0B
+/* Arbitrary pattern to write during existence testing. */
+#define UART_SR_TEST 0x4F
+
/* Function prototypes. */