diff --git a/build.sh b/build.sh index 4f68749..2755a01 100755 --- a/build.sh +++ b/build.sh @@ -1,6 +1,8 @@ #!/bin/bash -i386-elf-gcc -ffreestanding -c src/kernel/main.c -o kernel.o +i386-elf-gcc -ffreestanding -I src/ -c src/kernel/main.c -o kernel.o +i386-elf-gcc -ffreestanding -I src/ -c src/kernel/drivers/vga/screen.c -o screen.o +i386-elf-gcc -ffreestanding -I src/ -c src/kernel/drivers/ports/ports.c -o ports.o nasm -f elf src/entrypoint.s -o entry.o nasm -f bin src/boot/mbr.s -o mbr.bin -i386-elf-ld -o kernel.bin -Ttext 0x1000 entry.o kernel.o --oformat binary +i386-elf-ld -o kernel.bin -Ttext 0x1000 entry.o kernel.o ports.o screen.o --oformat binary cat mbr.bin kernel.bin > os.bin diff --git a/src/boot/mbr.s b/src/boot/mbr.s index 208c8ad..2296afe 100644 --- a/src/boot/mbr.s +++ b/src/boot/mbr.s @@ -42,9 +42,9 @@ load_kernel: ; Loads the kernel into memory ; Here we define our variables: They need to be defined after the ; halting because otherwise they will be executed as code -real_mode_msg: db "Booted in real mode", 0 +real_mode_msg: db "TSOS is starting up", 0 protected_mode_msg: db "Switched to protected mode", 0 -loading_kernel_msg: db "Loading kernel", 0 +loading_kernel_msg: db "Loading kernel into memory", 0 boot_drive: db 0 @@ -55,7 +55,7 @@ BEGIN_32BIT: ; After the switch we will get here ; to add to the start of the video memory that ; is added before writing. We skip the first ; 320 bytes so that we don't overwrite the log - ; messages we may have written beforehand + ; messages we have already written mov ecx, 0x140 call vga_println call kernel_offset diff --git a/src/kernel/drivers/vga/video.c b/src/kernel/drivers/ports/ports.c similarity index 58% rename from src/kernel/drivers/vga/video.c rename to src/kernel/drivers/ports/ports.c index b68d641..15e8e9b 100644 --- a/src/kernel/drivers/vga/video.c +++ b/src/kernel/drivers/ports/ports.c @@ -1,30 +1,31 @@ -// Implementation of a simple video driver using VGA text mode -#include "video.h" +// Utilities for writing to and reading from I/O ports + +#include "ports.h" -uchar_t vga_readb(u16_t port) { +byte vga_readb(u16 port) { // Reads a byte from the specified I/O port - uchar_t result; + byte result; __asm__("in %%dx, %%al" : "=a" (result) : "d" (port)); return result; } -void vga_writeb(u16_t port, uchar_t data) { - // Writes a byte from the specified I/O port +void vga_writeb(u16 port, byte data) { + // Writes a byte to the specified I/O port __asm__("out %%al, %%dx" : : "a" (data), "d" (port)); } -u16_t vga_writew(u16_t port) { +u16 vga_readw(u16 port) { // Reads a word (16 bits) from the specified I/O port - u16_t result; + u16 result; __asm__("in %%dx, %%ax" : "=a" (result) : "d" (port)); return result; } -void vga_readw(u16_t port, u16_t data) { +void vga_writew(u16 port, u16 data) { // Writes a word (16 bits) to the specified I/O port __asm__("out %%ax, %%dx" : : "a" (data), "d" (port)); } \ No newline at end of file diff --git a/src/kernel/drivers/ports/ports.h b/src/kernel/drivers/ports/ports.h new file mode 100644 index 0000000..5660c15 --- /dev/null +++ b/src/kernel/drivers/ports/ports.h @@ -0,0 +1,16 @@ +#ifndef TSOS_DRV_PORTS_H +#define TSOS_DRV_PORTS_H + + +#define VMEM_ADDR 0xb8000 +#include "kernel/ktypes.h" + + +byte vga_readb(u16 port); +void vga_writeb(u16 port, byte data); +u16 vga_readw(u16 port); +void vga_writew(u16 port, u16 data); + + + +#endif \ No newline at end of file diff --git a/src/kernel/drivers/vga/screen.c b/src/kernel/drivers/vga/screen.c new file mode 100644 index 0000000..68d466b --- /dev/null +++ b/src/kernel/drivers/vga/screen.c @@ -0,0 +1,2 @@ +// Implementation of a simple text-only VGA driver +#include "screen.h" \ No newline at end of file diff --git a/src/kernel/drivers/vga/screen.h b/src/kernel/drivers/vga/screen.h new file mode 100644 index 0000000..20f7ea3 --- /dev/null +++ b/src/kernel/drivers/vga/screen.h @@ -0,0 +1,23 @@ +#ifndef TSOS_DRV_VGA_SCREEN +#define TSOS_DRV_VGA_SCREEN + +#define VMEM_ADDRESS 0xb8000 +#define MAX_ROWS 25 +#define MAX_COLS 80 +#define LIGHT_GREY_ON_BLACK 0x07 +#define RED_ON_WHITE 0xf4 + +// VGA I/O ports +#define REG_SCREEN_CTRL 0x3d4 +#define REG_SCREEN_DATA 0x3d5 + +#include "kernel/ktypes.h" +#include "kernel/drivers/ports/ports.h" + +// Exposed API +void clear_screen(void); +void kprint_at(char *message, int col, int row); +void kprint(char *message); + + +#endif \ No newline at end of file diff --git a/src/kernel/drivers/vga/video.h b/src/kernel/drivers/vga/video.h deleted file mode 100644 index 149e2da..0000000 --- a/src/kernel/drivers/vga/video.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef TSOS_DRV_VGA_H // Avoid nasty double-inclusion problems -#define TSOS_DRV_VGA_H -#define VMEM_ADDR 0xb8000 -#include "../../types/ktypes.h" - - -uchar_t vga_writeb(u16_t port); -void vga_readb(u16_t port, uchar_t data); -u16_t vga_writew(u16_t port); -void vga_readw(u16_t port, u16_t data); - - - -#endif \ No newline at end of file diff --git a/src/kernel/ktypes.h b/src/kernel/ktypes.h new file mode 100644 index 0000000..5b0e4ca --- /dev/null +++ b/src/kernel/ktypes.h @@ -0,0 +1,13 @@ +// Shorthand definitions of various types +// used in the kernel +#ifndef TSOS_KTYPES +#define TSOS_KTYPES + + +typedef unsigned char byte; +typedef unsigned short int u16; +typedef short int i16; +typedef unsigned int uint; + + +#endif \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index c45f7de..ed9d1a0 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,14 +1,35 @@ // Entry point of the TSOS kernel -#include "types/ktypes.h" -#include "drivers/vga/video.h" +#include "kernel/ktypes.h" +#include "kernel/drivers/vga/screen.h" void kmain(void) { - char_t* vbuf = (char_t*)VMEM_ADDR; - vbuf += 480; // We skip the log messages before us - char_t *s = "Hello from the TSOS kernel!"; - for (int_t i = 0; s[i] != '\0'; i++) { - *vbuf = s[i]; - vbuf += 2; + byte* vga = (byte*)VMEM_ADDRESS; + vga_writeb(0x3d4, 14); // We request the high byte of cursor position on port 0x3D4 + int cursor = vga_readb(0x3d5); // And now we read it + // Since this is the high byte, we shift the + // cursor by 8 bits to make room for the low + // byte + cursor <<= 8; + // Now we request the low byte + vga_writeb(0x3d4, 15); + // And we add it to the cursor + cursor += vga_readb(0x3d5); + // VGA 'cells' are 2 bytes long, but + // the cursor counts cells as a unit, + // so we multiply it by 2 + cursor *= 2; + // We add 160 because when we print a + // message via VGA in the bootloader, + // and that leaves the cursor in the + // wrong position + cursor += 160; + // Now we write some message onto the screen + byte *s = "TSOS Kernel started"; + for (int i = 0; s[i] != '\0'; i++) { + vga[cursor] = s[i]; // We set the character code we want + cursor++; + vga[cursor] = 0x07; // Light grey on black + cursor++; } } \ No newline at end of file diff --git a/src/kernel/types/ktypes.h b/src/kernel/types/ktypes.h deleted file mode 100644 index 462a8d0..0000000 --- a/src/kernel/types/ktypes.h +++ /dev/null @@ -1,15 +0,0 @@ -// Shorthand definitions of various types -// used in the kernel -#ifndef TSOS_KTYPES -#define TSOS_KTYPES - - -typedef unsigned char uchar_t; -typedef unsigned short int u16_t; -typedef short int i16_t; -typedef char char_t; -typedef unsigned int uint_t; -typedef int int_t; - - -#endif \ No newline at end of file