diff --git a/CONTRIBUTING.MD b/CONTRIBUTING.MD index e6ff9ee..4b8e29d 100644 --- a/CONTRIBUTING.MD +++ b/CONTRIBUTING.MD @@ -3,3 +3,7 @@ Do you want to improve Soaplin? You can by contributing to the project! ## Contributing guidelines * Before making a commit, please run `make format`. This will run clang-format over all the C source files in kernel/src. +* Large language model-generated code is **allowed**, with the condition that you do extensive testing over that code. + You must also know how to make the LLM-generated code by yourself. + + Note: Even if LLM-generated code is allowed, please try to not use it. \ No newline at end of file diff --git a/GNUmakefile b/GNUmakefile index d3896ee..6ff16cd 100755 --- a/GNUmakefile +++ b/GNUmakefile @@ -83,7 +83,6 @@ run-aarch64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).iso .PHONY: run-hdd-aarch64 run-hdd-aarch64: ovmf/ovmf-code-$(ARCH).fd $(IMAGE_NAME).hdd - @echo " Starting QEMU with $(IMAGE_NAME).hdd" @qemu-system-$(ARCH) \ -M virt \ -cpu cortex-a72 \ @@ -204,8 +203,8 @@ $(IMAGE_NAME).iso: limine/limine kernel @mkdir -p iso_root/boot/limine @cp -v limine.conf iso_root/boot/limine/ @mkdir -p iso_root/EFI/BOOT + @cp -v initramfs.tar iso_root/ ifeq ($(ARCH),x86_64) - @cp -v testing/sk-hello.elf iso_root/ @cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/ @cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/ @cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT/ diff --git a/initramfs.tar b/initramfs.tar new file mode 100644 index 0000000..d5c2b82 Binary files /dev/null and b/initramfs.tar differ diff --git a/initramfs/dir/subtest.txt b/initramfs/dir/subtest.txt new file mode 100644 index 0000000..0688709 --- /dev/null +++ b/initramfs/dir/subtest.txt @@ -0,0 +1 @@ +Hello World from a subdirectory! \ No newline at end of file diff --git a/initramfs/test.txt b/initramfs/test.txt new file mode 100644 index 0000000..c57eff5 --- /dev/null +++ b/initramfs/test.txt @@ -0,0 +1 @@ +Hello World! \ No newline at end of file diff --git a/kernel/src/fs/vfs.c b/kernel/src/fs/vfs.c deleted file mode 100644 index e69de29..0000000 diff --git a/kernel/src/fs/vfs.h b/kernel/src/fs/vfs.h deleted file mode 100644 index bbaa364..0000000 --- a/kernel/src/fs/vfs.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -// btw fuck sun - -#include - -#define VNODE_TYPE_FILE 0 -#define VNODE_TYPE_DIR 1 -#define VNODE_TYPE_DEV 2 - -typedef struct __vnode { - char name[128]; - int type; - - struct __vnode *children; - struct __vnode *next; - struct __vnode *parent; - - void (*write)(void *buffer, uint64_t off, uint64_t size); - void (*read)(void *buffer, uint64_t off, uint64_t size); -} vnode; - -typedef struct __vfs_mount { - struct vfs_node - *mount_point; // The directory in the main VFS where this is mounted - struct vfs_node *mounted_root; // The root node of the mounted filesystem - struct vfs_mount *next; // Pointer to next mount point -} vfs_mount; diff --git a/kernel/src/lib/string.c b/kernel/src/lib/string.c new file mode 100644 index 0000000..216e6dd --- /dev/null +++ b/kernel/src/lib/string.c @@ -0,0 +1,57 @@ +#include +#include + +int strlen(const char *str) { + int len = 0; + while (str[len]) + len++; + return len; +} + +int strcmp(const char *s1, const char *s2) { + while (*s1 && *s1 == *s2) { + s1++; + s2++; + } + return *s1 - *s2; +} + +char *strcpy(char *dest, const char *src) +{ + if (dest == NULL || src == NULL) + return NULL; + + char *temp = dest; + while((*dest++ = *src++) != '\0'); + return temp; +} + +char *strchr(const char *s, int c) { + while (*s++) { + if (*s == c) + return (char *)s; + } + return NULL; +} + +char *strrchr(const char *s, int c) { + const char *p = NULL; + + for (;;) { + if (*s == (char)c) + p = s; + if (*s++ == '\0') + return (char *)p; + } +} + +int oct2bin(unsigned char *str, int size) { + int n = 0; + unsigned char *c = str; + while (size-- > 0) { + n *= 8; + n += *c - '0'; + c++; + } + return n; +} \ No newline at end of file diff --git a/kernel/src/lib/string.h b/kernel/src/lib/string.h new file mode 100644 index 0000000..da1cdd6 --- /dev/null +++ b/kernel/src/lib/string.h @@ -0,0 +1,8 @@ +#pragma once + +int strlen(const char *str); +int strcmp(const char *s1, const char *s2); +char *strchr(const char *s, int c); +char *strcpy(char *dest, const char *src); +char *strrchr(const char *s, int c); +int oct2bin(unsigned char *str, int size); \ No newline at end of file diff --git a/kernel/src/main.c b/kernel/src/main.c index 9c27252..fd9b080 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -1,5 +1,7 @@ #include "exec/elf.h" #include "exec/exec.h" +#include "fs/tapefs.h" +#include "fs/vfs.h" #include "mm/liballoc/liballoc.h" #include "mm/pmm.h" #include "mm/vma.h" @@ -11,29 +13,22 @@ #include "sys/syscall.h" #include #include +#include #include #include #include #include #include #include +#include #include #include #include #include -// Set the base revision to 3, this is recommended as this is the latest -// base revision described by the Limine boot protocol specification. -// See specification for further info. - __attribute__(( used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3); -// The Limine requests can be placed anywhere, but it is important that -// the compiler does not optimise them away, so, usually, they should -// be made volatile or equivalent, _and_ they should be accessed at least -// once or marked as used with the "used" attribute as done here. - __attribute__(( used, section( @@ -45,14 +40,6 @@ __attribute__(( section(".limine_requests"))) static volatile struct limine_module_request module_request = {.id = LIMINE_MODULE_REQUEST, .revision = 0}; -/*__attribute__((used, section(".limine_requests"))) -static volatile struct limine_entry_point_request entrypoint_request = { - .id = LIMINE_ENTRY_POINT_REQUEST, - .revision = 3 -};*/ -// Finally, define the start and end markers for the Limine requests. -// These can also be moved anywhere, to any .c file, as seen fit. - __attribute__((used, section(".limine_requests_" "start"))) static volatile LIMINE_REQUESTS_START_MARKER; @@ -62,38 +49,14 @@ __attribute__(( section( ".limine_requests_end"))) static volatile LIMINE_REQUESTS_END_MARKER; -// Halt and catch fire function. -static void hcf(void) { - for (;;) { -#if defined(__x86_64__) - asm("hlt"); -#elif defined(__aarch64__) || defined(__riscv) - asm("wfi"); -#elif defined(__loongarch64) - asm("idle 0"); -#endif - } -} - struct limine_framebuffer *fb; struct flanterm_context *ft_ctx; -uint32_t fg = 0xFFFFFF; char kstack[8192]; -// The following will be our kernel's entry point. -// If renaming kmain() to something else, make sure to change the -// linker script accordingly. void kmain(void) { - // Ensure the bootloader actually understands our base revision (see spec). - /*if (LIMINE_BASE_REVISION_SUPPORTED == false) { - hcf(); - }*/ - - // Ensure we got a framebuffer. if (framebuffer_request.response != NULL) { - // Fetch the first framebuffer. struct limine_framebuffer *framebuffer = framebuffer_request.response->framebuffers[0]; fb = framebuffer; @@ -103,12 +66,11 @@ void kmain(void) { framebuffer->height, framebuffer->pitch, framebuffer->red_mask_size, framebuffer->red_mask_shift, framebuffer->green_mask_size, framebuffer->green_mask_shift, framebuffer->blue_mask_size, - framebuffer->blue_mask_shift, NULL, NULL, NULL, NULL, &fg, NULL, NULL, + framebuffer->blue_mask_shift, NULL, NULL, NULL, NULL, NULL, NULL, NULL, VGA8, 8, 16, 0, 0, 0, 0); } printf("\n Soaplin 1.0-sild is booting up your computer...\n\n"); - // printf("Physical kernel EP: %p", entrypoint_request.entry); gdt_init(&kstack[8192]); idt_init(); @@ -125,21 +87,13 @@ void kmain(void) { asm("hlt"); } - // acpi_init(); syscall_init(); pit_init(1000); sched_init(); - // user_init(); - - struct limine_file *f = module_request.response->modules[0]; - log("kmain - %s\n", f->path); - - program_t *prog = elf_load((char *)f->address, 1); - - sched_create("Init", prog->entry, prog->pm, SCHED_USER_PROCESS); log("kernel - Soaplin initialized sucessfully.\n"); + while (1) ; - ; //__asm__ volatile ("hlt"); + ; } diff --git a/kernel/src/mm/vmm.c b/kernel/src/mm/vmm.c index e2a183f..cc246f0 100644 --- a/kernel/src/mm/vmm.c +++ b/kernel/src/mm/vmm.c @@ -211,8 +211,8 @@ void vmm_map_user(pagemap_t *pm, uint64_t vaddr, uint64_t paddr, uint64_t pml2_entry = (vaddr >> 21) & 0x1ff; uint64_t pml1_entry = (vaddr >> 12) & 0x1ff; - - uint64_t *pml3 = __vmm_get_next_lvl(pm->toplevel, pml4_entry, flags | VMM_WRITABLE, + uint64_t *pml3 = + __vmm_get_next_lvl(pm->toplevel, pml4_entry, flags | VMM_WRITABLE, true); // PML3 / Page Directory Pointer Entry uint64_t *pml2 = __vmm_get_next_lvl(pml3, pml3_entry, flags | VMM_WRITABLE, true); // PML2 / Page Directory Entry diff --git a/kernel/src/sched/sched.c b/kernel/src/sched/sched.c index 907f83a..f16f6b6 100644 --- a/kernel/src/sched/sched.c +++ b/kernel/src/sched/sched.c @@ -4,6 +4,7 @@ #include "mm/vmm.h" #include "sys/arch/x86_64/idt.h" #include "sys/log.h" +#include #include sched_process *proc_list; @@ -47,16 +48,11 @@ void sched_init() { sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t *pm, uint32_t flags) { - // TODO: implement a separate strlen function - // as there's like 4 strlen impls in the kernel. - int i = 0; - while (name[i] != 0) - i++; sched_process *proc = pmm_request_page(); memset(proc, 0, sizeof(sched_process)); - memcpy(proc->name, name, i); + memcpy(proc->name, name, strlen(name) > 128 ? 128 : strlen(name)); proc->pid = current_pid; proc->type = SCHED_RUNNING; proc->flags = flags; @@ -141,7 +137,6 @@ void schedule(registers_t *regs) { prev_proc->next = curr_proc->next; - // Now, it is safe to free the process's memory. vmm_release_pm(curr_proc->pm); pmm_free_page(curr_proc->stack_base_physical); @@ -155,15 +150,7 @@ void schedule(registers_t *regs) { if (curr_proc == NULL) curr_proc = proc_list; - //log("sched - I choosed process %d\n", curr_proc->pid); - - //log("sched - I choosed process %d (pm: %s, rip: %p)\n", curr_proc->pid, curr_proc->pm == vmm_kernel_pm ? "kernel" : "user", curr_proc->regs.rip); memcpy(regs, &curr_proc->regs, sizeof(registers_t)); - // Finally, load our pagemap - // if (memcmp(curr_proc->name, "Init", 4)== 0) { vmm_load_pagemap(curr_proc->pm); - // asm("cli"); - // while (1) - // asm("hlt");} } \ No newline at end of file diff --git a/kernel/src/sys/arch/x86_64/interrupts.c b/kernel/src/sys/arch/x86_64/interrupts.c index 8e3643c..41c4621 100644 --- a/kernel/src/sys/arch/x86_64/interrupts.c +++ b/kernel/src/sys/arch/x86_64/interrupts.c @@ -1,5 +1,3 @@ -// #include "mm/pmm.h" -// #include "mm/vmm.h" #include "mm/pmm.h" #include "mm/vmm.h" #include "sched/sched.h" @@ -7,39 +5,20 @@ #include "sys/arch/x86_64/rtc.h" #include "sys/log.h" #include "sys/syscall.h" -// #include "sys/sched.h" #include #include #include -// #include int pit_millis = 0; int pit_secs = 0; extern int vmm_kernel_pm_exists; -struct Idt_StackFrame { - struct Idt_StackFrame *rbp; - uint64_t rip; -} __attribute__((packed)); - -void dump_backtrace(registers_t *r) { - log("ints - backtrace : \n"); - struct Idt_StackFrame *frame = (struct Idt_StackFrame *)r->rbp; - - while (frame) { - log("ints - %s (ip: %p)\n", frame->rip); - frame = frame->rbp; - } - log("ints - \n"); -} - void pit_handler(registers_t *regs); void exception_handler(registers_t *regs) { vmm_load_pagemap(vmm_kernel_pm); if (regs->int_no < 32) { - // panic(kmode_cpu_exception, regs); log("ints - %d (RIP: %p, ERR: %d)\n", regs->int_no, regs->rip, regs->err_code); @@ -53,7 +32,6 @@ void exception_handler(registers_t *regs) { log("ints - PF: Faulting page map: %p\n", PHYSICAL(vmm_current_pm)); } - // dump_backtrace(regs); asm("cli"); while (1) asm("hlt"); @@ -73,7 +51,6 @@ void exception_handler(registers_t *regs) { } else if (regs->int_no == 0x80) { syscall_handle(regs); } - // logln(info, "arch/ints", "Received interrupt %d\n", regs->int_no); - //vmm_load_pagemap(curr_proc->pm); + pic_ack(regs->int_no - 32); } \ No newline at end of file diff --git a/kernel/src/sys/error_handling/panic.c b/kernel/src/sys/error_handling/panic.c index c867ff3..f9ee767 100644 --- a/kernel/src/sys/error_handling/panic.c +++ b/kernel/src/sys/error_handling/panic.c @@ -1 +1,75 @@ -void panic_ctx() {} \ No newline at end of file +#include "sys/arch/x86_64/idt.h" +#include + +static registers_t __panic_regdump; + +static void __panic_dump_regs() { + asm volatile( + // Save general purpose registers + "movq %%r15, %0\n\t" + "movq %%r14, %1\n\t" + "movq %%r13, %2\n\t" + "movq %%r12, %3\n\t" + "movq %%r11, %4\n\t" + "movq %%r10, %5\n\t" + "movq %%r9, %6\n\t" + "movq %%r8, %7\n\t" + "movq %%rdi, %8\n\t" + "movq %%rsi, %9\n\t" + "movq %%rbp, %10\n\t" + "movq %%rbx, %11\n\t" + "movq %%rdx, %12\n\t" + "movq %%rcx, %13\n\t" + "movq %%rax, %14\n\t" + + // The rest of the registers (rip, cs, rflags, rsp, ss) would typically + // be captured in the interrupt/exception handler context and passed in + // We'll zero them out here since we don't have direct access + : "=m"(__panic_regdump.r15), "=m"(__panic_regdump.r14), + "=m"(__panic_regdump.r13), "=m"(__panic_regdump.r12), + "=m"(__panic_regdump.r11), "=m"(__panic_regdump.r10), + "=m"(__panic_regdump.r9), "=m"(__panic_regdump.r8), + "=m"(__panic_regdump.rdi), "=m"(__panic_regdump.rsi), + "=m"(__panic_regdump.rbp), "=m"(__panic_regdump.rbx), + "=m"(__panic_regdump.rdx), "=m"(__panic_regdump.rcx), + "=m"(__panic_regdump.rax) + : + : "memory"); + + // Zero out the registers we can't directly access in this context + __panic_regdump.int_no = 0; + __panic_regdump.err_code = 0; + __panic_regdump.rip = 0; + __panic_regdump.cs = 0; + __panic_regdump.rflags = 0; + __panic_regdump.rsp = 0; + __panic_regdump.ss = 0; +} + +void panic() { + __panic_dump_regs(); + + log(" _ __ _ ___ _ \n"); + log("| |/ /___ _ _ _ _ ___| | | _ \\__ _ _ _ (_)__ \n"); + log("| ' +#include #include #include @@ -14,12 +15,8 @@ void log(char *format, ...) { // TODO: replace this call with a call to printf() when the RTC is // implemented. char *date = "1970-01-01 00:00:00 | "; - int i2 = 0; - for (i2; date[i2] != 0; i2++) - ; - ; if (ft_ctx) - flanterm_write(ft_ctx, date, i2); + flanterm_write(ft_ctx, date, strlen(date)); char buf[2048]; va_list l; @@ -27,14 +24,10 @@ void log(char *format, ...) { npf_vsnprintf(buf, 2048, format, l); va_end(l); - int i = 0; - for (i; buf[i] != 0; i++) - ; - ; if (ft_ctx) - flanterm_write(ft_ctx, buf, i); + flanterm_write(ft_ctx, buf, strlen(buf)); - for (int i = 0;; i++) { + /*for (int i = 0;; i++) { if (date[i] == '\0') break; @@ -46,7 +39,7 @@ void log(char *format, ...) { break; outb(0xE9, buf[i]); - } + }*/ // spinlock_release(&log_lock); } \ No newline at end of file diff --git a/kernel/src/sys/printf.c b/kernel/src/sys/printf.c index 9097ac6..b453bcf 100644 --- a/kernel/src/sys/printf.c +++ b/kernel/src/sys/printf.c @@ -2,6 +2,7 @@ // This code is part of the Soaplin kernel and is licensed under the terms of // the MIT License. #include "sys/gfx/flanterm/flanterm.h" +#include #include #define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1 @@ -25,11 +26,6 @@ void printf(char *format, ...) { va_end(lst); // rt_print(buf); - int i = 0; - for (i; buf[i] != 0; i++) - ; - ; - if (ft_ctx) - flanterm_write(ft_ctx, buf, i); + flanterm_write(ft_ctx, buf, strlen(buf)); } \ No newline at end of file diff --git a/limine.conf b/limine.conf index df98d06..fd0bd86 100755 --- a/limine.conf +++ b/limine.conf @@ -6,4 +6,4 @@ verbose: yes protocol: limine path: boot():/boot/soaplin - module_path: boot():/sk-hello.elf \ No newline at end of file + module_path: boot():/initramfs.tar \ No newline at end of file