diff --git a/Makefile b/Makefile index c2e7ed0..597a9f1 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ AS = nasm CC = gcc +CFLAGS = -std=c11 -m32 -ffreestanding -c -fno-stack-protector -fno-pie LD = ld QEMU = qemu-system-i386 IMG_SIZE = 1440k @@ -10,8 +11,15 @@ BOOT_SRC = bootloader/boot.asm BOOT_OBJ = $(BUILD_DIR)/boot.o BOOT_ELF = $(BUILD_DIR)/boot.elf BOOT_IMG = $(BUILD_DIR)/boot.img -KERNEL_SRC = kernel/kmain.c + +KERNEL_C_SRC = $(wildcard kernel/*.c) +KERNEL_ASM_SRC = $(wildcard kernel/*.asm) +KERNEL_OBJ = $(patsubst kernel/%.c, $(BUILD_DIR)/%.o, $(KERNEL_C_SRC)) +KERNEL_OBJ += $(patsubst kernel/%.asm, $(BUILD_DIR)/asm_%.o, $(KERNEL_ASM_SRC)) +KERNEL_OBJ += $(BUILD_DIR)/boot1.o +KERNEL_ELF = $(BUILD_DIR)/kernel.elf KERNEL_BIN = $(BUILD_DIR)/kernel.bin + DISK_IMG = $(BUILD_DIR)/disk.img all: $(BOOT_IMG) $(KERNEL_BIN) $(DISK_IMG) @@ -29,9 +37,17 @@ $(BOOT_IMG): $(BOOT_ELF) objcopy -O binary $< $@ truncate -s $(IMG_SIZE) $@ -$(KERNEL_BIN): $(KERNEL_SRC) | $(BUILD_DIR) - $(CC) -ffreestanding -c $< -o $(BUILD_DIR)/kernel.o - $(LD) -T bootloader/linker.ld -o $@ $(BUILD_DIR)/kernel.o +$(BUILD_DIR)/boot1.o: bootloader/boot1.asm + $(AS) -f elf32 -o $@ $< + +$(BUILD_DIR)/asm_%.o: kernel/%.asm + $(AS) -f elf32 -o $@ $< + +$(BUILD_DIR)/%.o: kernel/%.c + $(CC) $(CFLAGS) $< -o $@ + +$(KERNEL_BIN): $(KERNEL_OBJ) | $(BUILD_DIR) + $(LD) -melf_i386 --oformat binary -T bootloader/linker.ld -o $@ $(KERNEL_OBJ) $(DISK_IMG): $(BOOT_IMG) $(KERNEL_BIN) dd if=$(BOOT_IMG) of=$@ bs=512 seek=4 diff --git a/kernel/cpu.c b/kernel/cpu.c index 96aa335..a18041b 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -5,7 +5,7 @@ #include "print.h" void cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { - asm volatile ( + __asm__( "cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(function) @@ -32,6 +32,6 @@ void identify_cpu() { serial_write("\n"); terminal_write("CPUID max leaf: "); - print_hex(eax); // You must implement this (see below) + print_hex(eax, false, false); // You must implement this (see below) terminal_write("\n"); } diff --git a/kernel/idt.c b/kernel/idt.c index 2bb5af3..2cbfc4f 100644 --- a/kernel/idt.c +++ b/kernel/idt.c @@ -52,7 +52,7 @@ void idt_set_gate(int n, uint32_t handler) { // Load IDT via lidt static void idt_load() { - asm volatile("lidt (%0)" : : "r" (&idt_ptr)); + __asm__("lidt (%0)" : : "r" (&idt_ptr)); } // IDT initialization diff --git a/kernel/io.h b/kernel/io.h index aaaee3a..76d696b 100644 --- a/kernel/io.h +++ b/kernel/io.h @@ -4,12 +4,12 @@ #include static inline void outb(uint16_t port, uint8_t val) { - asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); + __asm__("outb %0, %1" : : "a"(val), "Nd"(port)); } static inline uint8_t inb(uint16_t port) { uint8_t ret; - asm volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port)); + __asm__("inb %1, %0" : "=a"(ret) : "Nd"(port)); return ret; } diff --git a/kernel/isr.asm b/kernel/isr.asm index deba3e0..7bd4999 100644 --- a/kernel/isr.asm +++ b/kernel/isr.asm @@ -1,8 +1,8 @@ [BITS 32] -[GLOBAL isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7, isr8, isr9] -[GLOBAL isr10, isr11, isr12, isr13, isr14, isr15, isr16, isr17, isr18, isr19] -[GLOBAL isr20, isr21, isr22, isr23, isr24, isr25, isr26, isr27, isr28, isr29] -[GLOBAL isr30, isr31, isr_default] +GLOBAL isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7, isr8, isr9 +GLOBAL isr10, isr11, isr12, isr13, isr14, isr15, isr16, isr17, isr18, isr19 +GLOBAL isr20, isr21, isr22, isr23, isr24, isr25, isr26, isr27, isr28, isr29 +GLOBAL isr30, isr31, isr_default [EXTERN isr_handler] diff --git a/kernel/isr.c b/kernel/isr.c index 636a189..c4d7189 100644 --- a/kernel/isr.c +++ b/kernel/isr.c @@ -2,20 +2,20 @@ #include "serial.h" #include "isr.h" #include "io.h" -#include "utils.h" +#include "print.h" static isr_callback_t interrupt_handlers[MAX_INTERRUPTS] = { 0 }; void isr_handler(uint32_t int_num, uint32_t err_code) { terminal_write("Interrupt occurred: "); - print_hex(int_num); + print_hex(int_num, true, false); terminal_write("\n"); serial_write("INT triggered\n"); terminal_write("Error code: "); - print_hex(err_code); + print_hex(err_code, true, false); terminal_write("\n"); if (interrupt_handlers[int_num]) { @@ -33,7 +33,7 @@ void isr_handler(uint32_t int_num, uint32_t err_code) { // Halt CPU while (1) { - asm volatile ("hlt"); + __asm__("hlt"); } } diff --git a/kernel/kmain.c b/kernel/kmain.c index 05ea503..b522142 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -1,5 +1,4 @@ #include -#include #include "io.h" #include "serial.h" #include "terminal.h" @@ -9,6 +8,7 @@ #include "gdt.h" #include "cpu.h" #include "kmalloc.h" +#include "print.h" #include "timer.h" #include "utils.h" #include "keyboard.h" @@ -69,9 +69,9 @@ void kmain(void) { char buf[32]; for (uint32_t i = 0; i < mmap_size; i++) { terminal_write(" - Base: "); - print_hex((uint32_t)(mmap[i].base_addr & 0xFFFFFFFF)); // Lower 32 bits + print_hex((uint32_t)(mmap[i].base_addr & 0xFFFFFFFF), true, false); // Lower 32 bits terminal_write(", Length: "); - print_hex((uint32_t)(mmap[i].length & 0xFFFFFFFF)); // Lower 32 bits + print_hex((uint32_t)(mmap[i].length & 0xFFFFFFFF), true, false); // Lower 32 bits terminal_write(", Type: "); itoa(mmap[i].type, buf, 10); terminal_write(buf); @@ -82,6 +82,6 @@ void kmain(void) { // Halt CPU in loop while (1) { - asm volatile("hlt"); + __asm__("hlt"); } } diff --git a/kernel/mouse.c b/kernel/mouse.c index 514844c..8d6ece6 100644 --- a/kernel/mouse.c +++ b/kernel/mouse.c @@ -10,7 +10,7 @@ static mouse_data_t mouse_data; // Read USB mouse data mouse_data_t usb_read_mouse(void) { uint8_t buffer[3]; // USB HID Mouse reports typically use 3 bytes - if (usb_interrupt_transfer(buffer, sizeof(buffer))) { // Ensure buffer is filled + if (usb_interrupt_transfer()) { // Ensure buffer is filled // Process the received data mouse_data.x += buffer[1]; // X movement mouse_data.y += buffer[2]; // Y movement diff --git a/kernel/paging.c b/kernel/paging.c index 17509ee..847d150 100644 --- a/kernel/paging.c +++ b/kernel/paging.c @@ -37,12 +37,12 @@ void enable_paging() { uint32_t cr0; // Load page directory into CR3 - asm volatile("mov %0, %%cr3" : : "r"(page_directory)); + __asm__("mov %0, %%cr3" : : "r"(page_directory)); // Enable paging (set the PG bit in CR0) - asm volatile("mov %%cr0, %0" : "=r"(cr0)); + __asm__("mov %%cr0, %0" : "=r"(cr0)); cr0 |= 0x80000000; // Set the PG (paging) bit - asm volatile("mov %0, %%cr0" : : "r"(cr0)); + __asm__("mov %0, %%cr0" : : "r"(cr0)); } // Initialize paging: set up the page directory and enable paging diff --git a/kernel/panic.c b/kernel/panic.c index 477ff66..6de41cc 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -14,6 +14,6 @@ void panic(const char *message) { // Halt the system while (true) { - asm volatile ("cli; hlt"); + __asm__("cli; hlt"); } } diff --git a/kernel/print.c b/kernel/print.c index d5a829f..54251fd 100644 --- a/kernel/print.c +++ b/kernel/print.c @@ -1,13 +1,14 @@ -#include #include #include "print.h" +#include "serial.h" +#include "terminal.h" void my_putchar(char ch) { // Write a single character to standard output // In a freestanding environment, you might need to implement this differently // For now, we will use the standard putchar for demonstration // Replace this with your own implementation if needed - putchar(ch); + terminal_putchar(ch); } void print_string(const char *str) { @@ -33,7 +34,9 @@ void my_printf(const char *format, ...) { case 'd': { // Integer int num = va_arg(args, int); char buffer[20]; // Buffer to hold the string representation - snprintf(buffer, sizeof(buffer), "%d", num); + + //TODO: implement `snprintf()` + //snprintf(buffer, sizeof(buffer), "%d", num); print_string(buffer); break; } @@ -56,29 +59,44 @@ void my_printf(const char *format, ...) { va_end(args); } +void print_hex(uint32_t val, int include_prefix, int suppress_leading_zeros) { + char hex_chars[] = "0123456789ABCDEF"; + char buffer[11]; // 8 hex digits + "0x" + null terminator + int pos = 10; // Start from end of buffer (null terminator) -void print_hex(unsigned int num) { - // Buffer to hold the hexadecimal representation - char buffer[9]; // 8 hex digits + null terminator - buffer[8] = '\0'; // Null-terminate the string + // Null-terminate the buffer + buffer[pos--] = '\0'; + // Convert value to hex digits for (int i = 7; i >= 0; i--) { - int digit = num & 0xF; // Get the last 4 bits - buffer[i] = (digit < 10) ? (digit + '0') : (digit - 10 + 'A'); // Convert to hex character - num >>= 4; // Shift right by 4 bits + int digit = val & 0xF; // Get last 4 bits + buffer[pos--] = hex_chars[digit]; + val >>= 4; // Shift right by 4 bits } - // Print the buffer, skipping leading zeros - int leading_zero = 1; - for (int i = 0; i < 8; i++) { - if (buffer[i] != '0') { - leading_zero = 0; // Found a non-zero digit - } - if (!leading_zero) { - my_putchar(buffer[i]); - } + // Add "0x" prefix if requested + if (include_prefix) { + buffer[pos--] = 'x'; + buffer[pos--] = '0'; } - if (leading_zero) { - my_putchar('0'); // If all were zeros, print a single '0' + + // Determine start of output (skip leading zeros if requested) + int start = include_prefix ? 0 : 2; // Start after "0x" if prefix included + if (suppress_leading_zeros && !include_prefix) { + int i = start; + while (i < 9 && buffer[i] == '0') { + i++; + } + if (i == 10) { + // All zeros, output single '0' + terminal_write("0"); + serial_write("0"); + return; + } + start = i; } -} \ No newline at end of file + + // Output the result + terminal_write(buffer + start); + serial_write(buffer + start); +} diff --git a/kernel/print.h b/kernel/print.h index 61c08ae..bf07e4a 100644 --- a/kernel/print.h +++ b/kernel/print.h @@ -1,9 +1,11 @@ #ifndef PRINT_H #define PRINT_H +#include "types.h" + void print_string(const char *str); void my_printf(const char *format, ...); -void print_hex(unsigned int num); +void print_hex(uint32_t val, int include_prefix, int suppress_leading_zeros); void my_putchar(char ch); #endif diff --git a/kernel/shell.c b/kernel/shell.c index 43b261c..f975f58 100644 --- a/kernel/shell.c +++ b/kernel/shell.c @@ -2,8 +2,6 @@ #include "keyboard.h" #include "terminal.h" #include "print.h" -#include -#include #include "string_utils.h" void execute(char *input) { @@ -49,7 +47,7 @@ void shell_loop() { if (index < sizeof(input) - 1) { input[index++] = c; - putchar(c); + terminal_putchar(c); } } } diff --git a/kernel/threading.c b/kernel/threading.c index f8b3c0a..c7b6ba5 100644 --- a/kernel/threading.c +++ b/kernel/threading.c @@ -1,8 +1,9 @@ +#include "malloc.h" +#include "print.h" #include "threading.h" -#include +#include "types.h" +#include "utils.h" #include -#include -#include #define MAX_THREADS 16 // Maximum number of threads #define THREAD_STACK_SIZE 8192 // Stack size for each thread @@ -27,7 +28,7 @@ void thread_init(void) { // Create a new thread void thread_create(Thread *thread __attribute__((unused)), void (*start_routine)(void *), void *arg) { if (num_threads >= MAX_THREADS) { - printf("Error: Maximum thread count reached.\n"); + my_printf("Error: Maximum thread count reached.\n"); return; } @@ -98,7 +99,7 @@ void scheduler(void) { void context_switch(Thread *next) { // For simplicity, context switching in this example would involve saving/restoring registers. // In a real system, you would need to save the CPU state (registers) and restore the next thread's state. - printf("Switching to thread...\n"); + my_printf("Switching to thread...\n"); next->start_routine(next->arg); // Start running the next thread } diff --git a/kernel/timer.c b/kernel/timer.c index ab4a859..f47ec36 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -3,6 +3,7 @@ #include "isr.h" #include "terminal.h" #include "stdio.h" +#include "utils.h" static volatile uint32_t tick = 0; diff --git a/kernel/types.c b/kernel/types.c index 6936871..8e71fd1 100644 --- a/kernel/types.c +++ b/kernel/types.c @@ -1,9 +1 @@ #include "types.h" - -// Example: Basic memory helper (unnecessary if libc exists) -void *memset(void *dest, int value, size_t len) { - unsigned char *ptr = (unsigned char *)dest; - while (len-- > 0) - *ptr++ = (unsigned char)value; - return dest; -} diff --git a/kernel/utils.c b/kernel/utils.c index 04dd14c..f41ceff 100644 --- a/kernel/utils.c +++ b/kernel/utils.c @@ -1,6 +1,4 @@ #include "utils.h" -#include "serial.h" -#include "terminal.h" static void reverse(char* str, int len) { int start = 0; @@ -79,13 +77,19 @@ char* utoa(unsigned int value, char* str, int base) { return str; } -void print_hex(uint32_t val) { - char hex_chars[] = "0123456789ABCDEF"; - char buf[11] = "0x00000000"; - for (int i = 9; i >= 2; i--) { - buf[i] = hex_chars[val & 0xF]; - val >>= 4; +int memcmp(const void *ptr1, const void *ptr2, size_t num) { + const uint8_t *p1 = ptr1, *p2 = ptr2; + for (size_t i = 0; i < num; i++) { + if (p1[i] != p2[i]) { + return p1[i] < p2[i] ? -1 : 1; + } } - terminal_write(buf); - serial_write(buf); -} \ No newline at end of file + return 0; +} + +void *memset(void *dest, int value, size_t len) { + unsigned char *ptr = (unsigned char *)dest; + while (len-- > 0) + *ptr++ = (unsigned char)value; + return dest; +} diff --git a/kernel/utils.h b/kernel/utils.h index 9ef78d9..78f9d44 100644 --- a/kernel/utils.h +++ b/kernel/utils.h @@ -1,7 +1,7 @@ #ifndef UTILS_H #define UTILS_H -#include +#include "types.h" // Convert integer to string (base is typically 10, 16, etc.) char* itoa(int value, char* str, int base); @@ -9,6 +9,7 @@ char* itoa(int value, char* str, int base); // Convert unsigned integer to string (base is typically 10, 16, etc.) char* utoa(unsigned int value, char* str, int base); -void print_hex(uint32_t val); +int memcmp(const void *ptr1, const void *ptr2, size_t num); +void *memset(void *dest, int value, size_t len); #endif // UTILS_H