From 394befa3a8d9fcf8f8507d0f94aa08ff440ab669 Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Sat, 21 May 2011 11:51:22 +0200 Subject: [PATCH] Color management for procedures using vga_putchar As seen in some BSD operating systems, you can now push and pop foreground and background colors onto a stack to change the colors you see on the screen whenever kprintf/kputchar is used. This could become useful if one wants to see kernel space kprintfs in other colors than user space printfs or error messages in red and other debugging purposes. Beware: This is just a small and dirty hack which protects the colorstack with locks and so on. But on task switching the color will not be switched. That makes different colors for different colors persistent for all the time difficult/impossible. But I considered adding colors to the task structures a bit overdone for a small debugging-help. [Sorry for those commit-and-pull-back-mails. Forgot that I had this stuff on the master branch while pushing my own branch onto the server.] --- arch/x86/kernel/vga.c | 8 ++--- include/metalsvm/stdio.h | 39 +++++++++++++++++++++++++ kernel/main.c | 5 +++- libkern/printf.c | 63 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/vga.c b/arch/x86/kernel/vga.c index 18cd183a..3b66f271 100644 --- a/arch/x86/kernel/vga.c +++ b/arch/x86/kernel/vga.c @@ -209,15 +209,15 @@ int vga_puts(const char *text) } /* Sets the forecolor and backcolor we will use */ -//void settextcolor(unsigned char forecolor, unsigned char backcolor) -//{ +void settextcolor(unsigned char forecolor, unsigned char backcolor) +{ /* * Top 4 bytes are the background, bottom 4 bytes * are the foreground color */ -// attrib = (backcolor << 4) | (forecolor & 0x0F); -//} + attrib = ((backcolor & 0x0F) << 4) | (forecolor & 0x0F); +} /* Sets our text-mode VGA pointer, then clears the screen for us */ void vga_init(void) diff --git a/include/metalsvm/stdio.h b/include/metalsvm/stdio.h index 6f9fc20e..cd5d2a61 100644 --- a/include/metalsvm/stdio.h +++ b/include/metalsvm/stdio.h @@ -74,6 +74,45 @@ int koutput_init(void); */ int kvprintf(char const *fmt, void (*func) (int, void *), void *arg, int radix, va_list ap); +/** @brief Set a new foreground color for kprintf and kputchar. + * + * The color change will affect any procedure using vga_putchar()/vga_puts(). + * This procedure pushes the color onto a colorstack making you + * able to revert this change just with a popfg(). + * */ +void pushfg(unsigned char fgcol); + +/** @brief Set a new background color for kprintf and kputchar. + * + * The color change will affect any procedure using vga_putchar()/vga_puts(). + * This procedure pushes the color onto a colorstack making you + * able to revert this change just with a popbg(). + * */ +void pushbg(unsigned char bgcol); + +#define COL_BLACK 0 +#define COL_BLUE 1 +#define COL_GREEN 2 +#define COL_CYAN 3 +#define COL_RED 4 +#define COL_MAGENTA 5 +#define COL_BROWN 6 +#define COL_LGRAY 7 +#define COL_DGRAY 8 +#define COL_LBLUE 9 +#define COL_LGREEN 10 +#define COL_LCYAN 11 +#define COL_LRED 12 +#define COL_LMAGENTA 13 +#define COL_LYELLOW 14 +#define COL_WHITE 15 + +/** @brief Revert the last foreground color change introduced by pushfg() */ +void popfg(); + +/** @brief Revert the last background color change introduced by pushfg() */ +void popbg(); + #ifdef __cplusplus } #endif diff --git a/kernel/main.c b/kernel/main.c index 2d9caca9..daf7f3af 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -82,7 +82,10 @@ int main(void) { lowlevel_init(); - kprintf("This is MetalSVM %s Build %u, %u\n", METALSVM_VERSION, &__BUILD_DATE, &__BUILD_TIME); + pushbg(COL_BLUE); + kprintf("This is MetalSVM %s Build %u, %u\n", + METALSVM_VERSION, &__BUILD_DATE, &__BUILD_TIME); + popbg(); system_init(); irq_init(); diff --git a/libkern/printf.c b/libkern/printf.c index 780184bb..416d2893 100644 --- a/libkern/printf.c +++ b/libkern/printf.c @@ -45,6 +45,7 @@ */ #include +#include #define __64BIT__ @@ -74,6 +75,14 @@ char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ #define MAXNBUF (sizeof(intmax_t) * NBBY + 1) +#define COLOR_STACK_SIZE 10 +static int fgstack[COLOR_STACK_SIZE] = {0xf}; +static int bgstack[COLOR_STACK_SIZE] = {0x0}; +static unsigned int fgstack_pos = 0; +static unsigned int bgstack_pos = 0; +static spinlock_t fglock = SPINLOCK_INIT; +static spinlock_t bglock = SPINLOCK_INIT; + /* * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse * order; return an optional length and a pointer to the last character @@ -483,3 +492,57 @@ int kprintf(const char *fmt, ...) return ret; } + +extern void settextcolor(unsigned char forecolor, unsigned char backcolor); + +void pushfg(unsigned char fgcol) +{ + spinlock_lock(&fglock); + /* Ignore this request if the stack is full */ + if (fgstack_pos == COLOR_STACK_SIZE) goto rel_pushfglock; + + ++fgstack_pos; + fgstack[fgstack_pos] = fgcol; + + settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +rel_pushfglock: + spinlock_unlock(&fglock); +} + +void pushbg(unsigned char bgcol) +{ + spinlock_lock(&bglock); + /* Ignore this request if the stack is full */ + if (bgstack_pos == COLOR_STACK_SIZE) goto rel_pushbglock; + + ++bgstack_pos; + bgstack[bgstack_pos] = bgcol; + + settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +rel_pushbglock: + spinlock_unlock(&bglock); +} + +void popfg() +{ + spinlock_lock(&fglock); + /* Ignore if we're already at the stack's bottom */ + if (!fgstack_pos) goto rel_popfglock; + + --fgstack_pos; + settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +rel_popfglock: + spinlock_unlock(&fglock); +} + +void popbg() +{ + spinlock_lock(&bglock); + /* Ignore if we're already at the stack's bottom */ + if (!bgstack_pos) goto rel_popbglock; + + --bgstack_pos; + settextcolor(fgstack[fgstack_pos], bgstack[bgstack_pos]); +rel_popbglock: + spinlock_unlock(&bglock); +}