From 6e1eb7768d06da9057129894443a72767dca0ed6 Mon Sep 17 00:00:00 2001 From: boreddevnl Date: Fri, 8 May 2026 21:05:33 +0200 Subject: [PATCH] core: update system boot logic for disk-based root and cmdline flags --- .gitignore | 3 ++ Makefile | 60 +++++++++++++++++++++--- src/core/main.c | 112 ++++++++++++++++++++++++++++++++++++--------- src/core/version.c | 4 +- src/mem/paging.c | 26 +++++++++++ src/mem/paging.h | 1 + src/sys/process.c | 10 ++-- 7 files changed, 181 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 8dba8fb..d3a6a1d 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ limine /build/ *.o disk.img +disk.qcow2 +.gitignore +disk.img diff --git a/Makefile b/Makefile index 5f5047a..318f1cb 100644 --- a/Makefile +++ b/Makefile @@ -202,8 +202,23 @@ $(BUILD_DIR)/initrd.tar: $(KERNEL_ELF) mkdir -p $(BUILD_DIR)/initrd/Library/images/icons/colloid mkdir -p $(BUILD_DIR)/initrd/Library/Fonts/Emoji mkdir -p $(BUILD_DIR)/initrd/Library/DOOM + mkdir -p $(BUILD_DIR)/initrd/Library/conf mkdir -p $(BUILD_DIR)/initrd/Library/bsh + mkdir -p $(BUILD_DIR)/initrd/Library/BWM/Wallpaper mkdir -p $(BUILD_DIR)/initrd/docs + mkdir -p $(BUILD_DIR)/initrd/boot + mkdir -p $(BUILD_DIR)/initrd/mnt + mkdir -p $(BUILD_DIR)/initrd/dev + mkdir -p $(BUILD_DIR)/initrd/root/Desktop + mkdir -p $(BUILD_DIR)/initrd/root/Pictures + mkdir -p $(BUILD_DIR)/initrd/root/Documents + mkdir -p $(BUILD_DIR)/initrd/root/Downloads + + @printf "$(YELLOW)[COPY]$(RESET) Limine binaries + kernel for installer..." + @if [ -f limine/BOOTX64.EFI ]; then cp limine/BOOTX64.EFI $(BUILD_DIR)/initrd/boot/; fi + @if [ -f limine/BOOTIA32.EFI ]; then cp limine/BOOTIA32.EFI $(BUILD_DIR)/initrd/boot/; fi + @if [ -f limine/limine-bios.sys ]; then cp limine/limine-bios.sys $(BUILD_DIR)/initrd/boot/; fi + @cp $(KERNEL_ELF) $(BUILD_DIR)/initrd/boot/boredos.elf @printf "$(YELLOW)[COPY]$(RESET) Userland binaries..." @for f in $(SRC_DIR)/userland/bin/*.elf; do \ @@ -331,30 +346,63 @@ clean: $(MAKE) -C $(SRC_DIR)/userland clean @printf "$(GREEN)[OK]$(RESET) Clean complete." -run-windows: $(ISO_IMAGE) +disk.qcow2: + $(call PRINT_STEP,CREATING 10GB EXPANDABLE DISK IMAGE) + qemu-img create -f qcow2 disk.qcow2 10G + +run-windows: $(ISO_IMAGE) disk.qcow2 $(call PRINT_STEP,RUNNING BOREDOS IN QEMU ON WINDOWS) qemu-system-x86_64 -m 4G -serial stdio -cdrom $< -boot d \ -smp 4 \ -audiodev dsound,id=audio0 -machine pcspk-audiodev=audio0 \ -vga std -global VGA.xres=1920 -global VGA.yres=1080 \ - -drive file=disk.img,format=raw,file.locking=off + -drive file=disk.qcow2,format=qcow2,file.locking=off -run-mac: $(ISO_IMAGE) +run-mac: $(ISO_IMAGE) disk.qcow2 $(call PRINT_STEP,RUNNING BOREDOS IN QEMU ON MACOS) qemu-system-x86_64 -m 4G -serial stdio -cdrom $< -boot d \ -smp 4 \ -audiodev coreaudio,id=audio0 -machine pcspk-audiodev=audio0 \ -vga std -global VGA.xres=1920 -global VGA.yres=1080 \ -display cocoa,show-cursor=off \ - -drive file=disk.img,format=raw,file.locking=off \ + -device ahci,id=ahci -drive file=disk.qcow2,format=qcow2,if=none,id=disk0 -device ide-hd,bus=ahci.0,drive=disk0 \ -cpu max -run-linux: $(ISO_IMAGE) +OVMF_CODE := /opt/homebrew/share/qemu/edk2-x86_64-code.fd +OVMF_VARS_TMPL := /opt/homebrew/share/qemu/edk2-i386-vars.fd +OVMF_VARS := edk2-vars.fd + +ifeq ($(shell test -f $(OVMF_CODE) && echo 1),) + OVMF_CODE := /usr/local/share/qemu/edk2-x86_64-code.fd + OVMF_VARS_TMPL := /usr/local/share/qemu/edk2-i386-vars.fd +endif + +$(OVMF_VARS): + @if [ -f $(OVMF_VARS_TMPL) ]; then \ + printf "$(YELLOW)[UEFI]$(RESET) Creating local NVRAM vars..."; \ + cp $(OVMF_VARS_TMPL) $(OVMF_VARS); \ + fi + +run-hd: disk.qcow2 $(OVMF_VARS) + $(call PRINT_STEP,BOOTING BOREDOS FROM HARD DRIVE) + qemu-system-x86_64 -m 4G -serial stdio -boot c \ + -smp 4 \ + -audiodev coreaudio,id=audio0 -machine pcspk-audiodev=audio0 \ + -vga std -global VGA.xres=1920 -global VGA.yres=1080 \ + -display cocoa,show-cursor=off \ + -drive if=pflash,format=raw,readonly=on,file=$(OVMF_CODE) \ + -drive if=pflash,format=raw,file=$(OVMF_VARS) \ + -device ahci,id=ahci \ + -drive file=disk.qcow2,format=qcow2,if=none,id=disk0 -device ide-hd,bus=ahci.0,drive=disk0 \ + -drive file=disk.img,format=raw,if=none,id=disk1 -device ide-hd,bus=ahci.1,drive=disk1 \ + -cpu max + +run-linux: $(ISO_IMAGE) disk.qcow2 $(call PRINT_STEP,RUNNING BOREDOS IN QEMU ON LINUX) qemu-system-x86_64 -m 4G -serial stdio -cdrom $< -boot d \ -smp 4 \ -audiodev pa,id=audio0 -machine pcspk-audiodev=audio0 \ -vga std -global VGA.xres=1920 -global VGA.yres=1080 \ -display gtk,show-cursor=off \ - -drive file=disk.img,format=raw,file.locking=off \ + -device ahci,id=ahci -drive file=disk.qcow2,format=qcow2,if=none,id=disk0 -device ide-hd,bus=ahci.0,drive=disk0 \ -cpu max diff --git a/src/core/main.c b/src/core/main.c index 122f2f4..87b2c87 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -235,6 +235,77 @@ static void fat32_mkdir_recursive(const char *path) { } } +static bool cmdline_has_flag(const char *cmdline, const char *flag) { + if (!cmdline || !flag || !flag[0]) return false; + int flag_len = (int)k_strlen(flag); + const char *p = cmdline; + while (*p) { + while (*p == ' ') p++; + if (!*p) break; + const char *start = p; + while (*p && *p != ' ') p++; + int len = (int)(p - start); + if (len == flag_len && k_strncmp(start, flag, (size_t)flag_len) == 0) return true; + } + return false; +} + +static bool cmdline_read_value(const char *cmdline, const char *key, char *out, int out_len) { + if (!cmdline || !key || !out || out_len <= 1) return false; + int key_len = (int)k_strlen(key); + const char *p = cmdline; + while (*p) { + while (*p == ' ') p++; + if (!*p) break; + if (k_strncmp(p, key, (size_t)key_len) == 0) { + const char *val = p + key_len; + int i = 0; + while (*val && *val != ' ' && i < out_len - 1) { + out[i++] = *val++; + } + out[i] = '\0'; + return i > 0; + } + while (*p && *p != ' ') p++; + } + return false; +} + +static void boot_parse_cmdline(const char *cmdline, uint32_t media_type) { + g_bootfs_state.boot_flags = 0; + g_bootfs_state.root_device[0] = '\0'; + + char root_arg[32]; + if (cmdline_read_value(cmdline, "root=", root_arg, (int)sizeof(root_arg))) { + const char *dev = root_arg; + if (dev[0] == '/' && dev[1] == 'd' && dev[2] == 'e' && dev[3] == 'v' && dev[4] == '/') { + dev += 5; + } + int i = 0; + while (dev[i] && i < (int)sizeof(g_bootfs_state.root_device) - 1) { + g_bootfs_state.root_device[i] = dev[i]; + i++; + } + g_bootfs_state.root_device[i] = '\0'; + if (i > 0) g_bootfs_state.boot_flags |= BOOT_FLAG_ROOT_SET; + } + + bool force_live = cmdline_has_flag(cmdline, "--live"); + bool force_disk = cmdline_has_flag(cmdline, "--disk"); + + if (force_live) { + g_bootfs_state.boot_flags |= BOOT_FLAG_LIVE | BOOT_FLAG_FORCED; + } else if (force_disk) { + g_bootfs_state.boot_flags |= BOOT_FLAG_DISK | BOOT_FLAG_FORCED; + } else if (g_bootfs_state.boot_flags & BOOT_FLAG_ROOT_SET) { + g_bootfs_state.boot_flags |= BOOT_FLAG_DISK; + } else if (media_type == LIMINE_MEDIA_TYPE_OPTICAL || media_type == LIMINE_MEDIA_TYPE_TFTP) { + g_bootfs_state.boot_flags |= BOOT_FLAG_LIVE; + } else { + g_bootfs_state.boot_flags |= BOOT_FLAG_DISK; + } +} + static bool usage_policy_prompt(void) { kconsole_set_active(true); serial_write("BoredOS - Please read the Usage Policy provided with this software before continuing.\n"); @@ -351,21 +422,6 @@ void kmain(void) { fat32_init(); log_ok("FAT32 ready"); - fat32_mkdir("/bin"); - fat32_mkdir("/Library"); - fat32_mkdir("/Library/images"); - fat32_mkdir("/Library/images/Wallpapers"); - fat32_mkdir("/Library/images/gif"); - fat32_mkdir("/Library/Fonts"); - fat32_mkdir("/Library/DOOM"); - fat32_mkdir("/Library/conf"); - fat32_mkdir("/Library/bsh"); - fat32_mkdir("/docs"); - fat32_mkdir("/root"); - fat32_mkdir("/root/Desktop"); - fat32_mkdir("/root/Pictures"); - fat32_mkdir("/root/Documents"); - fat32_mkdir("/root/Downloads"); sysfs_init_subsystems(); vfs_mount("/sys", "sysfs", "sysfs", sysfs_get_ops(), NULL); @@ -388,6 +444,14 @@ void kmain(void) { serial_write_hex(g_bootfs_state.kernel_size); serial_write(" bytes\n"); } + + if (kernel_file_request.response != NULL && kernel_file_request.response->kernel_file != NULL) { + const char *cmdline = kernel_file_request.response->kernel_file->cmdline; + uint32_t media_type = kernel_file_request.response->kernel_file->media_type; + boot_parse_cmdline(cmdline, media_type); + } else { + boot_parse_cmdline(NULL, LIMINE_MEDIA_TYPE_GENERIC); + } extern uint32_t wm_get_ticks(void); g_bootfs_state.boot_time_ms = wm_get_ticks(); @@ -415,6 +479,7 @@ void kmain(void) { if (path_len >= 5 && path[path_len-4] == '.' && path[path_len-3] == 't' && path[path_len-2] == 'a' && path[path_len-1] == 'r') { g_bootfs_state.initrd_size = mod->size; + g_bootfs_state.initrd_ptr = mod->address; serial_write("[INIT] -> Initrd detected\n"); } } @@ -488,7 +553,15 @@ void kmain(void) { smp_init(NULL); } - if (!usage_policy_prompt()) { + bool bypass_tos = false; + if (kernel_file_request.response != NULL && kernel_file_request.response->kernel_file != NULL) { + const char *cmdline = kernel_file_request.response->kernel_file->cmdline; + if (cmdline != NULL && k_strstr(cmdline, "--accept-tos") != NULL) { + bypass_tos = true; + } + } + + if (!bypass_tos && !usage_policy_prompt()) { log_fail("Usage policy not accepted, halting"); hcf(); } @@ -500,10 +573,5 @@ void kmain(void) { extern void bootfs_refresh_from_disk(void); bootfs_refresh_from_disk(); - while (1) { - wm_process_input(); - wm_process_deferred_thumbs(); - wallpaper_process_pending(); - asm("hlt"); - } + wm_run_loop(); } diff --git a/src/core/version.c b/src/core/version.c index f299ec6..e8aac65 100644 --- a/src/core/version.c +++ b/src/core/version.c @@ -13,10 +13,10 @@ void get_os_info(os_info_t *info) { for (size_t i = 0; i < sizeof(os_info_t); i++) p[i] = 0; const char *os_name = "BoredOS"; - const char *os_version = "26.5.1-stable"; + const char *os_version = "26.5.1-dev"; const char *os_codename = "Genesis"; const char *kernel_name = "Boredkernel"; - const char *kernel_version = "4.2.1-stable"; + const char *kernel_version = "4.2.1-dev"; const char *build_date = __DATE__; const char *build_time = __TIME__; const char *build_arch = "x86_64"; diff --git a/src/mem/paging.c b/src/mem/paging.c index 1394068..04d2858 100644 --- a/src/mem/paging.c +++ b/src/mem/paging.c @@ -155,3 +155,29 @@ void paging_destroy_user_pml4_phys(uint64_t pml4_phys) { extern void kfree(void* ptr); kfree((void*)pml4); } + +uint64_t paging_virt2phys(uint64_t pml4_phys, uint64_t virtual_addr) { + if (!pml4_phys) return 0; + + if (virtual_addr >= 0xFFFF800000000000ULL) { + return v2p(virtual_addr); + } + + page_table_t* pml4 = (page_table_t*)p2v(pml4_phys); + uint64_t pml4_index = (virtual_addr >> 39) & 0x1FF; + if (!(pml4->entries[pml4_index] & PT_PRESENT)) return 0; + + page_table_t* pdpt = (page_table_t*)p2v(pml4->entries[pml4_index] & PT_ADDR_MASK); + uint64_t pdpt_index = (virtual_addr >> 30) & 0x1FF; + if (!(pdpt->entries[pdpt_index] & PT_PRESENT)) return 0; + + page_table_t* pd = (page_table_t*)p2v(pdpt->entries[pdpt_index] & PT_ADDR_MASK); + uint64_t pd_index = (virtual_addr >> 21) & 0x1FF; + if (!(pd->entries[pd_index] & PT_PRESENT)) return 0; + + page_table_t* pt = (page_table_t*)p2v(pd->entries[pd_index] & PT_ADDR_MASK); + uint64_t pt_index = (virtual_addr >> 12) & 0x1FF; + if (!(pt->entries[pt_index] & PT_PRESENT)) return 0; + + return (pt->entries[pt_index] & PT_ADDR_MASK) | (virtual_addr & 0xFFF); +} diff --git a/src/mem/paging.h b/src/mem/paging.h index be2ff1d..4b34a34 100644 --- a/src/mem/paging.h +++ b/src/mem/paging.h @@ -38,5 +38,6 @@ void paging_switch_directory(uint64_t pml4_phys); void paging_destroy_user_pml4_phys(uint64_t pml4_phys); void paging_init(void); +uint64_t paging_virt2phys(uint64_t pml4_phys, uint64_t virtual_addr); #endif // PAGING_H diff --git a/src/sys/process.c b/src/sys/process.c index 9791065..68641b9 100644 --- a/src/sys/process.c +++ b/src/sys/process.c @@ -161,13 +161,13 @@ process_t* process_create(void (*entry_point)(void), bool is_user) { return NULL; } - // 2. Allocate aligned stack - void* user_stack = kmalloc_aligned(4096, 4096); + void* user_stack = kmalloc_aligned(131072, 4096); void* kernel_stack = kmalloc_aligned(32768, 32768); // Needed for when user interrupts to Ring 0 if (is_user) { - // Map user stack to 0x800000 - paging_map_page(new_proc->pml4_phys, 0x800000, v2p((uint64_t)user_stack), PT_PRESENT | PT_RW | PT_USER); + for (int i = 0; i < 32; i++) { + paging_map_page(new_proc->pml4_phys, 0x800000 + i*4096, v2p((uint64_t)user_stack + i*4096), PT_PRESENT | PT_RW | PT_USER); + } // Allocate code page aligned and copy code void* code = kmalloc_aligned(4096, 4096); @@ -180,7 +180,7 @@ process_t* process_create(void (*entry_point)(void), bool is_user) { uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 32768); *(--stack_ptr) = 0x1B; // SS (User Data) - *(--stack_ptr) = 0x800000 + 4096; // RSP + *(--stack_ptr) = 0x800000 + 131072; // RSP *(--stack_ptr) = 0x202; // RFLAGS (IF=1) *(--stack_ptr) = 0x23; // CS (User Code) *(--stack_ptr) = 0x400000; // RIP