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; + +--