core: update system boot logic for disk-based root and cmdline flags

This commit is contained in:
boreddevnl 2026-05-08 21:05:33 +02:00
parent 0fbc3a5fc8
commit 6e1eb7768d
7 changed files with 181 additions and 35 deletions

3
.gitignore vendored
View file

@ -31,3 +31,6 @@ limine
/build/ /build/
*.o *.o
disk.img disk.img
disk.qcow2
.gitignore
disk.img

View file

@ -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/images/icons/colloid
mkdir -p $(BUILD_DIR)/initrd/Library/Fonts/Emoji mkdir -p $(BUILD_DIR)/initrd/Library/Fonts/Emoji
mkdir -p $(BUILD_DIR)/initrd/Library/DOOM 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/bsh
mkdir -p $(BUILD_DIR)/initrd/Library/BWM/Wallpaper
mkdir -p $(BUILD_DIR)/initrd/docs 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..." @printf "$(YELLOW)[COPY]$(RESET) Userland binaries..."
@for f in $(SRC_DIR)/userland/bin/*.elf; do \ @for f in $(SRC_DIR)/userland/bin/*.elf; do \
@ -331,30 +346,63 @@ clean:
$(MAKE) -C $(SRC_DIR)/userland clean $(MAKE) -C $(SRC_DIR)/userland clean
@printf "$(GREEN)[OK]$(RESET) Clean complete." @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) $(call PRINT_STEP,RUNNING BOREDOS IN QEMU ON WINDOWS)
qemu-system-x86_64 -m 4G -serial stdio -cdrom $< -boot d \ qemu-system-x86_64 -m 4G -serial stdio -cdrom $< -boot d \
-smp 4 \ -smp 4 \
-audiodev dsound,id=audio0 -machine pcspk-audiodev=audio0 \ -audiodev dsound,id=audio0 -machine pcspk-audiodev=audio0 \
-vga std -global VGA.xres=1920 -global VGA.yres=1080 \ -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) $(call PRINT_STEP,RUNNING BOREDOS IN QEMU ON MACOS)
qemu-system-x86_64 -m 4G -serial stdio -cdrom $< -boot d \ qemu-system-x86_64 -m 4G -serial stdio -cdrom $< -boot d \
-smp 4 \ -smp 4 \
-audiodev coreaudio,id=audio0 -machine pcspk-audiodev=audio0 \ -audiodev coreaudio,id=audio0 -machine pcspk-audiodev=audio0 \
-vga std -global VGA.xres=1920 -global VGA.yres=1080 \ -vga std -global VGA.xres=1920 -global VGA.yres=1080 \
-display cocoa,show-cursor=off \ -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 -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) $(call PRINT_STEP,RUNNING BOREDOS IN QEMU ON LINUX)
qemu-system-x86_64 -m 4G -serial stdio -cdrom $< -boot d \ qemu-system-x86_64 -m 4G -serial stdio -cdrom $< -boot d \
-smp 4 \ -smp 4 \
-audiodev pa,id=audio0 -machine pcspk-audiodev=audio0 \ -audiodev pa,id=audio0 -machine pcspk-audiodev=audio0 \
-vga std -global VGA.xres=1920 -global VGA.yres=1080 \ -vga std -global VGA.xres=1920 -global VGA.yres=1080 \
-display gtk,show-cursor=off \ -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 -cpu max

View file

@ -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) { static bool usage_policy_prompt(void) {
kconsole_set_active(true); kconsole_set_active(true);
serial_write("BoredOS - Please read the Usage Policy provided with this software before continuing.\n"); serial_write("BoredOS - Please read the Usage Policy provided with this software before continuing.\n");
@ -351,21 +422,6 @@ void kmain(void) {
fat32_init(); fat32_init();
log_ok("FAT32 ready"); 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(); sysfs_init_subsystems();
vfs_mount("/sys", "sysfs", "sysfs", sysfs_get_ops(), NULL); vfs_mount("/sys", "sysfs", "sysfs", sysfs_get_ops(), NULL);
@ -389,6 +445,14 @@ void kmain(void) {
serial_write(" bytes\n"); 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); extern uint32_t wm_get_ticks(void);
g_bootfs_state.boot_time_ms = wm_get_ticks(); 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' && if (path_len >= 5 && path[path_len-4] == '.' && path[path_len-3] == 't' &&
path[path_len-2] == 'a' && path[path_len-1] == 'r') { path[path_len-2] == 'a' && path[path_len-1] == 'r') {
g_bootfs_state.initrd_size = mod->size; g_bootfs_state.initrd_size = mod->size;
g_bootfs_state.initrd_ptr = mod->address;
serial_write("[INIT] -> Initrd detected\n"); serial_write("[INIT] -> Initrd detected\n");
} }
} }
@ -488,7 +553,15 @@ void kmain(void) {
smp_init(NULL); 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"); log_fail("Usage policy not accepted, halting");
hcf(); hcf();
} }
@ -500,10 +573,5 @@ void kmain(void) {
extern void bootfs_refresh_from_disk(void); extern void bootfs_refresh_from_disk(void);
bootfs_refresh_from_disk(); bootfs_refresh_from_disk();
while (1) { wm_run_loop();
wm_process_input();
wm_process_deferred_thumbs();
wallpaper_process_pending();
asm("hlt");
}
} }

View file

@ -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; for (size_t i = 0; i < sizeof(os_info_t); i++) p[i] = 0;
const char *os_name = "BoredOS"; 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 *os_codename = "Genesis";
const char *kernel_name = "Boredkernel"; 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_date = __DATE__;
const char *build_time = __TIME__; const char *build_time = __TIME__;
const char *build_arch = "x86_64"; const char *build_arch = "x86_64";

View file

@ -155,3 +155,29 @@ void paging_destroy_user_pml4_phys(uint64_t pml4_phys) {
extern void kfree(void* ptr); extern void kfree(void* ptr);
kfree((void*)pml4); 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);
}

View file

@ -38,5 +38,6 @@ void paging_switch_directory(uint64_t pml4_phys);
void paging_destroy_user_pml4_phys(uint64_t pml4_phys); void paging_destroy_user_pml4_phys(uint64_t pml4_phys);
void paging_init(void); void paging_init(void);
uint64_t paging_virt2phys(uint64_t pml4_phys, uint64_t virtual_addr);
#endif // PAGING_H #endif // PAGING_H

View file

@ -161,13 +161,13 @@ process_t* process_create(void (*entry_point)(void), bool is_user) {
return NULL; return NULL;
} }
// 2. Allocate aligned stack void* user_stack = kmalloc_aligned(131072, 4096);
void* user_stack = kmalloc_aligned(4096, 4096);
void* kernel_stack = kmalloc_aligned(32768, 32768); // Needed for when user interrupts to Ring 0 void* kernel_stack = kmalloc_aligned(32768, 32768); // Needed for when user interrupts to Ring 0
if (is_user) { if (is_user) {
// Map user stack to 0x800000 for (int i = 0; i < 32; i++) {
paging_map_page(new_proc->pml4_phys, 0x800000, v2p((uint64_t)user_stack), PT_PRESENT | PT_RW | PT_USER); 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 // Allocate code page aligned and copy code
void* code = kmalloc_aligned(4096, 4096); 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); uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 32768);
*(--stack_ptr) = 0x1B; // SS (User Data) *(--stack_ptr) = 0x1B; // SS (User Data)
*(--stack_ptr) = 0x800000 + 4096; // RSP *(--stack_ptr) = 0x800000 + 131072; // RSP
*(--stack_ptr) = 0x202; // RFLAGS (IF=1) *(--stack_ptr) = 0x202; // RFLAGS (IF=1)
*(--stack_ptr) = 0x23; // CS (User Code) *(--stack_ptr) = 0x23; // CS (User Code)
*(--stack_ptr) = 0x400000; // RIP *(--stack_ptr) = 0x400000; // RIP