diff --git a/.gitignore b/.gitignore index 34badc1..de1984d 100644 --- a/.gitignore +++ b/.gitignore @@ -140,4 +140,6 @@ dkms.conf build/ nob nob.old -.clangd \ No newline at end of file +.clangd +spec +todo \ No newline at end of file diff --git a/nob.c b/nob.c index edf8ae8..bcf319f 100644 --- a/nob.c +++ b/nob.c @@ -53,9 +53,9 @@ bool build_assembly(Nob_Cmd *cmd) { } bool build_c(Nob_Cmd *cmd) { + const char *inputFiles[] = {SRC_FOLDER "kernel.c", SRC_FOLDER "serial.h"}; const char *output = BUILD_FOLDER "kernel.o"; - const char *input = SRC_FOLDER "kernel.c"; - int rebuild = nob_needs_rebuild1(output, input); + int rebuild = nob_needs_rebuild(output, inputFiles, NOB_ARRAY_LEN(inputFiles)); if (!rebuild) return true; @@ -69,6 +69,7 @@ bool build_c(Nob_Cmd *cmd) { "-O2", "-o", BUILD_FOLDER "kernel.o", "-c", SRC_FOLDER "kernel.c"); + if (!nob_cmd_run(cmd)) return false; @@ -83,9 +84,7 @@ bool link_everything(Nob_Cmd *cmd) { if (!rebuild) return true; - Nob_File_Paths objectFiles = {0}; - nob_da_append(&objectFiles, BUILD_FOLDER "kernel.o"); - nob_da_append(&objectFiles, BUILD_FOLDER "boot.o"); + const char *objectFiles[] = {BUILD_FOLDER "kernel.o", BUILD_FOLDER "boot.o"}; nob_cmd_append(cmd, "i686-elf-gcc", "-T", SRC_FOLDER "linker.ld", @@ -95,8 +94,8 @@ bool link_everything(Nob_Cmd *cmd) { "-nostdlib"); // Add objectFiles as input - for (size_t i = 0; i < objectFiles.count; ++i) { - nob_cmd_append(cmd, objectFiles.items[i]); + for (size_t i = 0; i < NOB_ARRAY_LEN(objectFiles); i++) { + nob_cmd_append(cmd, objectFiles[i]); } nob_cmd_append(cmd, "-lgcc"); @@ -168,7 +167,7 @@ bool build_bootable_image(Nob_Cmd *cmd) { } bool runQemu(Nob_Cmd *cmd) { - nob_cmd_append(cmd, "qemu-system-i386", "-cdrom", BUILD_FOLDER "kernel.iso"); + nob_cmd_append(cmd, "qemu-system-i386", "-cdrom", BUILD_FOLDER "kernel.iso", "-serial", "stdio"); if (!nob_cmd_run(cmd)) return false; return true; diff --git a/src/kernel.c b/src/kernel.c index 0c58631..b998b88 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1,115 +1,19 @@ +#include "serial.h" #include #include #include -/* Check if the compiler thinks you are targeting the wrong operating system. */ #if defined(__linux__) -#error "You are not using a cross-compiler, you will most certainly run into trouble" +#error "Not using cross compiler" #endif - -/* This tutorial will only work for the 32-bit ix86 targets. */ #if !defined(__i386__) -#error "This tutorial needs to be compiled with a ix86-elf compiler" +#error "Not using a ix86-elf compiler" #endif -/* Hardware text mode color constants. */ -enum vga_color { - VGA_COLOR_BLACK = 0, - VGA_COLOR_BLUE = 1, - VGA_COLOR_GREEN = 2, - VGA_COLOR_CYAN = 3, - VGA_COLOR_RED = 4, - VGA_COLOR_MAGENTA = 5, - VGA_COLOR_BROWN = 6, - VGA_COLOR_LIGHT_GREY = 7, - VGA_COLOR_DARK_GREY = 8, - VGA_COLOR_LIGHT_BLUE = 9, - VGA_COLOR_LIGHT_GREEN = 10, - VGA_COLOR_LIGHT_CYAN = 11, - VGA_COLOR_LIGHT_RED = 12, - VGA_COLOR_LIGHT_MAGENTA = 13, - VGA_COLOR_LIGHT_BROWN = 14, - VGA_COLOR_WHITE = 15, -}; - -static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) { - return fg | bg << 4; -} - -static inline uint16_t vga_entry(unsigned char uc, uint8_t color) { - return (uint16_t)uc | (uint16_t)color << 8; -} - -size_t strlen(const char *str) { - size_t len = 0; - while (str[len]) - len++; - return len; -} - -#define VGA_WIDTH 80 -#define VGA_HEIGHT 25 -#define VGA_MEMORY 0xB8000 - -size_t terminal_row; -size_t terminal_column; -uint8_t terminal_color; -uint16_t *terminal_buffer = (uint16_t *)VGA_MEMORY; - -void terminal_initialize(void) { - - terminal_row = 0; - terminal_column = 0; - terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); - - for (size_t y = 0; y < VGA_HEIGHT; y++) { - for (size_t x = 0; x < VGA_WIDTH; x++) { - const size_t index = y * VGA_WIDTH + x; - terminal_buffer[index] = vga_entry(' ', terminal_color); - } - } -} - -void terminal_setcolor(uint8_t color) { - terminal_color = color; -} - -void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) { - const size_t index = y * VGA_WIDTH + x; - terminal_buffer[index] = vga_entry(c, color); -} - -void terminal_putchar(char c) { - if (c == '\n') { - terminal_row += 1; - terminal_column = 0; - if (terminal_row == VGA_HEIGHT) - terminal_row = 0; - return; - } - - terminal_putentryat(c, terminal_color, terminal_column, terminal_row); - if (++terminal_column == VGA_WIDTH) { - terminal_column = 0; - if (++terminal_row == VGA_HEIGHT) - terminal_row = 0; - } -} - -void terminal_write(const char *data, size_t size) { - for (size_t i = 0; i < size; i++) { - terminal_putchar(data[i]); - } -} - -void terminal_writestring(const char *data) { - terminal_write(data, strlen(data)); -} - void kernel_main(void) { - /* Initialize terminal interface */ - terminal_initialize(); - - /* Newline support is left as an exercise. */ - terminal_writestring("Hello world!\nI'm in the kernel and no one can stop me now! =)"); + init_serial(); + if (!test_serial()) { + return; + } + send_serials("Init serial succesfully."); } diff --git a/src/serial.h b/src/serial.h new file mode 100644 index 0000000..4caf342 --- /dev/null +++ b/src/serial.h @@ -0,0 +1,60 @@ +#ifndef SERIAL_H_ +#define SERIAL_H_ + +#include +#define COM1 0x3F8 + +static inline void outb(unsigned short port, unsigned char c) { + __asm__ volatile("outb %0, %1" : : "a"(c), "Nd"(port)); +} + +static inline unsigned char inb(unsigned short port) { + unsigned char ret; + __asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +static inline void send_serial(unsigned char c) { + while ((inb(COM1 + 5) & 0x20) == 0) { + } + + outb(COM1, c); +} + +static inline void send_serials(const char *str) { + while (*str) { + send_serial(*str); + str++; + } +} + +static inline bool test_serial() { + bool to_return = true; + outb(COM1 + 4, 0x10); + send_serial(0xAE); + + while ((inb(COM1 + 5) & 0x01) == 0) { + } + + if (inb(COM1) != 0xAE) + to_return = false; + + outb(COM1 + 4, 0x00); + return to_return; +} + +static inline void init_serial() { + // Set baud rate + outb(COM1 + 3, 0x80); // set MSb to 1 + outb(COM1 + 0, 0x01); // set LSB to 1 for a divisor of 1 (115200 baud rate) + outb(COM1 + 1, 0x00); // set MSB to 0 for a divisor of 1 + outb(COM1 + 3, 0x00); // clean + + // Configure line control register + outb(COM1 + 3, 0x03); // set the two LSb to 11 for a max len of 8bits + + // Disable interrupts + outb(COM1 + 1, 0x00); +} + +#endif // SERIAL_H_