From 5efb8d9fbc62c1f8e6fc8b255cca94544a84cfe9 Mon Sep 17 00:00:00 2001 From: lordtet Date: Wed, 28 May 2025 23:19:50 -0400 Subject: [PATCH] Moved i/o content to kerno.c Added function for integer -> string (library pending) Modified makefile to reflect use of include/ dir --- Makefile | 16 +++++++--- include/kernio.h | 35 +++++++++++++++++++++ src/kernio.c | 57 ++++++++++++++++++++++++++++++++++ src/main.c | 80 +++++++++++++++++------------------------------- 4 files changed, 132 insertions(+), 56 deletions(-) create mode 100644 include/kernio.h create mode 100644 src/kernio.c diff --git a/Makefile b/Makefile index 03c1b3b..5ae0842 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,10 @@ AS := $(CROSS)as CC := $(CROSS)gcc LD := $(CROSS)ld QEMU := qemu-system-i386 +INCLUDES:= include/ - -CFLAGS := -ffreestanding -nostdlib -lgcc -g -LDFLAGS := -T linker.ld -nostdlib +CFLAGS := -I $(INCLUDES) -O2 -Wall -Wextra -ffreestanding -nostdlib -lgcc -g +LDFLAGS := -T linker.ld -nostdlib SRC_DIR := src OBJ_DIR := obj @@ -58,9 +58,17 @@ clean: iso: $(OUT_ISO) .PHONY: run -run: +run: $(OUT_ELF) $(QEMU) -kernel $(OUT_ELF) +.PHONY: debug +debug: + $(QEMU) -s -S -kernel $(OUT_ELF) + .PHONY: run_iso run_iso: $(QEMU) -cdrom $(OUT_ISO) + +.PHONY: debug_iso +debug_iso: + $(QEMU) -s -S -cdrom $(OUT_ISO) diff --git a/include/kernio.h b/include/kernio.h new file mode 100644 index 0000000..fed80d7 --- /dev/null +++ b/include/kernio.h @@ -0,0 +1,35 @@ +#ifndef KERNIO_H +#define KERNIO_H +#define VGA_GRID_COLS 79 +#define VGA_GRID_ROWS 25 +#include + +/* + * CONSTANTS AND VARIABLES + */ + +//Information on the VGA buffer + +extern volatile uint16_t* const vga_buffer; + +//grid is top left origin. This is our cursor! +extern int cursor_col; +extern int cursor_row; +extern uint16_t vga_attributes; // Black background, White foreground + + +/* + * Functions + */ + +//Clear the VGA buffer +void vga_clear(); +//Put a character in the VGA buffer and move the cursor to the right by one +void vga_putc(char c); +void vga_set_attributes(uint8_t attributes); +void vga_print(const char* out); +void vga_println(const char* out); + + + +#endif diff --git a/src/kernio.c b/src/kernio.c new file mode 100644 index 0000000..ac32fec --- /dev/null +++ b/src/kernio.c @@ -0,0 +1,57 @@ +#include "kernio.h" +#include + +/* + * VARS + */ + +int cursor_col = 0; +int cursor_row = 0; +volatile uint16_t* const vga_buffer = (uint16_t*)0xB8000; +uint16_t vga_attributes = 0x0F00; + +void vga_clear() { + for (int col = 0; col < VGA_GRID_COLS; col ++) { + for (int row = 0; row < VGA_GRID_ROWS; row ++) { + //works out to iterating every cell + const size_t index = (VGA_GRID_COLS * row) + col; + //vga buffer looks something like xxxxyyyyzzzzzzzz + //x=bg color + //y=fg color + //c=character to use + //Therefore, to write, we just take our color data and tack on the character to the end. + vga_buffer[index] = vga_attributes | ' '; //blank out + } + } +} + +void vga_putc(char c) +{ + //Check for some freaky escape character first + if(c == '\n') { + cursor_col = 0; + cursor_row = (cursor_row + 1) % 25; + return; + } + //Calculate where in the vga buffer to put the character + const size_t index = (VGA_GRID_COLS * cursor_row) + cursor_col; + //VGA buffer cell consists of the first half attributes, second half character + vga_buffer[index] = vga_attributes | c; + cursor_col++; +} + +void vga_set_attributes(uint8_t attributes) { + vga_attributes = ((uint16_t)attributes) << 8; +} + + +void vga_print(const char* out) +{ + for (int i = 0; out[i] != '\0'; i++) + vga_putc(out[i]); +} + +void vga_println(const char* out) { + vga_print(out); + vga_print("\n"); +} diff --git a/src/main.c b/src/main.c index 09509d9..ec75c19 100644 --- a/src/main.c +++ b/src/main.c @@ -1,55 +1,30 @@ -// Reworked sample code from OSDev! Stripped down some of the extra stuff to leave as an exercise. -//Headers provided by GCC :). No need for libs! We don't even have those yet. -#include +//Our own code, at this point... +//#include #include +#include "kernio.h" +//convert digits from int num to buffer buf. in hex. This is 32 bit only for now! +//WARN: integer is written from right to left into the buffer, and will halt if the buffer is too small. +void i_to_str(uint32_t num, char* buf, int size) { + //null terminate the string + buf[--size] = '\0'; + while(size > 0 && (num) != 0){ + int isolated_num = num % 0x10; + if(isolated_num > 9){ + isolated_num+=7; + } + buf[--size] = '0' + isolated_num; + num/=0x10; + } -//VGA buffer is the easiest way to write to the screen at this stage. it's just a massive array with two datapoints: what color, and what character? -//array starts at the absolute address 0xB8000 -volatile uint16_t* vga_buffer = (uint16_t*)0xB8000; -//the VGA buffer is 80x25 to represent the screen. -const int GRID_COLS = 80; -const int GRID_ROWS = 25; - - -//grid is top left origin. This is our cursor! -int cursor_col = 0; -int cursor_row = 0; -uint16_t term_color = 0x0F00; // Black background, White foreground - - -//wipe the screen -void term_clear() { - for (int col = 0; col < GRID_COLS; col ++) { - for (int row = 0; row < GRID_ROWS; row ++) { - //works out to iterating every cell - const size_t index = (GRID_COLS * row) + col; - //vga buffer looks something like xxxxyyyyzzzzzzzz - //x=bg color - //y=fg color - //c=character to use - //Therefore, to write, we just take our color data and tack on the character to the end. - vga_buffer[index] = term_color | ' '; //blank out - } - } -} - -// -void term_printc(char c) -{ - const size_t index = (GRID_COLS * cursor_row) + cursor_col; //where am i puttin it - vga_buffer[index] = term_color | c; //put it there by putting color+char into that spot in the array - cursor_col++; //next time put it in the next spot. -} - -//print a string! -void term_println(const char* out) -{ - for (int i = 0; out[i] != '\0'; i++) - term_printc(out[i]); - //go to the next line for a println func. - cursor_col = 0; - cursor_row++; + //now shift the whole thing to the left + if(size != 0) { + while(buf[size]!='\0') { + *buf = buf[size]; + buf++; + } + *buf = '\0'; + } } @@ -58,10 +33,11 @@ void kern_main() { //wipe the screen - term_clear(); + vga_clear(); //IT IS TIME. TO PRINT. - term_println("hello my chungus world"); - term_println(":100:"); + char lol[5]; + i_to_str(0xCAFEBABE, lol, 5); + vga_println(lol); }