From f33c8020e2693795032110c933cbb60dea5be8df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 29 May 2005 16:23:00 +0000 Subject: [PATCH] Removed debug/console.c, we no longer need it. frame_buffer_console_init() is now called by debug_init_post_vm(). Since the availability of a blue screen specific getchar() is static anyway, there is no need for the sBlueScreenGetChar variable (only the message "only serial input available" gets lost, but since that is platform specific anyway...). Hello blue screen! We now have an on-screen KDL, to be enabled by the kernel setting "bluescreen", just like on BeOS. The blue screen does not yet support any cursor actions or backspace, though (need to grab some stuff from our console driver). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12896 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/debug_console.h | 11 +- headers/private/kernel/debug.h | 2 +- headers/private/kernel/frame_buffer_console.h | 4 + .../kernel/arch/x86/arch_debug_console.c | 59 +++--- src/system/kernel/debug/Jamfile | 2 +- src/system/kernel/debug/blue_screen.cpp | 190 ++++++++++++++++++ src/system/kernel/debug/blue_screen.h | 27 +++ src/system/kernel/debug/console.c | 75 ------- src/system/kernel/debug/debug.c | 95 ++++++--- .../kernel/debug/frame_buffer_console.cpp | 34 +++- src/system/kernel/main.c | 4 - 11 files changed, 347 insertions(+), 156 deletions(-) create mode 100644 src/system/kernel/debug/blue_screen.cpp create mode 100644 src/system/kernel/debug/blue_screen.h delete mode 100644 src/system/kernel/debug/console.c 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();