diff --git a/additional-lib-functions.diff b/additional-lib-functions.diff
new file mode 100644
index 0000000..bb9fa13
--- /dev/null
+++ b/additional-lib-functions.diff
@@ -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);
+
+--
diff --git a/console-boot-parameter.diff b/console-boot-parameter.diff
new file mode 100644
index 0000000..1e6c04d
--- /dev/null
+++ b/console-boot-parameter.diff
@@ -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=" 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);
+
+--
diff --git a/memtest86+.spec b/memtest86+.spec
index 535d6a2..ca66c80 100644
--- a/memtest86+.spec
+++ b/memtest86+.spec
@@ -6,7 +6,7 @@
Summary: Stand-alone memory tester for x86 and x86-64 computers
Name: memtest86+
Version: 1.70
-Release: 1%{?dist}
+Release: 2%{?dist}
License: GPL
ExclusiveArch: %{ix86} x86_64
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
Source1: new-memtest-pkg
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
# require glibc-devel.i386 via this file:
BuildRequires: %{_includedir}/gnu/stubs-32.h
@@ -30,6 +34,9 @@ Run 'memtest-setup' to add to your GRUB or lilo boot menu.
%prep
%setup -q
+%patch0 -p1
+%patch1 -p1
+%patch2 -p1
%build
# Regular build flags not wanted for this binary
@@ -61,6 +68,9 @@ rm -rf $RPM_BUILD_ROOT
/sbin/new-memtest-pkg --remove %{version}
%changelog
+* Wed Oct 17 2007 Warren Togami - 1.70-2
+- mschmidt's boot time configuration of serial console (#319631)
+
* Thu Feb 08 2007 Florian La Roche - 1.70-1
- update to 1.70
diff --git a/use-strtoul-in-getval.diff b/use-strtoul-in-getval.diff
new file mode 100644
index 0000000..e3ee57d
--- /dev/null
+++ b/use-strtoul-in-getval.diff
@@ -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;
+
+--