added origin program

This commit is contained in:
2026-06-16 18:44:31 -05:00
parent 0a51a5e8bc
commit 171cbd21bc
12 changed files with 262 additions and 28 deletions

View File

@@ -1,3 +1,4 @@
menuentry "RockOS" {
multiboot /boot/rockos
module /boot/origin.elf
}

37
kernel/elf.h Normal file
View File

@@ -0,0 +1,37 @@
#ifndef KELF_H
#define KELF_H
#include <stdint.h>
#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

View File

@@ -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();
}

View File

@@ -11,4 +11,10 @@ reload_segments:
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
ret
ret
.global tss_flush
tss_flush:
mov $0x28, %ax
ltr %ax
ret

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -1,4 +1,4 @@
#include "lib/print.h"
#include "memory/mm.h"
#include "multiboot.h"
#include <stddef.h>
@@ -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;
}

View File

@@ -3,16 +3,23 @@
#include <stdint.h>
#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

View File

@@ -11,4 +11,15 @@ disable_pae:
and $0xFFFFFFEF, %edx
mov %edx, %cr4
ret
.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

View File

@@ -3,7 +3,7 @@
#include <stdint.h>
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

16
programs/makefile Normal file
View File

@@ -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

8
programs/origin.S Normal file
View File

@@ -0,0 +1,8 @@
.code32
.section .text
.global _start
_start:
mov $1, %eax
add $1, %eax
loop:
jmp loop