diff --git a/headers/private/kernel/arch/debug_console.h b/headers/private/kernel/arch/debug_console.h index d8d9e9845d..387808ca24 100644 --- a/headers/private/kernel/arch/debug_console.h +++ b/headers/private/kernel/arch/debug_console.h @@ -5,8 +5,8 @@ * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Distributed under the terms of the NewOS License. */ -#ifndef KERNEL_DBG_CONSOLE_H -#define KERNEL_DBG_CONSOLE_H +#ifndef KERNEL_ARCH_DEBUG_CONSOLE_H +#define KERNEL_ARCH_DEBUG_CONSOLE_H #include @@ -18,16 +18,17 @@ struct kernel_args; extern "C" { #endif +char arch_debug_blue_screen_getchar(void); char arch_debug_serial_getchar(void); -char arch_debug_serial_putchar(char c); +void arch_debug_serial_putchar(char c); void arch_debug_serial_puts(const char *s); void arch_debug_serial_early_boot_message(const char *string); -status_t arch_debug_console_init(struct kernel_args *args, char (**blueScreenGetChar)(void)); +status_t arch_debug_console_init(struct kernel_args *args); status_t arch_debug_console_init_settings(struct kernel_args *args); #ifdef __cplusplus } #endif -#endif /* KERNEL_DBG_CONSOLE_H */ +#endif /* KERNEL_ARCH_DEBUG_CONSOLE_H */ diff --git a/headers/private/kernel/debug.h b/headers/private/kernel/debug.h index ad33ffb78f..062ebfa1dd 100644 --- a/headers/private/kernel/debug.h +++ b/headers/private/kernel/debug.h @@ -31,7 +31,7 @@ extern "C" { extern status_t debug_init(struct kernel_args *args); extern status_t debug_init_post_vm(struct kernel_args *args); extern void debug_early_boot_message(const char *string); -extern char debug_putchar(char c); +extern void debug_putchar(char c); extern void debug_puts(const char *s); extern void _user_debug_output(const char *userString); diff --git a/headers/private/kernel/frame_buffer_console.h b/headers/private/kernel/frame_buffer_console.h index 0b2c5b7a91..d4bf95d403 100644 --- a/headers/private/kernel/frame_buffer_console.h +++ b/headers/private/kernel/frame_buffer_console.h @@ -26,8 +26,12 @@ struct frame_buffer_boot_info { extern "C" { #endif +bool frame_buffer_console_available(void); status_t frame_buffer_console_init(struct kernel_args *args); +status_t _user_frame_buffer_update(addr_t baseAddress, int32 width, int32 height, + int32 depth, int32 bytesPerRow); + #ifdef __cplusplus } #endif diff --git a/src/system/kernel/arch/x86/arch_debug_console.c b/src/system/kernel/arch/x86/arch_debug_console.c index 4abc899ff2..2ef86437e8 100644 --- a/src/system/kernel/arch/x86/arch_debug_console.c +++ b/src/system/kernel/arch/x86/arch_debug_console.c @@ -53,8 +53,29 @@ static bool sBochsOutput = false; #endif -static char -keyboard_getchar(void) +static void +put_char(const char c) +{ +#if BOCHS_DEBUG_HACK + if (sBochsOutput) { + out8(c, 0xe9); + return; + } +#endif + + // wait until the transmitter empty bit is set + while ((in8(sSerialBasePort + SERIAL_LINE_STATUS) & 0x20) == 0) + ; + + out8(c, sSerialBasePort + SERIAL_TRANSMIT_BUFFER); +} + + +// #pragma mark - + + +char +arch_debug_blue_screen_getchar(void) { /* polling the keyboard, similar to code in keyboard * driver, but without using an interrupt @@ -102,33 +123,12 @@ keyboard_getchar(void) } -static void -put_char(const char c) -{ -#if BOCHS_DEBUG_HACK - if (sBochsOutput) { - out8(c, 0xe9); - return; - } -#endif - - // wait until the transmitter empty bit is set - while ((in8(sSerialBasePort + SERIAL_LINE_STATUS) & 0x20) == 0) - ; - - out8(c, sSerialBasePort + SERIAL_TRANSMIT_BUFFER); -} - - -// #pragma mark - - - char arch_debug_serial_getchar(void) { #if BOCHS_DEBUG_HACK if (sBochsOutput) - return keyboard_getchar(); + return arch_debug_blue_screen_getchar(); #endif while ((in8(sSerialBasePort + SERIAL_LINE_STATUS) & 0x1) == 0) @@ -138,7 +138,7 @@ arch_debug_serial_getchar(void) } -char +void arch_debug_serial_putchar(const char c) { if (c == '\n') { @@ -146,8 +146,6 @@ arch_debug_serial_putchar(const char c) put_char('\n'); } else if (c != '\r') put_char(c); - - return c; } @@ -166,19 +164,16 @@ arch_debug_serial_early_boot_message(const char *string) { // this function will only be called in fatal situations // ToDo: also enable output via text console?! - arch_debug_console_init(NULL, NULL); + arch_debug_console_init(NULL); arch_debug_serial_puts(string); } status_t -arch_debug_console_init(kernel_args *args, char (**_blueScreenGetChar)(void)) +arch_debug_console_init(kernel_args *args) { uint16 divisor = (uint16)(115200 / kSerialBaudRate); - if (_blueScreenGetChar) - *_blueScreenGetChar = keyboard_getchar; - // only use the port if we could find one, else use the standard port if (args->platform_args.serial_base_ports[0] != 0) sSerialBasePort = args->platform_args.serial_base_ports[0]; diff --git a/src/system/kernel/debug/Jamfile b/src/system/kernel/debug/Jamfile index 6458e275c5..7e5941f641 100644 --- a/src/system/kernel/debug/Jamfile +++ b/src/system/kernel/debug/Jamfile @@ -3,7 +3,7 @@ SubDir OBOS_TOP src system kernel debug ; UsePrivateHeaders [ FDirName kernel debug ] ; KernelMergeObject kernel_debug.o : - console.c + blue_screen.cpp debug.c frame_buffer_console.cpp gdb.c diff --git a/src/system/kernel/debug/blue_screen.cpp b/src/system/kernel/debug/blue_screen.cpp new file mode 100644 index 0000000000..5ce750a4d5 --- /dev/null +++ b/src/system/kernel/debug/blue_screen.cpp @@ -0,0 +1,190 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "blue_screen.h" + +#include +#include +#include + +#include +#include + + +#define USE_SCROLLING 0 +#define NO_CLEAR 1 + +struct screen_info { + int32 columns; + int32 rows; + int32 x, y; + uint8 attr; +} sScreen; + +console_module_info *sModule; + + +static inline void +hide_cursor(void) +{ + sModule->move_cursor(-1, -1); +} + + +static inline void +update_cursor(int32 x, int32 y) +{ + sModule->move_cursor(x, y); +} + + +#if USE_SCROLLING + +/** scroll from the cursor line up to the top of the scroll region up one line */ + +static void +scroll_up(void) +{ + // move the screen up one + sModule->blit(0, 1, sScreen.columns, sScreen.rows - 1, 0, 0); + + // clear the bottom line + sModule->fill_glyph(0, 0, sScreen.columns, 1, ' ', sScreen.attr); +} +#endif + + +static void +next_line(void) +{ + if (sScreen.y == sScreen.rows - 1) { +#if USE_SCROLLING + scroll_up(); +#else + sScreen.y = 0; +#endif + } else if (sScreen.y < sScreen.rows - 1) { + sScreen.y++; + } + +#if NO_CLEAR + sModule->fill_glyph(0, sScreen.y + 2, sScreen.columns, 1, ' ', sScreen.attr); +#endif + sScreen.x = 0; +} + + +static void +back_space(void) +{ + if (sScreen.x <= 0) + return; + + sScreen.x--; + sModule->put_glyph(sScreen.x, sScreen.y, ' ', sScreen.attr); +} + + +static void +put_character(char c) +{ + if (++sScreen.x >= sScreen.columns) { + next_line(); + sScreen.x++; + } + + sModule->put_glyph(sScreen.x - 1, sScreen.y, c, sScreen.attr); +} + + +static void +parse_character(char c) +{ + // just output the stuff + switch (c) { + case '\n': + next_line(); + break; + case 0x8: + back_space(); + break; + case '\t': + put_character(' '); + break; + + case '\r': + case '\0': + break; + + default: + put_character(c); + } +} + + +// #pragma mark - + + +status_t +blue_screen_init(void) +{ + extern console_module_info gFrameBufferConsoleModule; + + // we can't use get_module() here, since it's too early in the boot process + + if (!frame_buffer_console_available()) + return B_ERROR; + + sModule = &gFrameBufferConsoleModule; + return B_OK; +} + + +void +blue_screen_enter(void) +{ + sScreen.attr = 0x0f; // black on white + sScreen.x = sScreen.y = 0; + + sModule->get_size(&sScreen.columns, &sScreen.rows); +#if !NO_CLEAR + sModule->clear(sScreen.attr); +#else + sModule->fill_glyph(0, sScreen.y, sScreen.columns, 3, ' ', sScreen.attr); +#endif +} + + +char +blue_screen_getchar(void) +{ + return arch_debug_blue_screen_getchar(); +} + + +void +blue_screen_putchar(char c) +{ + hide_cursor(); + + parse_character(c); + + update_cursor(sScreen.x, sScreen.y); +} + + +void +blue_screen_puts(const char *text) +{ + hide_cursor(); + + while (text[0] != '\0') { + parse_character(text[0]); + text++; + } + + update_cursor(sScreen.x, sScreen.y); +} diff --git a/src/system/kernel/debug/blue_screen.h b/src/system/kernel/debug/blue_screen.h new file mode 100644 index 0000000000..28e1338a8c --- /dev/null +++ b/src/system/kernel/debug/blue_screen.h @@ -0,0 +1,27 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef BLUE_SCREEN_H +#define BLUE_SCREEN_H + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +status_t blue_screen_init(void); +void blue_screen_enter(void); + +char blue_screen_getchar(void); +void blue_screen_putchar(char c); +void blue_screen_puts(const char *text); + +#ifdef __cplusplus +} +#endif + +#endif /* BLUE_SCREEN_H */ diff --git a/src/system/kernel/debug/console.c b/src/system/kernel/debug/console.c deleted file mode 100644 index ff0291e43d..0000000000 --- a/src/system/kernel/debug/console.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. - * Distributed under the terms of the NewOS License. - */ - -/* This file contains the kprintf stuff and console init */ - - -#include -#include - -#include -#include -#include - -#include -#include -#include - - - -struct console_op_xy_struct { - int x; - int y; - char buf[256]; -}; - -static int console_fd = -1; - - -void -kprintf(const char *fmt, ...) -{ - int ret = 0; - va_list args; - char temp[256]; - - if (console_fd >= 0) { - va_start(args, fmt); - ret = vsprintf(temp,fmt,args); - va_end(args); - - write_pos(console_fd, 0, temp, ret); - } -} - -#if 0 -void -kprintf_xy(int x, int y, const char *fmt, ...) -{ - int ret = 0; - va_list args; - struct console_op_xy_struct buf; - - if (console_fd >= 0) { - va_start(args, fmt); - ret = vsprintf(buf.buf,fmt,args); - va_end(args); - - buf.x = x; - buf.y = y; - ioctl(console_fd, CONSOLE_OP_WRITEXY, &buf, ret + sizeof(buf.x) + sizeof(buf.y)); - } -} -#endif - -int -con_init(kernel_args *args) -{ - frame_buffer_console_init(args); - return B_OK; -} diff --git a/src/system/kernel/debug/debug.c b/src/system/kernel/debug/debug.c index a71ce58719..a6ece2ff0d 100644 --- a/src/system/kernel/debug/debug.c +++ b/src/system/kernel/debug/debug.c @@ -8,18 +8,18 @@ /* This file contains the debugger */ +#include "blue_screen.h" + #include -#include -#include -#include +#include #include + +#include #include #include #include - #include #include -#include #include #include @@ -38,12 +38,10 @@ typedef struct debugger_command { int dbg_register_file[B_MAX_CPU_COUNT][14]; /* XXXmpetit -- must be made generic */ -char (*sBlueScreenGetChar)(void) = NULL; - // this will be set by arch_debug_console_init() - static bool sSerialDebugEnabled = false; static bool sSyslogOutputEnabled = false; static bool sBlueScreenEnabled = false; +static bool sBlueScreenOutput = false; static spinlock sSpinlock = 0; static int sDebuggerOnCPU = -1; @@ -99,8 +97,8 @@ read_line(char *buf, int max_len) int cur_history_spot = cur_line; char (*readChar)(void); - if (sBlueScreenEnabled && sBlueScreenGetChar != NULL) - readChar = sBlueScreenGetChar; + if (sBlueScreenEnabled) + readChar = blue_screen_getchar; else readChar = arch_debug_serial_getchar; @@ -178,7 +176,7 @@ read_line(char *buf, int max_len) break; case '$': case '+': - if (readChar != sBlueScreenGetChar) { + if (!sBlueScreenEnabled) { /* HACK ALERT!!! * * If we get a $ at the beginning of the line @@ -244,18 +242,14 @@ parse_line(char *buf, char **argv, int *argc, int max_args) static void kernel_debugger_loop(void) { - struct debugger_command *cmd; - int argc; - dprintf("Running on CPU %d\n", smp_get_current_cpu()); - if (sBlueScreenEnabled && sBlueScreenGetChar == NULL) - dprintf("Only serial keyboard input available.\n"); sDebuggerOnCPU = smp_get_current_cpu(); - cmd = NULL; - for (;;) { + struct debugger_command *cmd = NULL; + int argc; + dprintf("kdebug> "); read_line(line_buf[cur_line], LINE_BUF_SIZE); parse_line(line_buf[cur_line], args, &argc, MAX_ARGS); @@ -333,19 +327,19 @@ cmd_continue(int argc, char **argv) // #pragma mark - -char +void debug_putchar(char c) { cpu_status state = disable_interrupts(); acquire_spinlock(&sSpinlock); if (sSerialDebugEnabled) - c = arch_debug_serial_putchar(c); + arch_debug_serial_putchar(c); + if (sBlueScreenOutput) + blue_screen_putchar(c); release_spinlock(&sSpinlock); restore_interrupts(state); - - return c; } @@ -357,6 +351,8 @@ debug_puts(const char *s) if (sSerialDebugEnabled) arch_debug_serial_puts(s); + if (sBlueScreenOutput) + blue_screen_puts(s); release_spinlock(&sSpinlock); restore_interrupts(state); @@ -373,7 +369,7 @@ debug_early_boot_message(const char *string) status_t debug_init(kernel_args *args) { - return arch_debug_console_init(args, &sBlueScreenGetChar); + return arch_debug_console_init(args); } @@ -389,6 +385,9 @@ debug_init_post_vm(kernel_args *args) add_debugger_command("exit", &cmd_continue, NULL); add_debugger_command("es", &cmd_continue, NULL); + frame_buffer_console_init(args); + arch_debug_console_init_settings(args); + // get debug settings handle = load_driver_settings("kernel"); if (handle != NULL) { @@ -396,13 +395,14 @@ debug_init_post_vm(kernel_args *args) sSerialDebugEnabled = true; if (get_driver_boolean_parameter(handle, "syslog_debug_output", false, false)) sSyslogOutputEnabled = true; - if (get_driver_boolean_parameter(handle, "bluescreen", false, false)) - sBlueScreenEnabled = true; + if (get_driver_boolean_parameter(handle, "bluescreen", false, false)) { + if (blue_screen_init() == B_OK) + sBlueScreenEnabled = true; + } unload_driver_settings(handle); } - arch_debug_console_init_settings(args); return arch_debug_init(args); } @@ -522,14 +522,20 @@ kernel_debugger(const char *message) smp_send_broadcast_ici(SMP_MSG_CPU_HALT, 0, 0, 0, NULL, SMP_MSG_FLAG_SYNC); } - if (message) { - dprintf(message); - dprintf("\n"); + if (sBlueScreenEnabled) { + sBlueScreenOutput = true; + blue_screen_enter(); } - dprintf("Welcome to Kernel Debugging Land...\n"); + if (message) { + kprintf(message); + kprintf("\n"); + } + + kprintf("Welcome to Kernel Debugging Land...\n"); kernel_debugger_loop(); + sBlueScreenOutput = false; kernel_startup = false; restore_interrupts(state); @@ -548,7 +554,7 @@ set_dprintf_enabled(bool newState) void -dprintf(const char *fmt, ...) +dprintf(const char *format, ...) { cpu_status state; va_list args; @@ -563,17 +569,40 @@ dprintf(const char *fmt, ...) state = disable_interrupts(); acquire_spinlock(&sSpinlock); - va_start(args, fmt); - vsnprintf(sOutputBuffer, OUTPUT_BUFFER_SIZE, fmt, args); + va_start(args, format); + vsnprintf(sOutputBuffer, OUTPUT_BUFFER_SIZE, format, args); va_end(args); arch_debug_serial_puts(sOutputBuffer); + if (sBlueScreenOutput) + blue_screen_puts(sOutputBuffer); release_spinlock(&sSpinlock); restore_interrupts(state); } +/** Similar to dprintf() but thought to be used in the kernel + * debugger only. + */ + +void +kprintf(const char *format, ...) +{ + va_list args; + + // ToDo: don't print anything if the debugger is not running! + + va_start(args, format); + vsnprintf(sOutputBuffer, OUTPUT_BUFFER_SIZE, format, args); + va_end(args); + + arch_debug_serial_puts(sOutputBuffer); + if (sBlueScreenOutput) + blue_screen_puts(sOutputBuffer); +} + + // #pragma mark - // userland syscalls diff --git a/src/system/kernel/debug/frame_buffer_console.cpp b/src/system/kernel/debug/frame_buffer_console.cpp index f9d0f12d08..a696e2ada8 100644 --- a/src/system/kernel/debug/frame_buffer_console.cpp +++ b/src/system/kernel/debug/frame_buffer_console.cpp @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -298,7 +299,7 @@ console_std_ops(int32 op, ...) { switch (op) { case B_MODULE_INIT: - return sConsole.frame_buffer != NULL ? B_OK : B_ERROR; + return frame_buffer_console_available() ? B_OK : B_ERROR; case B_MODULE_UNINIT: return B_OK; @@ -323,10 +324,7 @@ console_module_info gFrameBufferConsoleModule = { }; -// #pragma mark - - - -status_t +static status_t frame_buffer_update(addr_t baseAddress, int32 width, int32 height, int32 depth, int32 bytesPerRow) { TRACE(("frame_buffer_update(buffer = %p, width = %ld, height = %ld, depth = %ld, bytesPerRow = %ld)\n", @@ -355,6 +353,16 @@ frame_buffer_update(addr_t baseAddress, int32 width, int32 height, int32 depth, } +// #pragma mark - + + +bool +frame_buffer_console_available(void) +{ + return sConsole.frame_buffer != NULL; +} + + status_t frame_buffer_console_init(kernel_args *args) { @@ -402,3 +410,19 @@ frame_buffer_console_init(kernel_args *args) return B_OK; } + +// #pragma mark - + + +status_t +_user_frame_buffer_update(addr_t baseAddress, int32 width, int32 height, + int32 depth, int32 bytesPerRow) +{ + if (geteuid() != 0) + return B_NOT_ALLOWED; + if (IS_USER_ADDRESS(baseAddress)) + return B_BAD_ADDRESS; + + return frame_buffer_update(baseAddress, width, height, depth, bytesPerRow); +} + diff --git a/src/system/kernel/main.c b/src/system/kernel/main.c index 1f8b9a0c9c..458d7a71b5 100644 --- a/src/system/kernel/main.c +++ b/src/system/kernel/main.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -214,9 +213,6 @@ main2(void *unused) TRACE(("Mount boot file system\n")); vfs_mount_boot_file_system(&ka); - TRACE(("Init console\n")); - con_init(&ka); - //net_init_postdev(&ka); //module_test();