From 2487445f5fad75959681a1b2cd3e597e610e28e6 Mon Sep 17 00:00:00 2001 From: Evgeniy Ivanov Date: Sun, 12 Feb 2012 19:11:47 +0400 Subject: [PATCH] make panic() work for multiboot/elf case . we cannot use the boot monitor to print the system diag buffer . for serial, we do nothing, just reset, everything is already printed . for not-serial, we print the current diag buffer using direct video memory access from the kernel --- kernel/arch/i386/arch_system.c | 59 ++++++------------ kernel/arch/i386/mb_utils.h | 12 ++++ kernel/arch/i386/pre_init.c | 106 +++++++++++++++++++++++++-------- kernel/glo.h | 1 + kernel/utility.c | 8 ++- 5 files changed, 117 insertions(+), 69 deletions(-) create mode 100644 kernel/arch/i386/mb_utils.h diff --git a/kernel/arch/i386/arch_system.c b/kernel/arch/i386/arch_system.c index b4f33ab21..022beac08 100644 --- a/kernel/arch/i386/arch_system.c +++ b/kernel/arch/i386/arch_system.c @@ -25,6 +25,7 @@ #include "oxpcie.h" #include "kernel/proc.h" #include "kernel/debug.h" +#include "mb_utils.h" #include #include "glo.h" @@ -85,15 +86,14 @@ PUBLIC int cpu_has_tsc; PUBLIC __dead void arch_shutdown(int how) { - static char mybuffer[sizeof(params_buffer)]; u16_t magic; vm_stop(); /* Mask all interrupts, including the clock. */ outb( INT_CTLMASK, ~0); -#if USE_BOOTPARAM if(minix_panicing) { + unsigned char unused_ch; /* We're panicing? Then retrieve and decode currently * loaded segment selectors. */ @@ -102,8 +102,22 @@ PUBLIC __dead void arch_shutdown(int how) if(read_ds() != read_ss()) { printseg("ss: ", 0, NULL, read_ss()); } + + /* Printing is done synchronously over serial. */ + if (do_serial_debug) + reset(); + + /* Print accumulated diagnostics buffer and reset. */ + mb_cls(); + mb_print("Minix panic. System diagnostics buffer:\n\n"); + mb_print(kmess_buf); + mb_print("\nSystem has panicked, press any key to reboot"); + while (!mb_read_char(&unused_ch)) + ; + reset(); } +#if USE_BOOTPARAM if (how == RBT_DEFAULT) { how = mon_return ? RBT_HALT : RBT_RESET; } @@ -119,37 +133,7 @@ PUBLIC __dead void arch_shutdown(int how) */ if (how != RBT_MONITOR) arch_set_params("", 1); - if(minix_panicing) { - int source, dest; - const char *lead = "echo \\n*** kernel messages:\\n"; - const int leadlen = strlen(lead); - strcpy(mybuffer, lead); - -#define DECSOURCE source = (source - 1 + _KMESS_BUF_SIZE) % _KMESS_BUF_SIZE - - dest = sizeof(mybuffer)-1; - mybuffer[dest--] = '\0'; - - source = kmess.km_next; - DECSOURCE; - - while(dest >= leadlen) { - const char c = kmess.km_buf[source]; - if(c == '\n') { - mybuffer[dest--] = 'n'; - mybuffer[dest] = '\\'; - } else if(isprint(c) && - c != '\'' && c != '"' && - c != '\\' && c != ';') { - mybuffer[dest] = c; - } else mybuffer[dest] = ' '; - - DECSOURCE; - dest--; - } - arch_set_params(mybuffer, strlen(mybuffer)+1); - } if (mon_return) arch_monitor(); @@ -157,14 +141,7 @@ PUBLIC __dead void arch_shutdown(int how) * depending on the parameters */ if (how == RBT_MONITOR) { - mybuffer[0] = '\0'; - arch_get_params(mybuffer, sizeof(mybuffer)); - if (strstr(mybuffer, "boot") || - strstr(mybuffer, "menu") || - strstr(mybuffer, "reset")) - how = RBT_RESET; - else - how = RBT_HALT; + how = RBT_RESET; } } @@ -643,8 +620,6 @@ PUBLIC void arch_ack_profile_clock(void) #endif -#define COLOR_BASE 0xB8000L - /* Saved by mpx386.s into these variables. */ u32_t params_size, params_offset, mon_ds; diff --git a/kernel/arch/i386/mb_utils.h b/kernel/arch/i386/mb_utils.h new file mode 100644 index 000000000..a17753d67 --- /dev/null +++ b/kernel/arch/i386/mb_utils.h @@ -0,0 +1,12 @@ +#ifndef MB_UTILS_H +#define MB_UTILS_H + +#include "kernel/kernel.h" + +_PROTOTYPE(void mb_cls, (void)); +_PROTOTYPE(void mb_print, (char*)); +_PROTOTYPE(void mb_print_char, (char)); +_PROTOTYPE(int mb_read_char, (unsigned char*)); + + +#endif diff --git a/kernel/arch/i386/pre_init.c b/kernel/arch/i386/pre_init.c index fe020b9f6..eef6d4cf3 100644 --- a/kernel/arch/i386/pre_init.c +++ b/kernel/arch/i386/pre_init.c @@ -16,6 +16,8 @@ #include "string.h" #include "arch_proto.h" #include "libexec.h" +#include "mb_utils.h" +#include "serial.h" #include #if USE_SYSDEBUG @@ -38,8 +40,6 @@ #define mb_save_phymem(buf, phy, len) \ phys_copy((u32_t)(buf), (phy), (len)) -FORWARD _PROTOTYPE(void mb_print, (char *str)); - PRIVATE void mb_itoa(u32_t val, char * out) { char ret[ITOA_BUFFER_SIZE]; @@ -117,50 +117,104 @@ PRIVATE char mb_get_char(int line, int col) /* Give non-zero values to avoid them in BSS */ PRIVATE int print_line = 1, print_col = 1; + +#include -PRIVATE void mb_cls(void) +PUBLIC void mb_cls(void) { -#if MULTIBOOT_VERBOSE int i, j; /* Clear screen */ for (i = 0; i < MULTIBOOT_CONSOLE_LINES; i++ ) for (j = 0; j < MULTIBOOT_CONSOLE_COLS; j++ ) mb_put_char(0, i, j); print_line = print_col = 0; -#endif + + /* Tell video hardware origin is 0. */ + outb(C_6845+INDEX, VID_ORG); + outb(C_6845+DATA, 0); + outb(C_6845+INDEX, VID_ORG+1); + outb(C_6845+DATA, 0); } PRIVATE void mb_scroll_up(int lines) { int i, j; - for (i = 0; i < MULTIBOOT_CONSOLE_LINES - lines; i++ ) { - for (j = 0; j < MULTIBOOT_CONSOLE_COLS; j++ ) - mb_put_char(mb_get_char(i + lines, j), i, j); + for (i = 0; i < MULTIBOOT_CONSOLE_LINES; i++ ) { + for (j = 0; j < MULTIBOOT_CONSOLE_COLS; j++ ) { + char c = 0; + if(i < MULTIBOOT_CONSOLE_LINES-lines) + c = mb_get_char(i + lines, j); + mb_put_char(c, i, j); + } } print_line-= lines; } -PRIVATE void mb_print(char *str) +PUBLIC void mb_print_char(char c) +{ + while (print_line >= MULTIBOOT_CONSOLE_LINES) + mb_scroll_up(1); + + if (c == '\n') { + while (print_col < MULTIBOOT_CONSOLE_COLS) + mb_put_char(' ', print_line, print_col++); + print_line++; + print_col = 0; + return; + } + + mb_put_char(c, print_line, print_col++); + + if (print_col >= MULTIBOOT_CONSOLE_COLS) { + print_line++; + print_col = 0; + } + + while (print_line >= MULTIBOOT_CONSOLE_LINES) + mb_scroll_up(1); +} + +PUBLIC void mb_print(char *str) { -#if MULTIBOOT_VERBOSE while (*str) { - if (*str == '\n') { - str++; - while (print_col < MULTIBOOT_CONSOLE_COLS) - mb_put_char(' ', print_line, print_col++); - print_line++; - print_col = 0; - continue; - } - mb_put_char(*str++, print_line, print_col++); - if (print_col >= MULTIBOOT_CONSOLE_COLS) { - print_line++; - print_col = 0; - } - while (print_line >= MULTIBOOT_CONSOLE_LINES) - mb_scroll_up(1); + mb_print_char(*str); + str++; + } +} + +/* Standard and AT keyboard. (PS/2 MCA implies AT throughout.) */ +#define KEYBD 0x60 /* I/O port for keyboard data */ +#define KB_STATUS 0x64 /* I/O port for status on AT */ +#define KB_OUT_FULL 0x01 /* status bit set when keypress char pending */ +#define KB_AUX_BYTE 0x20 /* Auxiliary Device Output Buffer Full */ + +PUBLIC int mb_read_char(unsigned char *ch) +{ + unsigned long b, sb; +#ifdef DEBUG_SERIAL + u8_t c, lsr; + + if (do_serial_debug) { + lsr= inb(COM1_LSR); + if (!(lsr & LSR_DR)) + return 0; + c = inb(COM1_RBR); + return 1; } -#endif /* MULTIBOOT_VERBOSE */ +#endif /* DEBUG_SERIAL */ + + sb = inb(KB_STATUS); + + if (!(sb & KB_OUT_FULL)) { + return 0; + } + + b = inb(KEYBD); + + if (!(sb & KB_AUX_BYTE)) + return 1; + + return 0; } PRIVATE void mb_print_hex(u32_t value) diff --git a/kernel/glo.h b/kernel/glo.h index 51adb7583..a0deadf21 100644 --- a/kernel/glo.h +++ b/kernel/glo.h @@ -22,6 +22,7 @@ EXTERN struct kinfo kinfo; /* kernel information for users */ EXTERN struct machine machine; /* machine information for users */ EXTERN struct kmessages kmess; /* diagnostic messages in kernel */ +EXTERN char kmess_buf[80*25]; /* printable copy of message buffer */ EXTERN struct k_randomness krandom; /* gather kernel random information */ EXTERN struct loadinfo kloadinfo; /* status of load average */ diff --git a/kernel/utility.c b/kernel/utility.c index fdae2506f..2dcb98fd7 100644 --- a/kernel/utility.c +++ b/kernel/utility.c @@ -23,7 +23,7 @@ PUBLIC void panic(const char *fmt, ...) va_list arg; /* The system has run aground of a fatal kernel error. Terminate execution. */ if (minix_panicing == ARE_PANICING) { - arch_monitor(); + reset(); } minix_panicing = ARE_PANICING; if (fmt != NULL) { @@ -53,6 +53,8 @@ int c; /* character to append */ * to the output driver if an END_OF_KMESS is encountered. */ if (c != END_OF_KMESS) { + static int blpos = 0; + int maxblpos = sizeof(kmess_buf) - 2; #ifdef DEBUG_SERIAL if (do_serial_debug) { if(c == '\n') @@ -61,9 +63,13 @@ int c; /* character to append */ } #endif kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */ + kmess_buf[blpos] = c; if (kmess.km_size < sizeof(kmess.km_buf)) kmess.km_size += 1; kmess.km_next = (kmess.km_next + 1) % _KMESS_BUF_SIZE; + if(blpos == maxblpos) { + memmove(kmess_buf, kmess_buf+1, sizeof(kmess_buf)-1); + } else blpos++; } else { int p; endpoint_t outprocs[] = OUTPUT_PROCS_ARRAY; -- 2.44.0