working on reading elf from initrd, and getting it launched with the new scheduler

This commit is contained in:
2026-06-30 19:26:31 -05:00
parent ce81d4eb31
commit af6c1c94cf
21 changed files with 253 additions and 151 deletions

View File

@@ -2,4 +2,5 @@
mkdir -p output
rm -rf output/*
find . -depth -print | cpio -o -H newc > output/initrd.img
find . -depth -print | cpio -o -H newc > output/initrd.img
cp output/initrd.img ../isodir/boot

View File

@@ -120,4 +120,6 @@ outsw:
.global fetch_cr3
fetch_cr3:
mov %cr3, %eax
ret
ret
.global set_cr3

View File

@@ -34,7 +34,7 @@ static uint32_t cpio_read(struct vfs_node* node, uint32_t offset, uint32_t size,
if (offset + size > node->size) {
size = node->size - offset;
}
memcpy(buffer, (uint8_t*)(node->ptr) + offset, size);
memcpy((uint8_t*)(node->data) + offset, buffer, size);
return size;
}
@@ -80,7 +80,7 @@ vfs_node_t* cpio_read_fs(uint32_t _vaddr) {
current->flags = VFS_FILE;
current->read = cpio_read;
current->ptr = (vfs_node_t*)file_data;
current->data = file_data;
}
uint32_t next_header_offset = file_data_offset + filesize;

View File

@@ -1,4 +1,4 @@
#include <stdint.h>
#include <gdt.h>
#define SEG_DESCTYPE(x) ((x) << 0x04) // Descriptor type (0 for system, 1 for code/data)
#define SEG_PRES(x) ((x) << 0x07) // Present
@@ -45,41 +45,11 @@ 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[6];
gdt_ptr_t gdtr;
tss_entry tss;
tss_entry_t tss;
extern void load_gdt();
extern void tss_flush();
@@ -126,14 +96,14 @@ void init_gdt() {
gdt[3] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL3));
gdt[4] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL3));
for (uint32_t i = 0; i < sizeof(tss_entry); i++) {
for (uint32_t i = 0; i < sizeof(tss_entry_t); i++) {
((char*)&tss)[i] = 0;
}
tss.ss0 = 0x10;
tss.iomap_base = sizeof(tss_entry);
tss.iomap_base = sizeof(tss_entry_t);
gdt[5] = create_tss_descriptor((uint32_t)&tss, sizeof(tss_entry) - 1);
gdt[5] = create_tss_descriptor((uint32_t)&tss, sizeof(tss_entry_t) - 1);
gdtr.limit = 6 * sizeof(uint64_t) - 1;
gdtr.base = (uint32_t)&gdt;

View File

@@ -1,6 +1,40 @@
#ifndef KGDT_H
#define KGDT_H
#include <stdint.h>
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_t;
void init_gdt();
extern tss_entry_t tss;
#endif

View File

@@ -1,34 +0,0 @@
#include "initrd.h"
#include <stdint.h>
#include <lib/print.h>
#include <lib/memory.h>
void parse_cpio(void *initrd_start) {
cpio_header_t *head = (cpio_header_t *)initrd_start;
while (strncmp(head->c_magic, "070701", 6) == 0) {
// If we hit the trailer, we are done
char *filename = (char *)(head + 1);
if (strncmp(filename, "TRAILER!!!", 10) == 0) {
break;
}
uint32_t filesize = parse_hex(head->c_filesize);
uint32_t namesize = parse_hex(head->c_namesize);
kprintf("found file of size %d\n", filesize);
// Calculate where the data begins (accounting for 4-byte padding)
uint32_t header_plus_name = 110 + namesize;
header_plus_name = (header_plus_name + 3) & ~3; // Align to 4 bytes
char *file_data = (char *)head + header_plus_name;
uint32_t total_record_size = header_plus_name + filesize;
total_record_size = (total_record_size + 3) & ~3; // Align to 4 bytes
head = (cpio_header_t *)((char *)head + total_record_size);
}
}

View File

@@ -1,36 +0,0 @@
#ifndef KINITRD_H
#define KINITRD_H
#include <stdint.h>
typedef struct {
char c_magic[6];
char c_ino[8];
char c_mode[8];
char c_uid[8];
char c_gid[8];
char c_nlink[8];
char c_mtime[8];
char c_filesize[8];
char c_devmajor[8];
char c_devminor[8];
char c_rdevmajor[8];
char c_rdevminor[8];
char c_namesize[8];
char c_check[8];
} cpio_header_t;
static inline uint32_t parse_hex(const char *s) {
uint32_t val = 0;
for (int i = 0; i < 8; i++) {
val <<= 4;
if (s[i] >= '0' && s[i] <= '9') val += (s[i] - '0');
else if (s[i] >= 'A' && s[i] <= 'F') val += (s[i] - 'A' + 10);
else if (s[i] >= 'a' && s[i] <= 'f') val += (s[i] - 'a' + 10);
}
return val;
}
void parse_cpio(void *initrd_start);
#endif

View File

@@ -44,8 +44,16 @@ ISR_ERRCODE 14 # Page Fault (Has Error Code!)
.extern send_eoi_master # drivers/pic/pic.c
isr32:
cli
pushal
movw %ds, %ax
pushl %eax
movw $0x10, %ax # Load Kernel Data Segment descriptor
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
pushl %esp
call switch_context
@@ -53,6 +61,12 @@ isr32:
call send_eoi_master
popl %eax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
popal
sti
iret

View File

@@ -4,6 +4,7 @@
#include "scheduler.h"
#include "common.h"
#include "vfs.h"
#include "elf.h"
#include <lib/print.h>
#include <lib/stream.h>
@@ -51,26 +52,73 @@ vfs_node_t* load_initrd() {
return cpio_read_fs(initrd_module->mod_start);
}
void load_origin_program() {
vfs_node_t* vfs_root = vfs_create_root();
vfs_node_t* initrd_root = load_initrd();
if (initrd_root) {
mount(vfs_root, initrd_root);
kprintf("initrd read, mounted @ /\n");
void load_program(const char* path) {
void* cr3 = create_task_pd();
load_pd(cr3);
flush_tlb();
int fd = open("/origin.elf", 0);
if (fd == -1) {
kprintf("failed to read origin program\n");
}
void* buf = kalloc(512);
int rd = read(fd, buf, 512);
if (rd > 0) {
kprintf("read %d bytes from origin.elf\n", rd);
}
int fd = open(path, 0);
if (fd == -1) {
kprintf("failed to open program: %s\n", path);
return;;
}
exit();
elf_header_t* e_hdr = kalloc(sizeof(elf_header_t));
memset((void*)e_hdr, 0, sizeof(elf_header_t));
uint32_t bytes_rd = read(fd, e_hdr, sizeof(elf_header_t));
if (bytes_rd <= 0) {
kprintf("failed to read program data for %s\n", path);
return;
}
uint32_t ph_table_ptr = e_hdr->e_phoff;
elf_program_header_t* ph = kalloc(sizeof(elf_program_header_t));
uint32_t heap_start = 0;
for (uint32_t i = 0; i < e_hdr->e_phnum; i++) {
fseek(fd, ph_table_ptr);
memset((void*)ph, 0, sizeof(elf_program_header_t));
read(fd, ph, sizeof(elf_program_header_t));
if (ph->p_type == PT_LOAD) {
uint32_t vstart = ph->p_vaddr;
uint32_t vend = vstart + ph->p_memsz;
if (vend > heap_start) {
heap_start = vend;
}
uint32_t page_start = vstart & ~(PAGE_SIZE - 1);
uint32_t page_end = (vend + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
for (uint32_t v = page_start; v < page_end; v += PAGE_SIZE) {
void* phys_frame = p_alloc_frame();
map_page(v, (uint32_t)phys_frame, 0x07);
}
uint32_t data_ptr = ph->p_offset;
fseek(fd, data_ptr);
read(fd, (void*)vstart, ph->p_memsz);
// 0 out bss
if (ph->p_memsz > ph->p_filesz) {
size_t bss_size = ph->p_memsz - ph->p_filesz;
memset((void*)(vstart + ph->p_filesz), 0, bss_size);
}
}
ph_table_ptr += sizeof(elf_program_header_t);
}
uint32_t esp = 0xBFFF0000;
void* pesp = p_alloc_frame();
map_page(esp - PAGE_SIZE, (uint32_t)pesp, 0x07);
create_task(e_hdr->e_entry, fetch_cr3(), 1);
}
void start_origin() {
load_program("/origin.elf");
}
void kmain(uint32_t magic, multiboot_info* mbi) {
@@ -96,9 +144,19 @@ void kmain(uint32_t magic, multiboot_info* mbi) {
kprintf("basic initializations complete\n");
vfs_node_t* vfs_root = vfs_create_root();
vfs_node_t* initrd_root = load_initrd();
if (!initrd_root) {
kprintf("failed to load initrd\n");
}
mount(vfs_root, initrd_root);
kprintf("initrd read, mounted @ /\n");
disable_interrupts();
init_scheduler();
enable_interrupts();
create_task((uint32_t)load_origin_program, fetch_cr3());
kprintf("loading user program\n");
start_origin();
}

6
kernel/lib/string.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef KSTRING_H
#define KSTRING_H
char* strtok_r(char* str, const char* delim, char** saveptr);
#endif

49
kernel/lib/strtok.c Normal file
View File

@@ -0,0 +1,49 @@
#include <lib/string.h>
#include <stddef.h>
static int is_delim(char c, const char* delim) {
while (*delim) {
if (c == *delim) {
return 1;
}
delim++;
}
return 0;
}
char* strtok_r(char* str, const char* delim, char** saveptr) {
if (saveptr == NULL) {
return NULL;
}
char* next_token = (str != NULL) ? str : *saveptr;
if (next_token == NULL || *next_token == '\0') {
*saveptr = NULL;
return NULL;
}
while (*next_token && is_delim(*next_token, delim)) {
next_token++;
}
if (*next_token == '\0') {
*saveptr = next_token;
return NULL;
}
char* token_start = next_token;
while (*next_token) {
if (is_delim(*next_token, delim)) {
*next_token = '\0'; // Destructively null-terminate the token
*saveptr = next_token + 1; // Save the position right after the null-terminator
return token_start;
}
next_token++;
}
*saveptr = next_token;
return token_start;
}

View File

@@ -8,8 +8,6 @@ extern uint8_t __kernel_start;
extern uint8_t __kernel_end;
extern uint32_t page_directory[1024];
extern void flush_tlb();
extern void disable_pae();
#define PAGE_SIZE 4096
#define MAX_RAM 0xFFFFFFFF // 4GB

View File

@@ -24,4 +24,9 @@ void* create_task_pd();
void map_page(uint32_t vaddr, uint32_t paddr, uint32_t flags);
void load_pd(void* paddr);
void flush_tlb();
void disable_pae();
#endif

View File

@@ -13,6 +13,7 @@ typedef enum {
typedef struct {
uint32_t pid;
uint32_t esp;
uint32_t esp0;
uint32_t cr3;
process_state_t state;
uint32_t sleep;

View File

@@ -8,6 +8,7 @@
#include "common.h"
#include "process.h"
#include "scheduler.h"
#include "gdt.h"
static process_t* process_table;
@@ -68,9 +69,10 @@ uint32_t switch_context(uint32_t current_esp) {
current_process = next_process;
tss.esp0 = process_table[current_process].esp0;
if (fetch_cr3() != process_table[current_process].cr3) {
extern void load_pd(uint32_t table);
load_pd(process_table[current_process].cr3);
load_pd((void*)process_table[current_process].cr3);
}
return process_table[current_process].esp;
@@ -88,12 +90,12 @@ void init_scheduler() {
process->sleep = 0;
total_processes++;
create_task((uint32_t)idle_task, fetch_cr3());
create_task((uint32_t)idle_task, fetch_cr3(), 0);
current_process = 0;
}
int create_task(uint32_t entry_point, uint32_t cr3) {
int create_task(uint32_t entry_point, uint32_t cr3, int user) {
if (total_processes >= 16) {
return 0;
}
@@ -117,10 +119,20 @@ int create_task(uint32_t entry_point, uint32_t cr3) {
void* stack_bottom = kalloc(4096);
uint32_t* esp = (uint32_t*)((uint32_t)stack_bottom + 4096);
process->esp0 = (uint32_t)esp;
*(--esp) = 0x0202; // EFLAGS
*(--esp) = 0x08; // CS
*(--esp) = entry_point; // EIP
if (user) {
*(--esp) = 0x23; // User Data Segment (SS) with RPL 3 (0x20 | 3)
*(--esp) = 0xBFFFF000; // User Stack Pointer (ESP) - location mapped in user space
*(--esp) = 0x0202; // EFLAGS (Interrupts enabled)
*(--esp) = 0x1B; // User Code Segment (CS) with RPL 3 (0x18 | 3)
*(--esp) = entry_point; // EIP
} else {
// IRET values for Ring 0
*(--esp) = 0x0202; // EFLAGS
*(--esp) = 0x08; // Kernel Code Segment (CS)
*(--esp) = entry_point; // EIP
}
*(--esp) = 0; // EAX
*(--esp) = 0; // ECX

View File

@@ -6,7 +6,7 @@
void init_scheduler();
int create_task(uint32_t entry_point, uint32_t cr3);
int create_task(uint32_t entry_point, uint32_t cr3, int user);
process_t* current_task();
void sleep(uint32_t ms);

View File

@@ -22,22 +22,22 @@ vfs_node_t* vfs_create_root() {
void mount(vfs_node_t* _mnt, vfs_node_t* _fs) {
if (!_fs || !_mnt || !(_mnt->flags & VFS_DIRECTORY)) return;
_mnt->ptr = _fs;
_mnt->mnt = _fs;
}
static vfs_node_t* lookup(const char* path) {
if (path[0] != '/') return NULL;
vfs_node_t* current = root;
if (current->ptr) {
current = current->ptr;
if (current->mnt) {
current = current->mnt;
}
const char* component = path + 1;
if (*component == '\0') return current;
const char* cmp = path + 1;
if (*cmp == '\0') return current;
if (current->finddir) {
return current->finddir(current, component);
return current->finddir(current, cmp);
}
return NULL;
@@ -72,6 +72,22 @@ int read(int fd, void* buf, size_t sz) {
return bytes_read;
}
int fseek(int fd) {
}
int fstat(int fd, file_t* dst) {
if (fd < 0 || fd >= MAX_PROCESS_FDS || !fd_table[fd].node) {
return 0;
}
file_t* src = &fd_table[fd];
memcpy(src, dst, sizeof(file_t));
return 1;
}
int fseek(int fd, size_t offset) {
if (fd < 0 || fd >= MAX_PROCESS_FDS || !fd_table[fd].node) {
return 0;
}
file_t* file = &fd_table[fd];
file->offset = offset;
return 1;
}

View File

@@ -25,7 +25,8 @@ typedef struct vfs_node {
write_type_t write;
finddir_type_t finddir;
struct vfs_node* ptr;
struct vfs_node* mnt;
void* data;
} vfs_node_t;
typedef struct {
@@ -40,4 +41,7 @@ void mount(vfs_node_t* _mnt, vfs_node_t* _fs);
int open(const char* path, int flags);
int read(int fd, void* buf, size_t sz);
int fstat(int fd, file_t* _f);
int fseek(int fd, size_t offset);
#endif

View File

@@ -1,8 +1,8 @@
CC = i686-elf-gcc
LD = i686-elf-ld
CFLAGS = -ffreestanding -O2 -Wall -Wextra -I../rocklibc/include
LDFLAGS = -m elf_i386 -nostdlib
CFLAGS = -ffreestanding -O2 -Wall -Wextra -ffunction-sections -fdata-sections -I../rocklibc/include
LDFLAGS = -m elf_i386 -nostdlib --gc-sections
TARGET = origin.elf
@@ -16,6 +16,7 @@ main.o: main.c
$(TARGET): crt0.o main.o ../rocklibc/rlibc.a
$(LD) $(LDFLAGS) -T linker.ld crt0.o main.o ../rocklibc/rlibc.a $(shell $(CC) -print-libgcc-file-name) -o $(TARGET)
cp $(TARGET) ../initrd
clean:
rm -f *.o $(TARGET)

View File

@@ -1,6 +1,7 @@
CC = i686-elf-gcc
AR = i686-elf-ar
CFLAGS = -ffreestanding -O2 -Wall -Wextra -Iinclude -DHAVE_MMAP=0 -DLACKS_SYS_MMAN_H=1 -DUSE_LOCKS=0 -DLACKS_SYS_PARAM_H=1
CFLAGS += -ffunction-sections -fdata-sections
TARGET = rlibc.a
SRCS = $(shell find src -name "*.c")