diff options
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 518 |
1 files changed, 270 insertions, 248 deletions
@@ -1,30 +1,25 @@ -/* lib.c - MemTest-86 Version 3.0 +/* lib.c - MemTest-86 Version 3.4 * * Released under version 2 of the Gnu Public License. - * By Chris Brady, cbrady@sgi.com - * ---------------------------------------------------- - * MemTest86+ V4.00 Specific code (GPL V2.0) - * By Samuel DEMEULEMEESTER, memtest@memtest.org - * http://www.canardplus.com - http://www.memtest.org -*/ - + * By Chris Brady + */ #include "io.h" #include "serial.h" #include "test.h" #include "config.h" #include "screen_buffer.h" +#include "stdint.h" +#include "cpuid.h" #include "smp.h" -#define NULL 0 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, 0x3e8, 0x2e8}; +const short serial_base_ports[] = {0x3f8, 0x2f8}; #if ((115200%SERIAL_BAUD_RATE) != 0) #error Bad default baud rate @@ -33,53 +28,55 @@ int serial_baud_rate = SERIAL_BAUD_RATE; unsigned char serial_parity = 0; unsigned char serial_bits = 8; -char buf[18]; - struct ascii_map_str { - int ascii; - int keycode; + int ascii; + int keycode; }; -char *codes[] = { - " Divide", - " Debug", - " NMI", - " Brkpnt", - "Overflow", - " Bound", - " Inv_Op", - " No_Math", - "Double_Fault", - "Seg_Over", - " Inv_TSS", - " Seg_NP", - "Stack_Fault", - "Gen_Prot", - "Page_Fault", - " Resvd", - " FPE", - "Alignment", - " Mch_Chk", - "SIMD FPE" -}; +inline void reboot(void) +{ + + /* tell the BIOS to do a cold start */ + *((unsigned short *)0x472) = 0x0; + + while(1) + { + outb(0xFE, 0x64); + outb(0x02, 0xcf9); /* reset that doesn't rely on the keyboard controller */ + outb(0x04, 0xcf9); + outb(0x0E, 0xcf9); + } +} -struct eregs { - ulong ss; - ulong ds; - ulong esp; - ulong ebp; - ulong esi; - ulong edi; - ulong edx; - ulong ecx; - ulong ebx; - ulong eax; - ulong vect; - ulong code; - ulong eip; - ulong cs; - ulong eflag; -}; +int strlen(char * string){ + int i=0; + while(*string++){i++;}; + return i; +} + +int strstr(char *haystack, char * needle) +{ + int i=0,j=0; + int here=0; + while(1){ + if(needle[i]==haystack[j]) + { + if(here==0) + here=j; + i++;j++; + if(i>=strlen(needle)) + { + return here; + } + if(j>=strlen(haystack)) + { + return -1; + } + } else { + j++;i=0;here=0; + } + } +} int memcmp(const void *s1, const void *s2, ulong count) { @@ -93,19 +90,6 @@ int memcmp(const void *s1, const void *s2, ulong count) return 0; } -void memcpy (void *dst, void *src, int len) -{ - char *s = (char*)src; - char *d = (char*)dst; - int i; - - if (len <= 0) { - return; - } - for (i = 0 ; i < len; i++) { - *d++ = *s++; - } -} int strncmp(const char *s1, const char *s2, ulong n) { signed char res = 0; while (n) { @@ -183,12 +167,11 @@ unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) { return result; } - /* * Scroll the error message area of the screen as needed * Starts at line LINE_SCROLL and ends at line 23 */ -void scroll(void) +void scroll(void) { int i, j; char *s, tmp; @@ -201,23 +184,23 @@ void scroll(void) while (slock) { check_input(); } - for (i=LINE_SCROLL; i<23; i++) { + for (i=LINE_SCROLL; i<23; i++) { s = (char *)(SCREEN_ADR + ((i+1) * 160)); for (j=0; j<160; j+=2, s+=2) { *(s-160) = *s; - tmp = get_scrn_buf(i+1, j/2); - set_scrn_buf(i, j/2, tmp); + tmp = get_scrn_buf(i+1, j/2); + set_scrn_buf(i, j/2, tmp); } } /* Clear the newly opened line */ s = (char *)(SCREEN_ADR + (23 * 160)); for (j=0; j<80; j++) { *s = ' '; - set_scrn_buf(23, j, ' '); + set_scrn_buf(23, j, ' '); s += 2; } - tty_print_region(LINE_SCROLL, 0, 23, 79); - } + tty_print_region(LINE_SCROLL, 0, 23, 79); + } } /* @@ -236,6 +219,17 @@ void clear_scroll(void) } /* + * Place a single character on screen + */ +void cplace(int y, int x, const char c) +{ + char *dptr; + + dptr = (char *)(SCREEN_ADR + (160*y) + (2*x)); + *dptr = c; +} + +/* * Print characters on screen */ void cprint(int y, int x, const char *text) @@ -247,37 +241,50 @@ void cprint(int y, int x, const char *text) for (i=0; text[i]; i++) { *dptr = text[i]; dptr += 2; - } - tty_print_line(y, x, text); + } + tty_print_line(y, x, text); } -void itoa(char s[], int n) +void itoa(char s[], int n) { - int i, sign; - - if((sign = n) < 0) - n = -n; - i=0; - do { - s[i++] = n % 10 + '0'; - } while ((n /= 10) > 0); - if(sign < 0) - s[i++] = '-'; - s[i] = '\0'; - reverse(s); + int i, sign; + + if((sign = n) < 0) + n = -n; + i=0; + do { + s[i++] = n % 10 + '0'; + } while ((n /= 10) > 0); + if(sign < 0) + s[i++] = '-'; + s[i] = '\0'; + reverse(s); } void reverse(char s[]) { - int c, i, j; - for(j = 0; s[j] != 0; j++) - ; - - for(i=0, j = j - 1; i < j; i++, j--) { - c = s[i]; - s[i] = s[j]; - s[j] = c; + int c, i, j; + for(j = 0; s[j] != 0; j++) + ; + + for(i=0, j = j - 1; i < j; i++, j--) { + c = s[i]; + s[i] = s[j]; + s[j] = c; + } +} +void memcpy (void *dst, void *src, int len) +{ + char *s = (char*)src; + char *d = (char*)dst; + int i; + + if (len <= 0) { + return; } + for (i = 0 ; i < len; i++) { + *d++ = *s++; + } } /* @@ -311,6 +318,7 @@ void dprint(int y, int x, ulong val, int len, int right) { ulong j, k; int i, flag=0; + char buf[18]; if (val > 999999999 || len > 9) { return; @@ -343,16 +351,16 @@ void dprint(int y, int x, ulong val, int len, int right) continue; } if (k == 0 && flag == 0) { - continue; + continue; } buf[i++] = k + '0'; val -= k * j; } else { - if (flag == 0 && i < len-1) { - buf[i++] = '0'; - } else { - buf[i++] = ' '; - } + if (flag == 0 && i < len-1) { + buf[i++] = '0'; + } else { + buf[i++] = ' '; + } } flag++; } @@ -361,56 +369,38 @@ void dprint(int y, int x, ulong val, int len, int right) cprint(y,x,buf); } - -/* - * Get_number of digits - */ -int getnum(ulong val) -{ - int len = 0; - int i = 1; - - while(i <= val) - { - len++; - i *= 10; - } - - return len; - -} - /* * Print a hex number on screen at least digits long */ void hprint2(int y,int x, unsigned long val, int digits) { - unsigned long j; - int i, idx, flag = 0; + unsigned long j; + int i, idx, flag = 0; + char buf[18]; for (i=0, idx=0; i<8; i++) { j = val >> (28 - (4 * i)); - j &= 0xf; - if (j < 10) { - if (flag || j || i == 7) { - buf[idx++] = j + '0'; - flag++; - } else { - buf[idx++] = '0'; - } - } else { - buf[idx++] = j + 'a' - 10; - flag++; - } - } - if (digits > 8) { - digits = 8; - } - if (flag > digits) { - digits = flag; + j &= 0xf; + if (j < 10) { + if (flag || j || i == 7) { + buf[idx++] = j + '0'; + flag++; + } else { + buf[idx++] = '0'; + } + } else { + buf[idx++] = j + 'a' - 10; + flag++; + } } + if (digits > 8) { + digits = 8; + } + if (flag > digits) { + digits = flag; + } buf[idx] = 0; - cprint(y,x,buf + (idx - digits)); + cprint(y,x,buf + (idx - digits)); } /* @@ -420,7 +410,7 @@ void hprint3(int y,int x, unsigned long val, int digits) { unsigned long j; int i, idx, flag = 0; - + char buf[18]; for (i=0, idx=0; i<digits; i++) { j = 0xf & val; @@ -455,7 +445,7 @@ void hprint(int y, int x, unsigned long val) */ void xprint(int y,int x, ulong val) { - ulong j; + ulong j; j = (val & 0xffc00000) >> 20; dprint(y, x, j, 4, 0); @@ -467,12 +457,54 @@ void xprint(int y,int x, ulong val) dprint(y, x+10, j, 4, 0); } +char *codes[] = { + " Divide", + " Debug", + " NMI", + " Brkpnt", + "Overflow", + " Bound", + " Inv_Op", + " No_Math", + "Double_Fault", + "Seg_Over", + " Inv_TSS", + " Seg_NP", + "Stack_Fault", + "Gen_Prot", + "Page_Fault", + " Resvd", + " FPE", + "Alignment", + " Mch_Chk", + "SIMD FPE" +}; + +struct eregs { + ulong ss; + ulong ds; + ulong esp; + ulong ebp; + ulong esi; + ulong edi; + ulong edx; + ulong ecx; + ulong ebx; + ulong eax; + ulong vect; + ulong code; + ulong eip; + ulong cs; + ulong eflag; +}; + /* Handle an interrupt */ void inter(struct eregs *trap_regs) { int i, line; unsigned char *pp; ulong address = 0; + int my_cpu_num = smp_my_cpu_num(); /* Get the page fault address */ if (trap_regs->vect == 14) { @@ -488,13 +520,14 @@ void inter(struct eregs *trap_regs) #endif /* clear scrolling region */ - pp=(unsigned char *)(SCREEN_ADR+(2*80*(LINE_SCROLL-2))); - for(i=0; i<2*80*(24-LINE_SCROLL-2); i++, pp+=2) { - *pp = ' '; - } + pp=(unsigned char *)(SCREEN_ADR+(2*80*(LINE_SCROLL-2))); + for(i=0; i<2*80*(24-LINE_SCROLL-2); i++, pp+=2) { + *pp = ' '; + } line = LINE_SCROLL-2; - cprint(line, 0, "Unexpected Interrupt - Halting"); + cprint(line, 0, "Unexpected Interrupt - Halting CPU"); + dprint(line, COL_MID + 4, my_cpu_num, 2, 1); cprint(line+2, 0, " Type: "); if (trap_regs->vect <= 19) { cprint(line+2, 7, codes[trap_regs->vect]); @@ -509,6 +542,10 @@ void inter(struct eregs *trap_regs) hprint(line+5, 7, trap_regs->eflag); cprint(line+6, 0, " Code: "); hprint(line+6, 7, trap_regs->code); + cprint(line+7, 0, " DS: "); + hprint(line+7, 7, trap_regs->ds); + cprint(line+8, 0, " SS: "); + hprint(line+8, 7, trap_regs->ss); if (trap_regs->vect == 14) { /* Page fault address */ cprint(line+7, 0, " Addr: "); @@ -531,21 +568,18 @@ void inter(struct eregs *trap_regs) hprint(line+8, 25, trap_regs->ebp); cprint(line+9, 20, "esp: "); hprint(line+9, 25, trap_regs->esp); - cprint(line+7, 0, " DS: "); - hprint(line+7, 7, trap_regs->ds); - cprint(line+8, 0, " SS: "); - hprint(line+8, 7, trap_regs->ss); + cprint(line+1, 38, "Stack:"); - for (i=0; i<12; i++) { + for (i=0; i<10; i++) { hprint(line+2+i, 38, trap_regs->esp+(4*i)); hprint(line+2+i, 47, *(ulong*)(trap_regs->esp+(4*i))); - hprint(line+2+i, 57, trap_regs->esp+(4*(i+12))); - hprint(line+2+i, 66, *(ulong*)(trap_regs->esp+(4*(i+12)))); + hprint(line+2+i, 57, trap_regs->esp+(4*(i+10))); + hprint(line+2+i, 66, *(ulong*)(trap_regs->esp+(4*(i+10)))); } cprint(line+11, 0, "CS:EIP: "); pp = (unsigned char *)trap_regs->eip; - for(i = 0; i < 10; i++) { + for(i = 0; i < 9; i++) { hprint2(line+11, 8+(3*i), pp[i], 2); } @@ -554,22 +588,14 @@ void inter(struct eregs *trap_regs) } } -void set_cache(int val) +void set_cache(int val) { - extern struct cpu_ident cpu_id; - /* 386's don't have a cache */ - if ((cpu_id.cpuid < 1) && (cpu_id.type == 3)) { - cprint(LINE_INFO, COL_CACHE, "none"); - return; - } switch(val) { case 0: - cache_off(); - cprint(LINE_INFO, COL_CACHE, "off"); + cache_off(); break; case 1: cache_on(); - cprint(LINE_INFO, COL_CACHE, " on"); break; } } @@ -603,13 +629,10 @@ void check_input(void) if ((c = get_key())) { switch(c & 0x7f) { - case 1: + case 1: /* "ESC" key was pressed, bail out. */ cprint(LINE_RANGE, COL_MID+23, "Halting... "); - - /* tell the BIOS to do a warm start */ - *((unsigned short *)0x472) = 0x1234; - outb(0xfe,0x64); + reboot(); break; case 46: /* c - Configure */ @@ -635,9 +658,9 @@ void check_input(void) void footer() { - cprint(24, 0, "(ESC)Reboot (c)configuration (SP)scroll_lock (CR)scroll_unlock"); + cprint(24, 0, "(ESC)exit (c)configuration (SP)scroll_lock (CR)scroll_unlock"); if (slock) { - cprint(24, 74, "LOCKED"); + cprint(24, 74, "Locked"); } else { cprint(24, 74, " "); } @@ -657,7 +680,7 @@ ulong getval(int x, int y, int result_shift) buf[i] = ' '; } buf[sizeof(buf)/sizeof(buf[0]) -1] = '\0'; - + wait_keyup(); done = 0; n = 0; @@ -711,7 +734,7 @@ ulong getval(int x, int y, int result_shift) } /* Don't allow anything to be entered after a suffix */ if (n > 0 && ( - (buf[n-1] == 'p') || (buf[n-1] == 'g') || + (buf[n-1] == 'p') || (buf[n-1] == 'g') || (buf[n-1] == 'm') || (buf[n-1] == 'k'))) { buf[n] = ' '; } @@ -743,7 +766,7 @@ ulong getval(int x, int y, int result_shift) shift -= result_shift; /* Compute our current value */ - val = simple_strtoul(buf, NULL, base); + val = simple_strtoul(buf, 0, base); if (shift > 0) { if (shift >= 32) { val = 0xffffffff; @@ -765,7 +788,7 @@ void ttyprint(int y, int x, const char *p) { static char sx[3]; static char sy[3]; - + sx[0]='\0'; sy[0]='\0'; x++; y++; @@ -779,11 +802,10 @@ void ttyprint(int y, int x, const char *p) serial_echo_print(p); } - void serial_echo_init(void) { int comstat, hi, lo, serial_div; - unsigned char lcr; + unsigned char lcr; /* read the Divisor Latch */ comstat = serial_echo_inb(UART_LCR); @@ -801,18 +823,36 @@ void serial_echo_init(void) serial_echo_outb((serial_div >> 8) & 0xff, UART_DLM); serial_echo_outb(lcr, UART_LCR); /* Done with divisor */ - /* Prior to disabling interrupts, read the LSR and RBR * registers */ comstat = serial_echo_inb(UART_LSR); /* COM? LSR */ comstat = serial_echo_inb(UART_RX); /* COM? RBR */ serial_echo_outb(0x00, UART_IER); /* Disable all interrupts */ - clear_screen_buf(); + clear_screen_buf(); return; } +/* + * Get_number of digits + */ +int getnum(ulong val) +{ + int len = 0; + int i = 1; + + while(i <= val) + { + len++; + i *= 10; + } + + return len; + +} + + void serial_echo_print(const char *p) { if (!serial_cons) { @@ -841,9 +881,9 @@ void serial_echo_print(const char *p) */ struct ascii_map_str ser_map[] = /*ascii keycode ascii keycode*/ -{ +{ /* Special cases come first so I can leave - * their "normal" mapping in the table, + * their ``normal'' mapping in the table, * without it being activated. */ { 27, 0x01}, /* ^[/ESC -> ESC */ @@ -1026,7 +1066,6 @@ void wait_keyup( void ) { } } - /* * Handles "console=<param>" command line option * @@ -1053,8 +1092,8 @@ void serial_console_setup(char *param) if (option == param) return; /* there were no digits */ - if (tty > 3) - return; /* only ttyS0 to ttyS3 supported */ + if (tty > 1) + return; /* only ttyS0 and ttyS1 supported */ if (*option == '\0' || *option == ' ') goto save_tty; /* no options given, just ttyS? */ @@ -1102,76 +1141,59 @@ void serial_console_setup(char *param) end++; - if (*end != '\0' && *end != ' ') + if (*end != '\0' || *end != ' ') return; /* garbage at the end */ serial_bits = bits; - save_parity: + save_parity: serial_parity = parity; - save_baud_rate: + save_baud_rate: serial_baud_rate = (int) baud_rate; - save_tty: + save_tty: serial_tty = (short) tty; serial_cons = 1; } - -#ifdef LP -#define DATA 0x00 -#define STATUS 0x01 -#define CONTROL 0x02 - -#define LP_PBUSY 0x80 /* inverted input, active high */ -#define LP_PERRORP 0x08 /* unchanged input, active low */ - -#define LP_PSELECP 0x08 /* inverted output, active low */ -#define LP_PINITP 0x04 /* unchanged output, active low */ -#define LP_PSTROBE 0x01 /* short high output on raising edge */ - -#define DELAY 0x10c6ul - -void lp_wait(ulong xloops) -{ - int d0; - __asm__("mull %0" - :"=d" (xloops), "=&a" (d0) - :"1" (xloops),"0" (current_cpu_data.loops_per_sec)); - __delay(xloops); -} -static void __delay(ulong loops) +/* Get a comma seperated list of numbers */ +void get_list(int x, int y, int len, char *buf) { - int d0; - __asm__ __volatile__( - "\tjmp 1f\n" - ".align 16\n" - "1:\tjmp 2f\n" - ".align 16\n" - "2:\tdecl %0\n\tjns 2b" - :"=&a" (d0) - :"0" (loops)); -} + int c, n = 0; -put_lp(char c, short port) -{ - unsigned char status; - - /* Wait for printer to be ready */ - while (1) { - status = inb(STATUS(port)); - if (status & LP_PERRORP) { - if (status & LP_PBUSY) { - break; + len--; + wait_keyup(); + while(1) { + /* Read a new character and process it */ + c = get_key(); + switch(c) { + case 0x1c: /* CR */ + /* If something has been entered we are done */ + if(n) { + buf[n] = 0; + return; + } + break; + case 0x0e: /* BS */ + if (n > 0) { + n -= 1; + buf[n] = ' '; } + break; + case 0x0B: buf[n++] = '0'; break; + case 0x02: buf[n++] = '1'; break; + case 0x03: buf[n++] = '2'; break; + case 0x04: buf[n++] = '3'; break; + case 0x05: buf[n++] = '4'; break; + case 0x06: buf[n++] = '5'; break; + case 0x07: buf[n++] = '6'; break; + case 0x08: buf[n++] = '7'; break; + case 0x09: buf[n++] = '8'; break; + case 0x0a: buf[n++] = '9'; break; + case 0x33: buf[n++] = ','; break; + } + cprint(x, y, buf); + if (n >= len) { + buf[n] = 0; + return; } } - - outb(d, DATA(c)); - lp_wait(DELAY); - outb((LP_PSELECP | LP_PINITP | LP_PSTROBE), CONTROL(port)); - lp_wait(DELAY); - outb((LP_PSELECP | LP_PINITP), CONTROL(port)); - lp_wait(DELAY); -} - -#endif - +}
\ No newline at end of file |