mschmidt's boot time configuration of serial console (#319631)

This commit is contained in:
Warren Togami 2007-10-17 17:58:03 +00:00
parent e9d378a849
commit 018b917ac8
4 changed files with 382 additions and 1 deletions

View File

@ -0,0 +1,101 @@
This adds several standard C functions to lib.c:
strncmp, toupper, isdigit, isxdigit
simple_strtoul is a limited implementation of strtoul, taken from Linux.
They will be needed for command line parsing.
Index: memtest86+-1.70/lib.c
===================================================================
--- memtest86+-1.70.orig/lib.c
+++ memtest86+-1.70/lib.c
@@ -69,6 +69,21 @@ int memcmp(const void *s1, const void *s
return 0;
}
+int strncmp(const char *s1, const char *s2, ulong n)
+{
+ signed char res = 0;
+ while (n) {
+ res = *s1 - *s2;
+ if (res != 0)
+ return res;
+ if (*s1 == '\0')
+ return 0;
+ ++s1, ++s2;
+ --n;
+ }
+ return res;
+}
+
void *memmove(void *dest, const void *src, ulong n)
{
long i;
@@ -87,6 +102,53 @@ void *memmove(void *dest, const void *sr
}
return dest;
}
+
+char toupper(char c)
+{
+ if (c >= 'a' && c <= 'z')
+ return c + 'A' -'a';
+ else
+ return c;
+}
+
+int isdigit(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+int isxdigit(char c)
+{
+ return isdigit(c) || (toupper(c) >= 'A' && toupper(c) <= 'F');
+}
+
+unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
+{
+ unsigned long result = 0, value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if (toupper(*cp) == 'X' && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ } else if (base == 16) {
+ if (cp[0] == '0' && toupper(cp[1]) == 'X')
+ cp += 2;
+ }
+ while (isxdigit(*cp) &&
+ (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
/*
* Scroll the error message area of the screen as needed
* Starts at line LINE_SCROLL and ends at line 23
Index: memtest86+-1.70/test.h
===================================================================
--- memtest86+-1.70.orig/test.h
+++ memtest86+-1.70/test.h
@@ -95,6 +95,7 @@ typedef unsigned long ulong;
#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); })
int memcmp(const void *s1, const void *s2, ulong count);
void *memmove(void *dest, const void *src, ulong n);
+int strncmp(const char *s1, const char *s2, ulong n);
int query_linuxbios(void);
int query_pcbios(void);
int insertaddress(ulong);
--

239
console-boot-parameter.diff Normal file
View File

@ -0,0 +1,239 @@
Make the serial console port and its baudrate configurable on the bootloader
(e.g GRUB) command line.
The parameter format is similar to Linux's. Examples:
console=ttyS0 # to enable serial console on the first serial port
console=ttyS1 # second serial port
console=ttyS0,38400 # with the given baudrate
Selectable parity, bits, flow control not implemented yet.
Index: memtest86+-1.70/config.h
===================================================================
--- memtest86+-1.70.orig/config.h
+++ memtest86+-1.70/config.h
@@ -15,6 +15,9 @@
/* to enable. */
#define SERIAL_CONSOLE_DEFAULT 0
+/* SERIAL_TTY - The default serial port to use. 0=ttyS0, 1=ttyS1 */
+#define SERIAL_TTY 0
+
/* SERIAL_BAUD_RATE - Baud rate for the serial console */
#define SERIAL_BAUD_RATE 9600
Index: memtest86+-1.70/lib.c
===================================================================
--- memtest86+-1.70.orig/lib.c
+++ memtest86+-1.70/lib.c
@@ -11,6 +11,18 @@
int slock = 0, lsr = 0;
short serial_cons = SERIAL_CONSOLE_DEFAULT;
+
+#if SERIAL_TTY != 0 && SERIAL_TTY != 1
+#error Bad SERIAL_TTY. Only ttyS0 and ttyS1 are supported.
+#endif
+short serial_tty = SERIAL_TTY;
+const short serial_base_ports[] = {0x3f8, 0x2f8};
+
+#if ((115200%SERIAL_BAUD_RATE) != 0)
+#error Bad default baud rate
+#endif
+int serial_baud_rate = SERIAL_BAUD_RATE;
+
char buf[18];
struct ascii_map_str {
@@ -721,19 +733,9 @@ void ttyprint(int y, int x, const char *
serial_echo_print(p);
}
-#if defined(SERIAL_BAUD_RATE)
-
-#if ((115200%SERIAL_BAUD_RATE) != 0)
-#error Bad ttys0 baud rate
-#endif
-
-#define SERIAL_DIV (115200/SERIAL_BAUD_RATE)
-
-#endif /* SERIAL_BAUD_RATE */
-
void serial_echo_init(void)
{
- int comstat, hi, lo;
+ int comstat, hi, lo, serial_div;
/* read the Divisor Latch */
comstat = serial_echo_inb(UART_LCR);
@@ -744,12 +746,11 @@ void serial_echo_init(void)
/* now do hardwired init */
serial_echo_outb(0x03, UART_LCR); /* No parity, 8 data bits, 1 stop */
-#if defined(SERIAL_BAUD_RATE)
+ serial_div = 115200 / serial_baud_rate;
serial_echo_outb(0x83, UART_LCR); /* Access divisor latch */
- serial_echo_outb(SERIAL_DIV & 0xff, UART_DLL); /* baud rate divisor */
- serial_echo_outb((SERIAL_DIV>> 8) & 0xff, UART_DLM);
+ serial_echo_outb(serial_div & 0xff, UART_DLL); /* baud rate divisor */
+ serial_echo_outb((serial_div >> 8) & 0xff, UART_DLM);
serial_echo_outb(0x03, UART_LCR); /* Done with divisor */
-#endif
/* Prior to disabling interrupts, read the LSR and RBR
* registers */
@@ -974,6 +975,59 @@ void wait_keyup( void ) {
}
}
}
+
+/*
+ * Handles "console=<param>" command line option
+ *
+ * Examples of accepted params:
+ * ttyS0
+ * ttyS1
+ * ttyS0,115200
+ */
+void serial_console_setup(char *param)
+{
+ char *option, *end;
+ unsigned long tty;
+ unsigned long baud_rate;
+
+ if (strncmp(param, "ttyS", 4))
+ return; /* not a serial port */
+
+ param += 4;
+
+ tty = simple_strtoul(param, &option, 10);
+
+ if (option == param)
+ return; /* there were no digits */
+
+ if (tty > 1)
+ return; /* only ttyS0 and ttyS1 supported */
+
+ if (*option == '\0')
+ goto save_tty; /* no options given, just ttyS? */
+
+ if (*option != ',')
+ return; /* missing the comma separator */
+
+ /* baud rate must follow */
+ option++;
+ baud_rate = simple_strtoul(option, &end, 10);
+
+ if (end == option)
+ return; /* no baudrate after comma */
+
+ if (baud_rate == 0 || (115200 % baud_rate) != 0)
+ return; /* wrong baud rate */
+
+ if (*end != '\0')
+ return; /* garbage at the end */
+
+ serial_baud_rate = (int) baud_rate;
+save_tty:
+ serial_tty = (short) tty;
+ serial_cons = 1;
+}
+
#ifdef LP
#define DATA 0x00
#define STATUS 0x01
Index: memtest86+-1.70/main.c
===================================================================
--- memtest86+-1.70.orig/main.c
+++ memtest86+-1.70/main.c
@@ -31,6 +31,7 @@ const struct tseq tseq[] = {
};
char firsttime = 0;
+char cmdline_parsed = 0;
struct vars variables = {};
struct vars * const v = &variables;
@@ -135,12 +136,53 @@ static void run_at(unsigned long addr)
__run_at(run_at_addr);
}
+/* command line passing using the 'old' boot protocol */
+#define MK_PTR(seg,off) ((void*)(((unsigned long)(seg) << 4) + (off)))
+#define OLD_CL_MAGIC_ADDR ((unsigned short*) MK_PTR(INITSEG,0x20))
+#define OLD_CL_MAGIC 0xA33F
+#define OLD_CL_OFFSET_ADDR ((unsigned short*) MK_PTR(INITSEG,0x22))
+
+static void parse_command_line(void)
+{
+ char *cmdline;
+
+ if (cmdline_parsed)
+ return;
+
+ if (*OLD_CL_MAGIC_ADDR != OLD_CL_MAGIC)
+ return;
+
+ unsigned short offset = *OLD_CL_OFFSET_ADDR;
+ cmdline = MK_PTR(INITSEG, offset);
+
+ /* skip leading spaces */
+ while (*cmdline == ' ')
+ cmdline++;
+
+ while (*cmdline) {
+ if (!strncmp(cmdline, "console=", 8)) {
+ cmdline += 8;
+ serial_console_setup(cmdline);
+ }
+
+ /* go to the next parameter */
+ while (*cmdline && *cmdline != ' ')
+ cmdline++;
+ while (*cmdline == ' ')
+ cmdline++;
+ }
+
+ cmdline_parsed = 1;
+}
+
void do_test(void)
{
int i = 0;
unsigned long chunks;
unsigned long lo, hi;
+ parse_command_line();
+
/* If we have a partial relocation finish it */
if (run_at_addr == (unsigned long)&_start) {
run_at_addr = 0xffffffff;
Index: memtest86+-1.70/serial.h
===================================================================
--- memtest86+-1.70.orig/serial.h
+++ memtest86+-1.70/serial.h
@@ -136,8 +136,8 @@
*/
#include "io.h"
-#define serial_echo_outb(v,a) outb((v),(a)+0x3f8)
-#define serial_echo_inb(a) inb((a)+0x3f8)
+#define serial_echo_outb(v,a) outb((v),(a)+serial_base_ports[serial_tty])
+#define serial_echo_inb(a) inb((a)+serial_base_ports[serial_tty])
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
/* Wait for transmitter & holding register to empty */
#define WAIT_FOR_XMITR \
Index: memtest86+-1.70/test.h
===================================================================
--- memtest86+-1.70.orig/test.h
+++ memtest86+-1.70/test.h
@@ -103,6 +103,7 @@ void printpatn(void);
void printpatn(void);
void itoa(char s[], int n);
void reverse(char *p);
+void serial_console_setup(char *param);
void serial_echo_init(void);
void serial_echo_print(const char *s);
void ttyprint(int y, int x, const char *s);
--

View File

@ -6,7 +6,7 @@
Summary: Stand-alone memory tester for x86 and x86-64 computers Summary: Stand-alone memory tester for x86 and x86-64 computers
Name: memtest86+ Name: memtest86+
Version: 1.70 Version: 1.70
Release: 1%{?dist} Release: 2%{?dist}
License: GPL License: GPL
ExclusiveArch: %{ix86} x86_64 ExclusiveArch: %{ix86} x86_64
Group: System Environment/Base Group: System Environment/Base
@ -14,6 +14,10 @@ Source0: http://www.memtest.org/download/1.20/memtest86+-%{version}.tar.gz
URL: http://www.memtest.org URL: http://www.memtest.org
Source1: new-memtest-pkg Source1: new-memtest-pkg
Source2: memtest-setup Source2: memtest-setup
# patches from mschmidt@redhat.com to implement boot-time configurable serial console
Patch0: additional-lib-functions.diff
Patch1: console-boot-parameter.diff
Patch2: use-strtoul-in-getval.diff
Requires(preun): coreutils Requires(preun): coreutils
# require glibc-devel.i386 via this file: # require glibc-devel.i386 via this file:
BuildRequires: %{_includedir}/gnu/stubs-32.h BuildRequires: %{_includedir}/gnu/stubs-32.h
@ -30,6 +34,9 @@ Run 'memtest-setup' to add to your GRUB or lilo boot menu.
%prep %prep
%setup -q %setup -q
%patch0 -p1
%patch1 -p1
%patch2 -p1
%build %build
# Regular build flags not wanted for this binary # Regular build flags not wanted for this binary
@ -61,6 +68,9 @@ rm -rf $RPM_BUILD_ROOT
/sbin/new-memtest-pkg --remove %{version} /sbin/new-memtest-pkg --remove %{version}
%changelog %changelog
* Wed Oct 17 2007 Warren Togami <wtogami@redhat.com> - 1.70-2
- mschmidt's boot time configuration of serial console (#319631)
* Thu Feb 08 2007 Florian La Roche <laroche@redhat.com> - 1.70-1 * Thu Feb 08 2007 Florian La Roche <laroche@redhat.com> - 1.70-1
- update to 1.70 - update to 1.70

View File

@ -0,0 +1,31 @@
Now that we have simple_strtoul() we can use it in getval().
Index: memtest86+-1.70/lib.c
===================================================================
--- memtest86+-1.70.orig/lib.c
+++ memtest86+-1.70/lib.c
@@ -683,21 +683,7 @@ ulong getval(int x, int y, int result_sh
shift -= result_shift;
/* Compute our current value */
- val = 0;
- for(i = (base == 16)? 2: 0; i < n; i++) {
- unsigned long digit = 0;
- if ((buf[i] >= '0') && (buf[i] <= '9')) {
- digit = buf[i] - '0';
- }
- else if ((buf[i] >= 'a') && (buf[i] <= 'f')) {
- digit = buf[i] - 'a' + 10;
- }
- else {
- /* It must be a suffix byte */
- break;
- }
- val = (val * base) + digit;
- }
+ val = simple_strtoul(buf, NULL, base);
if (shift > 0) {
if (shift >= 32) {
val = 0xffffffff;
--