From 3568adbeba1623a28e80fa3680a2286fd48b0ed3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Duje=20Mihanovi=C4=87?= Date: Thu, 16 Sep 2021 19:38:34 +0200 Subject: [PATCH] More features in VGA driver Now supports color (specify color when using kprint) and moves the VGA cursor as it prints. --- .gitignore | 1 + Makefile | 4 +- include/arch/x86/io.h | 20 ++++++++ include/arch/x86/tty.h | 25 +++++++++- kernel/arch/x86/tty/tty.c | 98 +++++++++++++++++++++++++++++++++++++-- kernel/kernel.c | 24 +++++++++- 6 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 include/arch/x86/io.h diff --git a/.gitignore b/.gitignore index a5ea528..a45d17d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ toolchain/ boot.img +boot/x86/boot **/*.o **/*.bin **/*.elf diff --git a/Makefile b/Makefile index ce6fccc..5d98229 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ kernel/entry.o: kernel/entry.s $(AS) -f elf kernel/entry.s -o $@ kernel/arch/x86/tty/tty.o: kernel/arch/x86/tty/tty.c - $(CC) -g -o $@ -ffreestanding -c kernel/arch/x86/tty/tty.c + $(CC) -g -o $@ -Iinclude/arch/x86 -ffreestanding -c kernel/arch/x86/tty/tty.c kernel/kernel.o: kernel/kernel.c $(CC) -g -o $@ -Iinclude/arch/x86 -ffreestanding -c kernel/kernel.c @@ -29,6 +29,6 @@ kernel/kernel.elf: kernel/kernel.bin $(LD) -o $@ -T kernel/linker.ld ${KERNEL_OBJ} --oformat=elf32-i386 clean: - rm boot/x86/boot kernel/kernel.bin ${KERNEL_OBJ} boot.img + rm boot/x86/boot kernel/kernel.bin kernel/kernel.elf ${KERNEL_OBJ} boot.img .PHONY: all clean diff --git a/include/arch/x86/io.h b/include/arch/x86/io.h new file mode 100644 index 0000000..586eb74 --- /dev/null +++ b/include/arch/x86/io.h @@ -0,0 +1,20 @@ +#ifndef X86_IO_H +#define X86_IO_H + +#include + +static inline void outb(uint16_t port, uint8_t value) +{ + asm volatile ("outb %0, %1": : "a" (value), "Nd" (port)); +} + +static inline uint8_t inb(uint16_t port) +{ + uint8_t ret; + asm volatile ("inb %1, %0" + : "=a" (ret) + : "d" (port)); + return ret; +} + +#endif diff --git a/include/arch/x86/tty.h b/include/arch/x86/tty.h index 988d738..2224737 100644 --- a/include/arch/x86/tty.h +++ b/include/arch/x86/tty.h @@ -1,5 +1,28 @@ #ifndef X86_TTY_H #define X86_TTY_H + +#include + +#define VGA_COLOR_BLACK 0x0 +#define VGA_COLOR_BLUE 0x1 +#define VGA_COLOR_GREEN 0x2 +#define VGA_COLOR_TEAL 0x3 +#define VGA_COLOR_DARK_RED 0x4 +#define VGA_COLOR_MAGENTA 0x5 +#define VGA_COLOR_BROWN 0x6 +#define VGA_COLOR_LIGHT_GRAY 0x7 +#define VGA_COLOR_DARK_GRAY 0x8 +#define VGA_COLOR_PURPLE 0x9 +#define VGA_COLOR_LIME 0xA +#define VGA_COLOR_CYAN 0xB +#define VGA_COLOR_BRIGHT_RED 0xC +#define VGA_COLOR_PINK 0xD +#define VGA_COLOR_YELLOW 0xE +#define VGA_COLOR_WHITE 0xF + extern void screen_clear(void); -extern void kprint(const char *string); +extern void kprint(const char *string, uint8_t color); +extern void kprintb(const uint8_t byte); +extern void kprintw(const uint16_t word); +extern void kprintd(const uint32_t dword); #endif diff --git a/kernel/arch/x86/tty/tty.c b/kernel/arch/x86/tty/tty.c index d3ef87b..07d734e 100644 --- a/kernel/arch/x86/tty/tty.c +++ b/kernel/arch/x86/tty/tty.c @@ -1,17 +1,23 @@ +#include +#include +#include + #define VGA_WIDTH 80 #define VGA_HEIGHT 25 volatile char *video_memory = (char *) 0xB8000; /* VGA VRAM starts at 0xB8000 */ -static int cursor_x = 0; +static int cursor_x = 0; /* keep track of where cursor is */ static int cursor_y = 0; +char *hex_chars = "0123456789ABCDEF"; + void screen_clear(void) { int x, y; for ( y = 0; y < VGA_HEIGHT; y++ ) { for ( x = 0; x < VGA_WIDTH; x++ ) { - video_memory[(y * VGA_WIDTH + x) * 2 + 1] = 0x07; + video_memory[(y * VGA_WIDTH + x) * 2 + 1] = VGA_COLOR_LIGHT_GRAY; video_memory[(y * VGA_WIDTH + x) * 2] = ' '; } } @@ -34,16 +40,100 @@ void scroll_up(void) cursor_y = VGA_HEIGHT - 1; } -void kprint(const char *string) +void kprint(const char *string, uint8_t color) { char next_char; + uint8_t vga_misc_output; + uint16_t crtc_port; next_char = *string; while ( next_char != 0 ) { if ( next_char == '\n') { cursor_x = 0; cursor_y++; } - else { video_memory[(cursor_y * VGA_WIDTH + cursor_x++) * 2] = next_char; } + else { video_memory[(cursor_y * VGA_WIDTH + cursor_x) * 2] = next_char; video_memory[((cursor_y * VGA_WIDTH + cursor_x++) * 2)+ 1] = color != 0 ? color : VGA_COLOR_LIGHT_GRAY; } if ( cursor_x >= VGA_WIDTH ) { cursor_x = 0; cursor_y++; } if ( cursor_y >= VGA_HEIGHT ) { scroll_up(); } next_char = *++string; } + + vga_misc_output = inb(0x3CC); + if (vga_misc_output & 0x1 == 0) { + crtc_port = 0x3B4; + } else { + crtc_port = 0x3D4; + } + + outb(crtc_port, 0xE); + outb(crtc_port + 1, (cursor_y * VGA_WIDTH + cursor_x) >> 8); + outb(crtc_port, 0xF); + outb(crtc_port + 1, (cursor_y * VGA_WIDTH + cursor_x) & 0xFF); +} + +void kprintc(const char character, uint8_t color) +{ + uint8_t vga_misc_output; + uint16_t crtc_port; + + if ( character == '\n') { cursor_x = 0; cursor_y++; } + else { video_memory[(cursor_y * VGA_WIDTH + cursor_x) * 2] = character; video_memory[((cursor_y * VGA_WIDTH + cursor_x++) * 2)+ 1] = color != 0 ? color : VGA_COLOR_LIGHT_GRAY; } + if ( cursor_x >= VGA_WIDTH ) { cursor_x = 0; cursor_y++; } + if ( cursor_y >= VGA_HEIGHT ) { scroll_up(); } + + vga_misc_output = inb(0x3CC); + if (vga_misc_output & 0x1 == 0) { + crtc_port = 0x3B4; + } else { + crtc_port = 0x3D4; + } + + outb(crtc_port, 0xE); + outb(crtc_port + 1, (cursor_y * VGA_WIDTH + cursor_x) >> 8); + outb(crtc_port, 0xF); + outb(crtc_port + 1, (cursor_y * VGA_WIDTH + cursor_x) & 0xFF); + +} + +void kprintb(uint8_t byte) +{ + uint8_t temp; + temp = byte >> 4; + kprint("0x", VGA_COLOR_LIGHT_GRAY); + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); + temp = byte & 0xF; + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); +} + +void kprintw(uint16_t word) +{ + uint8_t temp; + temp = word >> 12; + kprint("0x", VGA_COLOR_LIGHT_GRAY); + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); + temp = (word >> 8) & 0xF; + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); + temp = (word >> 4) & 0xF; + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); + temp = word & 0xF; + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); +} + +void kprintd(uint32_t dword) +{ + uint8_t temp; + temp = dword >> 28; + kprint("0x", VGA_COLOR_LIGHT_GRAY); + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); + temp = (dword >> 24) & 0xF; + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); + temp = (dword >> 20) & 0xF; + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); + temp = (dword >> 16) & 0xF; + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); + temp = (dword >> 12) & 0xF; + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); + temp = (dword >> 8) & 0xF; + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); + temp = (dword >> 4) & 0xF; + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); + temp = dword & 0xF; + kprintc(hex_chars[temp], VGA_COLOR_LIGHT_GRAY); } diff --git a/kernel/kernel.c b/kernel/kernel.c index 7ac2ad7..7b6d354 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,4 +1,6 @@ #include +#include +#include const char *string = "Hello there!\n\n\ Hopefully your machine manages to print this text.\n\ @@ -13,5 +15,25 @@ Feel free to mess around with the code, although I doubt it will be very interes void _start(void) { screen_clear(); - kprint(string); + /*kprint(string, 0x07);*/ + kprint("Color 0x01\n", VGA_COLOR_BLUE); + kprint("Color 0x02\n", VGA_COLOR_GREEN); + kprint("Color 0x03\n", VGA_COLOR_TEAL); + kprint("Color 0x04\n", VGA_COLOR_DARK_RED); + kprint("Color 0x05\n", VGA_COLOR_MAGENTA); + kprint("Color 0x06\n", VGA_COLOR_BROWN); + kprint("Color 0x07\n", VGA_COLOR_LIGHT_GRAY); + kprint("Color 0x08\n", VGA_COLOR_DARK_GRAY); + kprint("Color 0x09\n", VGA_COLOR_PURPLE); + kprint("Color 0x0A\n", VGA_COLOR_LIME); + kprint("Color 0x0B\n", VGA_COLOR_CYAN); + kprint("Color 0x0C\n", VGA_COLOR_BRIGHT_RED); + kprint("Color 0x0D\n", VGA_COLOR_PINK); + kprint("Color 0x0E\n", VGA_COLOR_YELLOW); + kprint("Color 0x0F\n", VGA_COLOR_WHITE); + kprintb(0xAE); + kprint("\n", 0); + kprintw(0xDEAD); + kprint("\n", 0); + kprintd(0x89ABCDEF); } -- 2.39.2