commit d5b504e8154ca4297ac83e2282b4242683e15c51 Author: Ruslan Isaev Date: Fri Mar 14 17:22:59 2025 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f3f17a3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +bin/ +myos.bin + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..71de756 --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ +# Define the object files +OBJS = bin/boot.o bin/kernel.o bin/idt.o bin/isr.o bin/screen.o + +# Define the compiler and assembler +CC = gcc +AS = nasm + +# Define the compiler flags +CFLAGS = -std=gnu99 -ffreestanding -O2 -Wall -Wextra -m32 +ASFLAGS = -f elf32 + +# Define the linker flags +LDFLAGS = -ffreestanding -O2 -nostdlib -m32 +LDSCRIPT = link.ld + +# Define the output file +OUTPUT = myos.bin + +all: $(OUTPUT) + +$(OUTPUT): $(OBJS) + $(CC) -T $(LDSCRIPT) -o $@ $(OBJS) $(LDFLAGS) + +bin/boot.o: src/boot.asm + $(AS) $(ASFLAGS) $< -o $@ + +bin/kernel.o: src/kernel.c + $(CC) $(CFLAGS) -c $< -o $@ + +bin/screen.o: src/screen.c + $(CC) $(CFLAGS) -c $< -o $@ + +bin/isr.o: src/isr.c + $(CC) $(CFLAGS) -c $< -o $@ + +bin/idt.o: src/idt.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -rf bin/ + rm -f $(OUTPUT) + +.PHONY: all clean diff --git a/include/idt.h b/include/idt.h new file mode 100644 index 0000000..fe563e3 --- /dev/null +++ b/include/idt.h @@ -0,0 +1,30 @@ +#ifndef IDT_H +#define IDT_H +#include "../include/types.h" +#include + +typedef struct { + uint16_t isr_low; // The lower 16 bits of the ISR's address + uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR + uint8_t reserved; // Set to zero + uint8_t attributes; // Type and attributes; see the IDT page + uint16_t isr_high; // The higher 16 bits of the ISR's address +} __attribute__((packed)) idt_entry_t; + +__attribute__((aligned(0x10))) +static idt_entry_t idt[256]; // Create an array of IDT entries; aligned for performance + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) idtr_t; + +static idtr_t idtr; + +//void idt_init(void); +//void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags); +void idt_set_descriptor(uint8 vector, uint32 isr, uint8_t flags); +void idt_set(); + +#endif + diff --git a/include/isr.h b/include/isr.h new file mode 100644 index 0000000..1d73735 --- /dev/null +++ b/include/isr.h @@ -0,0 +1,40 @@ +#ifndef ISR_H +#define ISR_H + +void isr0(); +void isr1(); +void isr2(); +void isr3(); +void isr4(); +void isr5(); +void isr6(); +void isr7(); +void isr8(); +void isr9(); +void isr10(); +void isr11(); +void isr12(); +void isr13(); +void isr14(); +void isr15(); +void isr16(); +void isr17(); +void isr18(); +void isr19(); +void isr20(); +void isr21(); +void isr22(); +void isr23(); +void isr24(); +void isr25(); +void isr26(); +void isr27(); +void isr28(); +void isr29(); +void isr30(); +void isr31(); + +static char* exception_messages[32]; + +void isr_install(); +#endif diff --git a/include/screen.h b/include/screen.h new file mode 100644 index 0000000..ede60f2 --- /dev/null +++ b/include/screen.h @@ -0,0 +1,42 @@ +// screen.h +#ifndef SCREEN_H +#define SCREEN_H + +#include +#include +#include + +/* 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 const size_t VGA_WIDTH = 80; +static const size_t VGA_HEIGHT = 25; + +uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg); +uint16_t vga_entry(unsigned char uc, uint8_t color); +size_t strlen(const char* str); +void terminal_initialize(void); +void terminal_setcolor(uint8_t color); +void terminal_putentryat(char c, uint8_t color, size_t x, size_t y); +void terminal_putchar(char c); +void terminal_write(const char* data, size_t size); +void terminal_writestring(const char* data); + +#endif diff --git a/include/types.h b/include/types.h new file mode 100644 index 0000000..d696d74 --- /dev/null +++ b/include/types.h @@ -0,0 +1,21 @@ +#ifndef TYPES_H +#define TYPES_H + +typedef signed char int8; +typedef unsigned char uint8; + +typedef signed short int16; +typedef unsigned short uint16; + +typedef signed int int32; +typedef unsigned int uint32; + +typedef signed long long int64; +typedef unsigned long long uint64; + +typedef char* string; + +#define low_16(address) (uint16)((address) & 0xFFFF) +#define high_16(address) (uint16)(((address) >> 16) & 0xFFFF) + +#endif diff --git a/link.ld b/link.ld new file mode 100644 index 0000000..f398e54 --- /dev/null +++ b/link.ld @@ -0,0 +1,10 @@ +OUTPUT_FORMAT(elf32-i386) +ENTRY(start) +SECTIONS + { + . = 0x100000; + .text : { *(.text) } + .rodata : { *(.rodata) } + .data : { *(.data) } + .bss : { *(.bss) } + } diff --git a/src/boot.asm b/src/boot.asm new file mode 100644 index 0000000..12f3ae0 --- /dev/null +++ b/src/boot.asm @@ -0,0 +1,24 @@ +bits 32 + +section .text + align 4 + dd 0x1BADB002 + dd 0x00 + dd - (0x1BADB002+0x00) + +global start +extern kmain ; this function is gonna be located in our c code(kernel.c) + +start: + cli ;clears the interrupts + call kmain ;send processor to continue execution from the kamin funtion in c code + + +;;;;;;;;;;;DIVISION BY ZERO TEST +; mov ax, 10 +; mov bx, 0 +; div bx +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + hlt ; halt the cpu(pause it from executing from this address + diff --git a/src/idt.c b/src/idt.c new file mode 100644 index 0000000..67e3810 --- /dev/null +++ b/src/idt.c @@ -0,0 +1,40 @@ +#include "../include/idt.h" +#include +//IDT_MAX_DESCRIPTORS = 256 +static bool vectors[sizeof(idt)]; + +extern void* isr_stub_table[]; + +#define KERNEL_CS 0x08 + + +/*void idt_init() { + idtr.base = (uintptr_t)&idt[0]; + idtr.limit = (uint16_t)sizeof(idt_entry_t) * sizeof(idt) - 1; + + for (uint8_t vector = 0; vector < 32; vector++) { + idt_set_descriptor(vector, isr_stub_table[vector], 0x8E); + vectors[vector] = true; + } + + __asm__ volatile ("lidt %0" : : "m"(idtr)); // load the new IDT + __asm__ volatile ("sti"); // set the interrupt flag +}*/ + +void idt_set() { + idtr.base = (uint32) &idt; + idtr.limit = sizeof(idt) * sizeof(idt_entry_t) - 1; + __asm__ __volatile__("lidtl (%0)" : : "r" (&idtr)); +} + + +//void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags) +void idt_set_descriptor(uint8_t vector, uint32 isr, uint8_t flags) { + idt_entry_t* descriptor = &idt[vector]; + + descriptor->isr_low = isr & 0xFFFF; + descriptor->kernel_cs = 0x08; // this value can be whatever offset your kernel code selector is in your GDT + descriptor->attributes = flags; + descriptor->isr_high = high_16(isr);//(uint32_t)isr >> 16; + descriptor->reserved = 0; +} diff --git a/src/isr.c b/src/isr.c new file mode 100644 index 0000000..87b09be --- /dev/null +++ b/src/isr.c @@ -0,0 +1,241 @@ +#include "../include/idt.h" +#include "../include/isr.h" +#include "../include/types.h" +#include "../include/screen.h" + +void isr_install() { + idt_set_descriptor(0, (uint32)isr0, 0x8E); + idt_set_descriptor(1, (uint32)isr1, 0x8E); + idt_set_descriptor(2, (uint32)isr2, 0x8E); + idt_set_descriptor(3, (uint32)isr3, 0x8E); + idt_set_descriptor(4, (uint32)isr4, 0x8E); + idt_set_descriptor(5, (uint32)isr5, 0x8E); + idt_set_descriptor(6, (uint32)isr6, 0x8E); + idt_set_descriptor(7, (uint32)isr7, 0x8E); + idt_set_descriptor(8, (uint32)isr8, 0x8E); + idt_set_descriptor(9, (uint32)isr9, 0x8E); + idt_set_descriptor(10, (uint32)isr10, 0x8E); + idt_set_descriptor(11, (uint32)isr11, 0x8E); + idt_set_descriptor(12, (uint32)isr12, 0x8E); + idt_set_descriptor(13, (uint32)isr13, 0x8E); + idt_set_descriptor(14, (uint32)isr14, 0x8E); + idt_set_descriptor(15, (uint32)isr15, 0x8E); + idt_set_descriptor(16, (uint32)isr16, 0x8E); + idt_set_descriptor(17, (uint32)isr17, 0x8E); + idt_set_descriptor(18, (uint32)isr18, 0x8E); + idt_set_descriptor(19, (uint32)isr19, 0x8E); + idt_set_descriptor(20, (uint32)isr20, 0x8E); + idt_set_descriptor(21, (uint32)isr21, 0x8E); + idt_set_descriptor(22, (uint32)isr22, 0x8E); + idt_set_descriptor(23, (uint32)isr23, 0x8E); + idt_set_descriptor(24, (uint32)isr24, 0x8E); + idt_set_descriptor(25, (uint32)isr25, 0x8E); + idt_set_descriptor(26, (uint32)isr26, 0x8E); + idt_set_descriptor(27, (uint32)isr27, 0x8E); + idt_set_descriptor(28, (uint32)isr28, 0x8E); + idt_set_descriptor(29, (uint32)isr29, 0x8E); + idt_set_descriptor(30, (uint32)isr30, 0x8E); + idt_set_descriptor(31, (uint32)isr31, 0x8E); + + idt_set(); // Load with ASM + terminal_writestring("isr_install done"); +} + +void isr0() +{ + terminal_writestring(exception_messages[0]); + asm("hlt"); +} +void isr1() +{ + terminal_writestring(exception_messages[1]); + asm("hlt"); +} +void isr2() +{ + terminal_writestring(exception_messages[2]); + asm("hlt"); +} +void isr3() +{ + terminal_writestring(exception_messages[3]); + asm("hlt"); +} +void isr4() +{ + terminal_writestring(exception_messages[4]); + asm("hlt"); +} +void isr5() +{ + terminal_writestring(exception_messages[5]); + asm("hlt"); +} +void isr6() +{ + terminal_writestring(exception_messages[6]); + asm("hlt"); +} +void isr7() +{ + terminal_writestring(exception_messages[7]); + asm("hlt"); +} +void isr8() +{ + terminal_writestring(exception_messages[8]); + asm("hlt"); +} +void isr9() +{ + terminal_writestring(exception_messages[9]); + asm("hlt"); +} +void isr10() +{ + terminal_writestring(exception_messages[10]); + asm("hlt"); +} +void isr11() +{ + terminal_writestring(exception_messages[11]); + asm("hlt"); +} +void isr12() +{ + terminal_writestring(exception_messages[12]); + asm("hlt"); +} +void isr13() +{ + terminal_writestring(exception_messages[13]); + asm("hlt"); +} +void isr14() +{ + terminal_writestring(exception_messages[14]); + asm("hlt"); +} +void isr15() +{ + terminal_writestring(exception_messages[15]); + asm("hlt"); +} +void isr16() +{ + terminal_writestring(exception_messages[16]); + asm("hlt"); +} +void isr17() +{ + terminal_writestring(exception_messages[17]); + asm("hlt"); +} +void isr18() +{ + terminal_writestring(exception_messages[18]); + asm("hlt"); +} +void isr19() +{ + terminal_writestring(exception_messages[19]); + asm("hlt"); +} +void isr20() +{ + terminal_writestring(exception_messages[20]); + asm("hlt"); +} +void isr21() +{ + terminal_writestring(exception_messages[21]); + asm("hlt"); +} +void isr22() +{ + terminal_writestring(exception_messages[22]); + asm("hlt"); +} +void isr23() +{ + terminal_writestring(exception_messages[23]); + asm("hlt"); +} +void isr24() +{ + terminal_writestring(exception_messages[24]); + asm("hlt"); +} +void isr25() +{ + terminal_writestring(exception_messages[25]); + asm("hlt"); +} +void isr26() +{ + terminal_writestring(exception_messages[26]); + asm("hlt"); +} +void isr27() +{ + terminal_writestring(exception_messages[27]); + asm("hlt"); +} +void isr28() +{ + terminal_writestring(exception_messages[28]); + asm("hlt"); +} +void isr29() +{ + terminal_writestring(exception_messages[29]); + asm("hlt"); +} +void isr30() +{ + terminal_writestring(exception_messages[30]); + asm("hlt"); +} +void isr31() +{ + terminal_writestring(exception_messages[31]); + asm("hlt"); +} + +static string exception_messages[] = { + "Division By Zero", + "Debug", + "Non Maskable Interrupt", + "Breakpoint", + "Into Detected Overflow", + "Out of Bounds", + "Invalid Opcode", + "No Coprocessor", + + "Double Fault", + "Coprocessor Segment Overrun", + "Bad TSS", + "Segment Not Present", + "Stack Fault", + "General Protection Fault", + "Page Fault", + "Unknown Interrupt", + + "Coprocessor Fault", + "Alignment Check", + "Machine Check", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved" +}; diff --git a/src/kernel.c b/src/kernel.c new file mode 100644 index 0000000..bcfd513 --- /dev/null +++ b/src/kernel.c @@ -0,0 +1,22 @@ +#include "../include/isr.h" +#include "../include/screen.h" + +/* 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" +#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" +#endif +*/ + +void kmain() +{ + terminal_initialize(); + terminal_writestring("KatauOS booting up"); + isr_install(); + terminal_writestring("Kernel init sequence completed"); + return; +} diff --git a/src/screen.c b/src/screen.c new file mode 100644 index 0000000..bffea9c --- /dev/null +++ b/src/screen.c @@ -0,0 +1,73 @@ +// screen.c +#include "../include/screen.h" + +static size_t terminal_row; +static size_t terminal_column; +static uint8_t terminal_color; +static uint16_t* terminal_buffer; + +uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) +{ + return fg | bg << 4; +} + +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; +} + +void terminal_initialize(void) +{ + terminal_row = 0; + terminal_column = 0; + terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); + terminal_buffer = (uint16_t*) 0xB8000; + 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) +{ + 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)); + terminal_row++; + terminal_column = 0; +}