From 4d98d73f5ea90a0a0b6e26340658457c0de2fc73 Mon Sep 17 00:00:00 2001 From: slinky55 Date: Wed, 8 Jul 2026 21:15:30 -0500 Subject: [PATCH] almost got the term emu working and shell --- build_programs.sh | 6 --- compile_commands.json | 17 ++++++++ kernel/elf.c | 65 ++++++++++++++++++++++++++++ kernel/elf.h | 2 + kernel/kmain.c | 65 +++------------------------- kernel/memory/mm.c | 4 ++ kernel/memory/mm.h | 1 + kernel/scheduler.c | 4 ++ kernel/syscall.c | 49 +++++++++++++++++++-- programs/compile_commands.json | 1 + programs/lib/rlibc.a | Bin 4156 -> 4408 bytes programs/rocksh/main.c | 39 ++--------------- programs/test/compile_commands.json | 36 --------------- programs/test/crt0.S | 21 --------- programs/test/linker.ld | 31 ------------- programs/test/main.c | 13 ------ programs/test/makefile | 23 ---------- programs/vga_text_term/main.c | 41 +++++++++++++++++- rocklibc/include/syscall.h | 8 ++++ rocklibc/src/syscall.c | 16 +++++++ 20 files changed, 214 insertions(+), 228 deletions(-) create mode 100644 kernel/elf.c create mode 100644 programs/compile_commands.json delete mode 100644 programs/test/compile_commands.json delete mode 100644 programs/test/crt0.S delete mode 100644 programs/test/linker.ld delete mode 100644 programs/test/main.c delete mode 100644 programs/test/makefile diff --git a/build_programs.sh b/build_programs.sh index de9c6d2..46d98e7 100755 --- a/build_programs.sh +++ b/build_programs.sh @@ -20,10 +20,4 @@ bear -- make cp vga_text_term.elf ../bin cd .. -cd test -make clean -bear -- make -cp test.elf ../bin -cd .. - cd .. \ No newline at end of file diff --git a/compile_commands.json b/compile_commands.json index f26fed2..cc99d35 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -254,6 +254,23 @@ "file": "/home/slinky/source/RockOS/kernel/interrupts.c", "output": "/home/slinky/source/RockOS/obj/kernel/interrupts.c.o" }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/elf.c.o", + "kernel/elf.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/elf.c", + "output": "/home/slinky/source/RockOS/obj/kernel/elf.c.o" + }, { "arguments": [ "/home/slinky/opt/cross/bin/i686-elf-gcc", diff --git a/kernel/elf.c b/kernel/elf.c new file mode 100644 index 0000000..a0496e2 --- /dev/null +++ b/kernel/elf.c @@ -0,0 +1,65 @@ +#include "elf.h" +#include "vfs.h" +#include "memory/mm.h" + +#include + +uint32_t load_elf_program(const char* prgm) { + int fd = open(prgm, 0); + if (fd == -1) { + return -1; + } + + 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) { + return -1; + } + + 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, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER); + } + + uint32_t data_ptr = ph->p_offset; + fseek(fd, data_ptr); + read(fd, (void*)vstart, ph->p_filesz); + + // 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 eip = e_hdr->e_entry; + kfree(ph); + kfree(e_hdr); + + return eip; +} diff --git a/kernel/elf.h b/kernel/elf.h index fea2a46..524354f 100644 --- a/kernel/elf.h +++ b/kernel/elf.h @@ -34,4 +34,6 @@ typedef struct { uint32_t p_align; } __attribute__((packed)) elf_program_header_t; +uint32_t load_elf_program(const char* prgm); + #endif \ No newline at end of file diff --git a/kernel/kmain.c b/kernel/kmain.c index b644477..f904f9e 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -64,65 +64,14 @@ void load_root_program(const char* path) { load_pd(cr3); flush_tlb(); - int fd = open(path, 0); - if (fd == -1) { - kprintf("failed to open program: %s\n", path); - return;; - } - 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, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER); - } - - uint32_t data_ptr = ph->p_offset; - fseek(fd, data_ptr); - read(fd, (void*)vstart, ph->p_filesz); - - // 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 eip = load_elf_program(path); uint32_t stack_sz = PAGE_SIZE * 16; uint32_t stack_top = 0xBFFF0000; uint32_t stack_bottom = stack_top - stack_sz; for (uint32_t vaddr = stack_bottom; vaddr < stack_top; vaddr += PAGE_SIZE) { - void* phys_frame = p_alloc_frame(); - map_page(vaddr, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER); + void* phys_frame = p_alloc_frame(); + map_page(vaddr, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER); } uint32_t* u_esp = (uint32_t*)stack_top; @@ -131,7 +80,7 @@ void load_root_program(const char* path) { *(--u_esp) = 0; // argc = 0 process_t* process = kalloc(sizeof(process_t)); - init_task(process, e_hdr->e_entry, (uint32_t)cr3, 1, (uint32_t)u_esp); + init_task(process, eip, (uint32_t)cr3, 1, (uint32_t)u_esp); add_task(process); unlock_scheduler(); @@ -164,8 +113,8 @@ 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"); } @@ -177,8 +126,8 @@ void kmain(uint32_t magic, multiboot_info* mbi) { init_scheduler(); enable_interrupts(); - kprintf("loading test program\n"); - load_root_program("/test.elf"); + kprintf("loading terminal program\n"); + load_root_program("/vga_text_term.elf"); kprintf("kernel going to sleep...\n"); } diff --git a/kernel/memory/mm.c b/kernel/memory/mm.c index 48c1ad8..973821b 100644 --- a/kernel/memory/mm.c +++ b/kernel/memory/mm.c @@ -267,4 +267,8 @@ void* clone_current_pd() { unmap_page(TEMP_TASKPD_VADDR); return (void*)task_pd_addr; +} + +void clear_current_pd() { + } \ No newline at end of file diff --git a/kernel/memory/mm.h b/kernel/memory/mm.h index 23aef4d..0877456 100644 --- a/kernel/memory/mm.h +++ b/kernel/memory/mm.h @@ -34,6 +34,7 @@ uint32_t total_free_memory(); void* create_new_pd(); void* clone_current_pd(); +void clear_current_pd(); int is_cow(uint32_t vaddr); diff --git a/kernel/scheduler.c b/kernel/scheduler.c index 8d0c312..287061e 100644 --- a/kernel/scheduler.c +++ b/kernel/scheduler.c @@ -99,6 +99,10 @@ void init_task ( process->flags = user ? PROCESS_FLAG_USER : PROCESS_FLAG_KERNEL; total_processes++; + if (process->kstack_top != 0) { + kfree((void*)process->kstack_top); + } + void* kstack_bottom = kalloc(PAGE_SIZE); uint32_t kstack_top = (uint32_t)kstack_bottom + PAGE_SIZE; process->kstack_top = kstack_top; diff --git a/kernel/syscall.c b/kernel/syscall.c index 80202f2..dffa0e9 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1,15 +1,18 @@ #include #include -#include #include "lib/memory.h" #include "lib/ringbuf.h" + #include "memory/mm.h" + #include "process.h" #include "scheduler.h" #include "vfs.h" +#include "elf.h" #include +#include #include #include @@ -53,11 +56,13 @@ static int32_t sys_read(int fd, void* buf, size_t count) { } static int32_t sys_open(const char* filename, int flags) { - return -1; + return open(filename, flags); } static int32_t sys_close(int fd) { - return -1; + process_t* task = current_task(); + task->fd_table[fd] = NULL; + return 1; } static int32_t sys_brk(uint32_t new_break) { @@ -155,6 +160,42 @@ static int32_t sys_fork(registers_t* parent_regs) { return child->pid; } +static int32_t sys_exec(registers_t* regs, const char* prgm) { + clear_current_pd(); + + uint32_t eip = load_elf_program(prgm); + + uint32_t stack_sz = PAGE_SIZE * 16; + uint32_t stack_top = 0xBFFF0000; + uint32_t stack_bottom = stack_top - stack_sz; + for (uint32_t vaddr = stack_bottom; vaddr < stack_top; vaddr += PAGE_SIZE) { + void* phys_frame = p_alloc_frame(); + map_page(vaddr, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER); + } + + uint32_t* u_esp = (uint32_t*)stack_top; + *(--u_esp) = 0; // envp = NULL + *(--u_esp) = 0; // argv = NULL + *(--u_esp) = 0; // argc = 0 + + regs->eax = 0; + regs->ecx = 0; + regs->edx = 0; + regs->ebp = 0; + regs->esi = 0; + regs->edi = 0; + regs->eip = eip; + regs->useresp = (uint32_t)u_esp; + + return 0; +} + +static int32_t sys_dup2(int src, int dst) { + process_t* task = current_task(); + task->fd_table[dst] = task->fd_table[src]; + return dst; +} + void syscall(registers_t* regs) { int32_t ret; switch(regs->eax) { @@ -166,6 +207,8 @@ void syscall(registers_t* regs) { case 12: ret = sys_brk(regs->ebx); break; case 20: ret = sys_pty((int*)regs->ebx); break; case 21: ret = sys_fork(regs); break; + case 22: ret = sys_exec(regs, (const char*)regs->ebx); break; + case 23: ret = sys_dup2(regs->ebx, regs->ecx); break; default: ret = -1; } regs->eax = ret; diff --git a/programs/compile_commands.json b/programs/compile_commands.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/programs/compile_commands.json @@ -0,0 +1 @@ +[] diff --git a/programs/lib/rlibc.a b/programs/lib/rlibc.a index eea302d36f6b1865751c2c84064adcd43bd603fd..e43cc2cc55d3a4fe9c47b93d5ba7743544dc2190 100644 GIT binary patch delta 569 zcmdm^utRBrY`vMWk%fhVf`I}EAd?CThUR8qQ3ZtrE(Qh$K_LEu9kZq|Fc89=F$@fx zF}bO^$pw`RKq@!CER`X5@;YW|o79TT5{CSO)I5grqRf(1hN9HO6o%xS{NhxGf|5#x zwEUuMhSZAGWQLT|0wackqRhOKG=}ullH`oUqKW6lSiyeS_$r%49_kxI0|TH};G~&} ziGqTqshPrL7Df%G8m7tfSPd9iC-bw(Pd>-$z{mz>@v#{Q>h*3>1NxAmcN>Td-5~~& z5flfq4KH;*4es{k>5k<%+c5bzljY#+po|a$BZDZAHUMHtC|?>#2O#kkfb0Sw zhN%ZxG69LN1!QjkVj(bQWY7oF7l0V1-UP`00K^hN46=`*xUx7oF=z5=HckyqxnUPg| Qasr1aB#bv#aU5a?0655aEC2ui delta 352 zcmdm?v`1lrthTACxtXbgf`I}EAd?CTh9(fcfMq&{ILvaaEAYCtCA8aYm zB6AC4Q;)HJFw#PCmqHFjZgDwDa` zwKye#?h;~PWDuKd%Pwv$4CToK=>jktBFj)*S)81hlcSf+kXn&h!hpq%lix5WO!j6G zWolxW9L1r;bckVc9ful-TE_yW&T*)*-T;|9nUPhQ)q|0NL1nTcr!rFx<77Wp@yW5A OB5-GmZ|>z>%? -#include #include +#include const char* shell_prompt = "rocksh> "; -static void process_cmd(const char* cmd) { - size_t cmd_len = strlen(cmd); - if (cmd_len < 1) { - return; - } - - if (strcmp(cmd, "exit") == 0) { - printf("bye!\n"); - exit(0); - } - - printf("command not recognized: %s\n", cmd); -} - int main(int argc, char *argv[]) { (void)argc; (void)argv; - char cmd[128]; - size_t p = 0; - - printf("%s", shell_prompt); + printf(shell_prompt); - while (1) { - char c = getchar(); - printf("%c", c); - if (c != '\n') { - cmd[p++] = c; - continue; - } - - cmd[p] = 0; - process_cmd(cmd); - memset(cmd, 0, 128); - p = 0; - printf("%s", shell_prompt); - } - - return 0; + return 3; } \ No newline at end of file diff --git a/programs/test/compile_commands.json b/programs/test/compile_commands.json deleted file mode 100644 index 63209b9..0000000 --- a/programs/test/compile_commands.json +++ /dev/null @@ -1,36 +0,0 @@ -[ - { - "arguments": [ - "/home/slinky/opt/cross/bin/i686-elf-gcc", - "-ffreestanding", - "-O2", - "-Wall", - "-Wextra", - "-I../../rocklibc/include", - "-c", - "-o", - "crt0.o", - "crt0.S" - ], - "directory": "/home/slinky/source/RockOS/programs/test", - "file": "/home/slinky/source/RockOS/programs/test/crt0.S", - "output": "/home/slinky/source/RockOS/programs/test/crt0.o" - }, - { - "arguments": [ - "/home/slinky/opt/cross/bin/i686-elf-gcc", - "-ffreestanding", - "-O2", - "-Wall", - "-Wextra", - "-I../../rocklibc/include", - "-c", - "-o", - "main.o", - "main.c" - ], - "directory": "/home/slinky/source/RockOS/programs/test", - "file": "/home/slinky/source/RockOS/programs/test/main.c", - "output": "/home/slinky/source/RockOS/programs/test/main.o" - } -] diff --git a/programs/test/crt0.S b/programs/test/crt0.S deleted file mode 100644 index d97f158..0000000 --- a/programs/test/crt0.S +++ /dev/null @@ -1,21 +0,0 @@ -.global _start -.extern exit -.section .text -_start: - xor %ebp, %ebp - - mov (%esp), %eax - lea 4(%esp), %ebx - lea 8(%esp,%eax,4), %ecx - - and $-16, %esp - - push %ecx - push %ebx - push %eax - - call main - - push %eax - call exit - diff --git a/programs/test/linker.ld b/programs/test/linker.ld deleted file mode 100644 index 03d6e3c..0000000 --- a/programs/test/linker.ld +++ /dev/null @@ -1,31 +0,0 @@ -ENTRY(_start) - -SECTIONS -{ - . = 0x40000000; - - .text ALIGN(4K) : - { - /* Force the crt0.o entry code to be placed FIRST in memory */ - KEEP(*crt0.o(.text)) - *(.text .text.*) - } - - .rodata ALIGN(4K) : - { - *(.rodata .rodata.*) - } - - .data ALIGN(4K) : - { - *(.data .data.*) - } - - .bss ALIGN(4K) : - { - _bss_start = .; - *(.bss .bss.*) - *(COMMON) - _bss_end = .; - } -} \ No newline at end of file diff --git a/programs/test/main.c b/programs/test/main.c deleted file mode 100644 index c9d12f6..0000000 --- a/programs/test/main.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "syscall.h" -#include - -int main(int argc, char *argv[]) { - (void)argc; - (void)argv; - - if (fork() == 0) { - return 1; - } - - return 0; -} \ No newline at end of file diff --git a/programs/test/makefile b/programs/test/makefile deleted file mode 100644 index cca7c29..0000000 --- a/programs/test/makefile +++ /dev/null @@ -1,23 +0,0 @@ -CC = i686-elf-gcc -LD = i686-elf-ld - -CFLAGS = -ffreestanding -O2 -Wall -Wextra -I../../rocklibc/include -LDFLAGS = -m elf_i386 -nostdlib - -TARGET = test.elf - -all: $(TARGET) - -crt0.o: crt0.S - $(CC) $(CFLAGS) -c crt0.S -o crt0.o - -main.o: main.c - $(CC) $(CFLAGS) -c main.c -o main.o - -$(TARGET): crt0.o main.o ../lib/rlibc.a - $(LD) $(LDFLAGS) -T linker.ld crt0.o main.o ../lib/rlibc.a -o $(TARGET) - -clean: - rm -f *.o $(TARGET) - -.PHONY: all clean test \ No newline at end of file diff --git a/programs/vga_text_term/main.c b/programs/vga_text_term/main.c index 5ef21ec..29917ac 100644 --- a/programs/vga_text_term/main.c +++ b/programs/vga_text_term/main.c @@ -1,5 +1,44 @@ -#include +#include + +void term(); + +int ptys; +int ptym; int main(int argc, char *argv[]) { + (void)argc; + (void)argv; + + ptym = pty(&ptys); + + if (fork() == 0) { + close(ptym); + dup2(ptys, 0); + dup2(0, 1); + dup2(0, 2); + + exec("/rocksh.elf"); + } + + close(ptys); + dup2(ptym, 0); + dup2(0, 1); + dup2(0, 2); + + term(); + return 0; +} + +void term() { + int vga_fd = open("/dev/tvga"); + if (vga_fd == -1) return; + + while (1) { + char c; + int rd = read(0, &c, 1); + if (rd > 0) { + write(vga_fd, &c, 1); + } + } } \ No newline at end of file diff --git a/rocklibc/include/syscall.h b/rocklibc/include/syscall.h index c7201d0..d03b89c 100644 --- a/rocklibc/include/syscall.h +++ b/rocklibc/include/syscall.h @@ -7,9 +7,14 @@ #define SYS_EXIT 1 #define SYS_READ 3 #define SYS_WRITE 4 +#define SYS_OPEN 5 +#define SYS_CLOSE 6 #define SYS_PTY 20 #define SYS_FORK 21 +#define SYS_EXEC 22 +#define SYS_DUP2 23 +int open(const char* path); int write(int fd, const void *buf, size_t count); int read(int fd, void *buf, size_t count); int close(int fd); @@ -22,6 +27,9 @@ void *sbrk(intptr_t increment); int brk(void *addr); int pty(int* slave); + int fork(); +int exec(const char* path); +int dup2(int src, int dst); #endif \ No newline at end of file diff --git a/rocklibc/src/syscall.c b/rocklibc/src/syscall.c index 1dc0da9..af9814c 100644 --- a/rocklibc/src/syscall.c +++ b/rocklibc/src/syscall.c @@ -27,6 +27,10 @@ void exit(int status) { while(1); } +int open(const char* path) { + return syscall1(SYS_OPEN, (uint32_t)path); +} + int write(int fd, const void* buf, size_t cnt) { return syscall3(SYS_WRITE, (uint32_t)fd, (uint32_t)buf, (uint32_t)cnt); } @@ -35,10 +39,22 @@ int read(int fd, void* buf, size_t cnt) { return syscall3(SYS_READ, (uint32_t)fd, (uint32_t)buf, (uint32_t)cnt); } +int close(int fd) { + return syscall1(SYS_CLOSE, fd); +} + int pty(int* slave) { return syscall1(SYS_PTY, (uint32_t)slave); } int fork() { return syscall1(SYS_FORK, 0); +} + +int exec(const char* path) { + return syscall1(SYS_EXEC, (uint32_t)path); +} + +int dup2(int src, int dst) { + return syscall3(SYS_DUP2, src, dst, 0); } \ No newline at end of file