From 171cbd21bc1c032bc3818696b937007bc6013bec Mon Sep 17 00:00:00 2001 From: slinky55 Date: Tue, 16 Jun 2026 18:44:31 -0500 Subject: [PATCH] added origin program --- grub.cfg | 1 + kernel/elf.h | 37 +++++++++++++++++++++ kernel/gdt.c | 65 +++++++++++++++++++++++++++++++++++-- kernel/gdt_stubs.S | 8 ++++- kernel/interrupts.c | 15 ++++++++- kernel/kmain.c | 70 ++++++++++++++++++++++++++++++++++++++-- kernel/memory/mm.c | 33 ++++++++++--------- kernel/memory/mm.h | 9 +++++- kernel/memory/mm_stubs.S | 13 +++++++- kernel/multiboot.h | 15 ++++++--- programs/makefile | 16 +++++++++ programs/origin.S | 8 +++++ 12 files changed, 262 insertions(+), 28 deletions(-) create mode 100644 kernel/elf.h create mode 100644 programs/makefile create mode 100644 programs/origin.S diff --git a/grub.cfg b/grub.cfg index 63ee132..67bab1e 100644 --- a/grub.cfg +++ b/grub.cfg @@ -1,3 +1,4 @@ menuentry "RockOS" { multiboot /boot/rockos + module /boot/origin.elf } \ No newline at end of file diff --git a/kernel/elf.h b/kernel/elf.h new file mode 100644 index 0000000..fea2a46 --- /dev/null +++ b/kernel/elf.h @@ -0,0 +1,37 @@ +#ifndef KELF_H +#define KELF_H + +#include + +#define ELF_MAGIC 0x464C457F +#define PT_LOAD 1 + +typedef struct { + uint8_t e_ident[16]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint32_t e_entry; + uint32_t e_phoff; + uint32_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} __attribute__((packed)) elf_header_t; + +typedef struct { + uint32_t p_type; + uint32_t p_offset; + uint32_t p_vaddr; + uint32_t p_paddr; + uint32_t p_filesz; + uint32_t p_memsz; + uint32_t p_flags; + uint32_t p_align; +} __attribute__((packed)) elf_program_header_t; + +#endif \ No newline at end of file diff --git a/kernel/gdt.c b/kernel/gdt.c index 0fffd64..7db6b84 100644 --- a/kernel/gdt.c +++ b/kernel/gdt.c @@ -45,11 +45,44 @@ typedef struct __attribute__((packed)) { uint16_t limit; uint32_t base; } gdt_ptr_t; + +typedef struct __attribute__((packed)) { + uint32_t prev_tss; + uint32_t esp0; + uint32_t ss0; + uint32_t esp1; + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap; + uint16_t iomap_base; +} tss_entry; -uint64_t gdt[5]; +uint64_t gdt[6]; gdt_ptr_t gdtr; +tss_entry tss; + extern void load_gdt(); +extern void tss_flush(); uint64_t create_descriptor(uint32_t base, uint32_t limit, uint16_t flag) { @@ -68,6 +101,24 @@ uint64_t create_descriptor(uint32_t base, uint32_t limit, uint16_t flag) return descriptor; } +uint64_t create_tss_descriptor(uint32_t base, uint32_t limit) +{ + uint64_t descriptor; + uint16_t tss_flags = SEG_PRES(1) | SEG_PRIV(0) | SEG_DESCTYPE(0) | 0x09; + + descriptor = limit & 0x000F0000; + descriptor |= (tss_flags << 8) & 0x00F0FF00; + descriptor |= (base >> 16) & 0x000000FF; + descriptor |= base & 0xFF000000; + + descriptor <<= 32; + + descriptor |= base << 16; + descriptor |= limit & 0x0000FFFF; + + return descriptor; +} + void init_gdt() { gdt[0] = create_descriptor(0, 0, 0); gdt[1] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL0)); @@ -75,9 +126,17 @@ void init_gdt() { gdt[3] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL3)); gdt[4] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL3)); - gdtr.limit = 5 * sizeof(uint64_t) - 1; - gdtr.base = (uint32_t)&gdt; + for (uint32_t i = 0; i < sizeof(tss_entry); i++) { + ((char*)&tss)[i] = 0; + } + tss.ss0 = 0x10; + tss.iomap_base = sizeof(tss_entry); + gdt[5] = create_tss_descriptor((uint32_t)&tss, sizeof(tss_entry) - 1); + + gdtr.limit = 6 * sizeof(uint64_t) - 1; + gdtr.base = (uint32_t)&gdt; load_gdt(); + tss_flush(); } diff --git a/kernel/gdt_stubs.S b/kernel/gdt_stubs.S index 760ebe7..762b276 100644 --- a/kernel/gdt_stubs.S +++ b/kernel/gdt_stubs.S @@ -11,4 +11,10 @@ reload_segments: mov %ax, %fs mov %ax, %gs mov %ax, %ss - ret \ No newline at end of file + ret + +.global tss_flush +tss_flush: + mov $0x28, %ax + ltr %ax + ret \ No newline at end of file diff --git a/kernel/interrupts.c b/kernel/interrupts.c index a8f3fbf..21db4f5 100644 --- a/kernel/interrupts.c +++ b/kernel/interrupts.c @@ -41,11 +41,24 @@ void common_interrupt_handler(struct registers *args) { case 11: case 12: case 13: - case 14: case 15: case 16: kprintf("CPU Error: %s", err_messages[args->int_no]); break; + case 14:{ + uint32_t faulting_address; + asm volatile("mov %%cr2, %0" : "=r"(faulting_address)); + kprintf("\n--- PAGE FAULT ---\n"); + kprintf("Faulting Virtual Address (CR2): 0x%x\n", faulting_address); + kprintf("Error Code: 0x%x\n", args->error_code); + kprintf("Instruction Pointer (EIP): 0x%x\n", args->eip); + kprintf("Caused by: %s, %s, running in %s mode\n", + (args->error_code & 0x01) ? "Page protection violation" : "Non-present page", + (args->error_code & 0x02) ? "Write operation" : "Read operation", + (args->error_code & 0x04) ? "User (Ring 3)" : "Supervisor (Ring 0)"); + while(1); + break; + } case 32: // wake the PIT timer driver send_eoi_master(); diff --git a/kernel/kmain.c b/kernel/kmain.c index 284c9fb..2ce815c 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -9,6 +9,8 @@ #include "memory/mm.h" +#include "elf.h" + extern void init_idt(); extern void init_gdt(); extern void init_pic(); @@ -23,6 +25,69 @@ extern char __kernel_end; void* user_page_directories[10]; +void load_origin_program(multiboot_info* mbi) { + user_page_directories[0] = create_user_pd(); + kprintf("Created origin process page directory @ [phys] 0x%x\n", user_page_directories[0]); + extern void load_pd(void* pd); + extern void flush_tlb(); + load_pd(user_page_directories[0]); + flush_tlb(); + kprintf("switched to user address space\n"); + + uint32_t mods_virtual_addr = mbi->mods_addr + 0xC0000000; + kprintf("parsing mutliboot modules @ 0x%x\n", mods_virtual_addr); + + if (mbi->mods_count == 0) { + return; + } + + multiboot_module_entry* modules = (multiboot_module_entry*)mods_virtual_addr; + + uint32_t elf_vbase = 0xE0000000; + uint32_t elf_pbase = modules[0].mod_start; + uint32_t elf_limit = modules[0].mod_end - modules[0].mod_start; + uint32_t elf_pages_needed = (elf_limit / 4096) + 1; + + for (uint32_t i = 0; i < elf_pages_needed; i++) { + const uint32_t vaddr = elf_vbase + (i * 4096); + const uint32_t paddr = elf_pbase + (i * 4096); + map_page(vaddr, paddr, PAGE_PRESENT | PAGE_WRITABLE); + } + + elf_header_t* elf = (elf_header_t*)elf_vbase; + elf_program_header_t* ph = (elf_program_header_t*)(elf_vbase + elf->e_phoff); + + kprintf("elf header @ 0x%x\n", elf); + kprintf("program headers @ 0x%x\n", ph); + + // load program sections into physical memory and map the pages + for (int i = 0; i < elf->e_phnum; i++) { + if (ph[i].p_type == PT_LOAD) { + uint32_t v_start = ph[i].p_vaddr & 0xFFFFF000; + uint32_t v_end = (ph[i].p_vaddr + ph[i].p_memsz + 4095) & 0xFFFFF000; + + for (uint32_t page = v_start; page < v_end; page += 4096) { + uint32_t frame_paddr = (uint32_t)p_alloc_frame(); + map_page(page, frame_paddr, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER); + } + + for (uint32_t j = 0; j < ph[i].p_memsz; j++) { + ((char*)ph[i].p_vaddr)[j] = 0; + } + + for (uint32_t j = 0; j < ph[i].p_filesz; j++) { + ((char*)ph[i].p_vaddr)[j] = ((char*)(elf_vbase + ph[i].p_offset))[j]; + } + } + } + + // allocate the user stack + uint32_t stack_paddr = (uint32_t)p_alloc_frame(); + map_page(0xBFFFF000, stack_paddr, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER); + + kprintf("program loaded into memory @ [virt] 0x%x\n", elf->e_entry); +} + void kmain(uint32_t magic, multiboot_info* mbi) { extern print_stream_t vga_print_stream; extern print_stream_t* kout; @@ -39,6 +104,8 @@ void kmain(uint32_t magic, multiboot_info* mbi) { } kprintf("multiboot virtual address: 0x%x\n", mbi); + + kprintf("parsing multiboot memory map\n"); uint32_t mmap_virtual_addr = mbi->mmap_addr + 0xC0000000; kprintf("mmap virtual address: 0x%x\n", mmap_virtual_addr); init_pmm((void*)mmap_virtual_addr, mbi->mmap_length); @@ -70,8 +137,7 @@ void kmain(uint32_t magic, multiboot_info* mbi) { init_page_tables(); kprintf("Page tables initialized\n"); - user_page_directories[0] = create_user_pd(); - kprintf("Created first user process page directory @ 0x%x\n", user_page_directories[0]); + load_origin_program(mbi); while(1); } diff --git a/kernel/memory/mm.c b/kernel/memory/mm.c index 634d8b9..494e1c5 100644 --- a/kernel/memory/mm.c +++ b/kernel/memory/mm.c @@ -1,4 +1,4 @@ -#include "lib/print.h" +#include "memory/mm.h" #include "multiboot.h" #include @@ -19,10 +19,6 @@ extern void disable_pae(); #define TEMP_MAPPING_VADDR 0xE0000000 -#define PAGE_PRESENT 0x1 -#define PAGE_WRITABLE 0x2 -#define PAGE_USER 0x4 - static uint32_t max_address = 0; static uint32_t total_available_memory = 0; static uint8_t memory_bitmap[BITMAP_SIZE]; @@ -92,7 +88,7 @@ static void parse_multiboot_mmap(void* base, uint32_t limit) { } } -static void* p_alloc_frame() { +void* p_alloc_frame() { for (uint32_t i = 0; i < BITMAP_SIZE; i++) { uint8_t b = memory_bitmap[i]; if (b == 0xFF) { @@ -116,7 +112,7 @@ static void p_free_frame(void* addr) { } // MODIFIES THE ACTIVE PAGE TABLE AT THE PHYSICAL ADDRESS LOADED INTO CR3 VIA RECURSIVE MAPPING -static void map_page(uint32_t vaddr, uint32_t paddr, uint32_t flags) { +void map_page(uint32_t vaddr, uint32_t paddr, uint32_t flags) { uint32_t pde_entry = vaddr >> 22; uint32_t pte_entry = (vaddr >> 12) & 0x3FF; uint32_t* pd = (uint32_t*)PAGE_DIRECTORY; @@ -124,7 +120,7 @@ static void map_page(uint32_t vaddr, uint32_t paddr, uint32_t flags) { if ((pd[pde_entry] & PAGE_PRESENT) == 0) { uint32_t new_table = (uint32_t)p_alloc_frame(); - pd[pde_entry] = new_table | PAGE_PRESENT | PAGE_WRITABLE; + pd[pde_entry] = new_table | flags; flush_tlb(); for (int i = 0; i < 1024; i++) { tablev[i] = 0; @@ -146,11 +142,16 @@ void init_pmm(void* mmap_base, uint32_t mmap_limit) { } void init_page_tables() { - uint32_t* kernel_table = p_alloc_frame(); - for (int i = 0; i < 1024; i++) { - kernel_table[i] = (i * PAGE_SIZE) | 0x3; + uint32_t kernel_size = (uint32_t)&__kernel_end - (uint32_t)&__kernel_start; + uint32_t num_pages = kernel_size / PAGE_SIZE + 1; + uint32_t num_page_tables = (num_pages + 1023) / 1024; + for (uint32_t table = 0; table < num_page_tables; table++) { + uint32_t* kernel_table = p_alloc_frame(); + for (int i = 0; i < 1024; i++) { + kernel_table[i] = (i * PAGE_SIZE) | 0x3; + } + page_directory[768 + table] = (uint32_t)(kernel_table) | 0x3; } - page_directory[768] = (uint32_t)(kernel_table) | 0x3; page_directory[0] = 0; disable_pae(); flush_tlb(); @@ -171,17 +172,19 @@ void* create_user_pd() { uint32_t* user_pd = (uint32_t*)TEMP_MAPPING_VADDR; uint32_t* kernel_pd = (uint32_t*)PAGE_DIRECTORY; - for(int i = 0; i < 1024; i++) { + for(int i = 0; i < 768; i++) { user_pd[i] = 0; } - user_pd[768] = kernel_pd[768]; + for(int i = 768; i < 1023; i++) { + user_pd[i] = kernel_pd[i]; + } + user_pd[1023] = (uint32_t)pd_address | PAGE_PRESENT | PAGE_WRITABLE; uint32_t pde = TEMP_MAPPING_VADDR >> 22; uint32_t pte = (TEMP_MAPPING_VADDR >> 12) & 0x3FF; uint32_t* kernel_pt = (uint32_t*)(PAGE_TABLES + (pde * PAGE_SIZE)); kernel_pt[pte] = 0; - flush_tlb(); return (void*)pd_address; } \ No newline at end of file diff --git a/kernel/memory/mm.h b/kernel/memory/mm.h index a17876a..99060e4 100644 --- a/kernel/memory/mm.h +++ b/kernel/memory/mm.h @@ -3,16 +3,23 @@ #include +#define PAGE_PRESENT 0x1 +#define PAGE_WRITABLE 0x2 +#define PAGE_USER 0x4 + typedef struct __attribute__((packed)) { uint32_t addr; } mem_page_t; void init_pmm(void* mmap_base, uint32_t mmap_limit); void init_page_tables(); -void* init_kheap(); + +void* p_alloc_frame(); uint32_t total_free_memory(); void* create_user_pd(); +void map_page(uint32_t vaddr, uint32_t paddr, uint32_t flags); + #endif diff --git a/kernel/memory/mm_stubs.S b/kernel/memory/mm_stubs.S index 5cd8690..2de6d53 100644 --- a/kernel/memory/mm_stubs.S +++ b/kernel/memory/mm_stubs.S @@ -11,4 +11,15 @@ disable_pae: and $0xFFFFFFEF, %edx mov %edx, %cr4 ret - \ No newline at end of file + +.global load_pd +load_pd: + push %ebp + mov %esp, %ebp + mov 8(%ebp), %eax + mov %eax, %cr3 + lea flush, %ecx + jmp *%ecx +flush: + leave + ret \ No newline at end of file diff --git a/kernel/multiboot.h b/kernel/multiboot.h index 3d39f3d..dd26241 100644 --- a/kernel/multiboot.h +++ b/kernel/multiboot.h @@ -3,7 +3,7 @@ #include -typedef struct { +typedef struct { uint32_t flags; uint32_t mem_lower; uint32_t mem_upper; @@ -17,13 +17,20 @@ typedef struct { uint32_t shndx; uint32_t mmap_length; uint32_t mmap_addr; -} multiboot_info; +} __attribute__((packed)) multiboot_info; -typedef struct __attribute__((packed)) { +typedef struct { uint32_t size; uint64_t addr; uint64_t len; uint32_t type; -} multiboot_mmap_entry; +} __attribute__((packed)) multiboot_mmap_entry; + +typedef struct { + uint32_t mod_start; // Physical start address of user.elf in memory + uint32_t mod_end; // Physical end address of user.elf + uint32_t cmdline; // Pointer to a string (e.g., "/boot/user.elf") + uint32_t pad; +} __attribute__((packed)) multiboot_module_entry; #endif \ No newline at end of file diff --git a/programs/makefile b/programs/makefile new file mode 100644 index 0000000..f84e57b --- /dev/null +++ b/programs/makefile @@ -0,0 +1,16 @@ +CC = i686-elf-gcc +LD = i686-elf-ld + +CFLAGS := -ffreestanding -O2 -Wall -Wextra + +all: origin.elf + +origin.o: origin.S + $(CC) -c origin.S -o origin.o $(CFLAGS) + +origin.elf: origin.o + $(LD) -Ttext 0x40000000 origin.o -o origin.elf + mv origin.elf ../isodir/boot + +clean: + rm -f origin.o origin.elf \ No newline at end of file diff --git a/programs/origin.S b/programs/origin.S new file mode 100644 index 0000000..b4b9469 --- /dev/null +++ b/programs/origin.S @@ -0,0 +1,8 @@ +.code32 +.section .text +.global _start +_start: + mov $1, %eax + add $1, %eax +loop: + jmp loop \ No newline at end of file