From f85145edea7e0621fd3f73b5e544f5455399df60 Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 01/20] [SERVICES] added services [PACKAGE] added package manager Signed-off-by: di --- Makefile | 7 ++- kernel/kernel_processes/boot/bootprocess.c | 23 +++++-- kernel/process/syscall.c | 2 +- kernel/tools/tools.c | 12 ++-- services/Makefile | 25 ++++++++ services/ServiceMakefile | 48 +++++++++++++++ services/pacguy/main.c | 70 ++++++++++++++++++++++ shared | 2 +- 8 files changed, 178 insertions(+), 11 deletions(-) create mode 100644 services/Makefile create mode 100644 services/ServiceMakefile create mode 100644 services/pacguy/main.c diff --git a/Makefile b/Makefile index 993aa303..305a403b 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ endif .PHONY: all shared user kernel clean raspi virt run debug dump prepare-fs help install -all: kshared modules kernel shared user tools libs docs +all: kshared modules kernel shared user tools libs services docs @echo "Build complete." ./createfs @@ -33,6 +33,9 @@ kernel: kshared modules tools: shared libs prepare-fs $(MAKE) -C tools +services: shared libs prepare-fs + $(MAKE) -C services + libs: shared $(MAKE) -C libs @@ -50,6 +53,7 @@ clean: $(MAKE) -C tools $@ $(MAKE) -C modules $@ $(MAKE) -C libs $@ + $(MAKE) -C services $@ @echo "removing images" $(RM) kernel.img kernel.elf dump @@ -72,6 +76,7 @@ dump: $(ARCH)objdump -S -D kernel.elf > dump $(MAKE) -C user $@ $(MAKE) -C tools $@ + $(MAKE) -C services $@ install: $(MAKE) clean diff --git a/kernel/kernel_processes/boot/bootprocess.c b/kernel/kernel_processes/boot/bootprocess.c index bbb36c9c..228635ec 100644 --- a/kernel/kernel_processes/boot/bootprocess.c +++ b/kernel/kernel_processes/boot/bootprocess.c @@ -6,16 +6,17 @@ #include "input/input_dispatch.h" #include "usb/usb.h" #include "graph/graphics.h" -#include "exceptions/exception_handler.h" #include "kernel_processes/boot/screensaver.h" #include "kernel_processes/boot/login_screen.h" #include "kernel_processes/windows/dos.h" #include "tools/tools.h" +#include "files/helpers.h" enum { bsm_none, bsm_screensaver, bsm_login, + bsm_services, bsm_userland } boot_state; @@ -27,12 +28,25 @@ void visual_init(){ mouse_config((gpu_point){(i32)screen_size.width/2,(i32)screen_size.height/2}, screen_size); } +void load_service(const char *directory, const char *service){ + if (strlen(service) && *service == '.') return; + string full_name = string_format("%s/%s",directory,service); + process_t *proc = execute(full_name.data, 0, 0, EXEC_MODE_KEEP_FOCUS); + string_free(full_name); + if (!proc) print("[BOOT error] failed to load service %s",service); +} + void bootsm_transition(int new_state){ boot_state = new_state; switch (boot_state) { case bsm_none: break; case bsm_screensaver: current_proc = start_screensaver(); break; case bsm_login: current_proc = present_login(); break; + case bsm_services: { + traverse_directory("/boot/redos/services", false, load_service); + current_proc = 0; + break; + } case bsm_userland: { if (system_config.headless || !system_config.use_windows){ const char *argv = system_config.headless ? "headless" : ""; @@ -55,9 +69,10 @@ void bootsm_advance(){ bootsm_transition(bsm_screensaver); break; } - bootsm_transition(bsm_userland); break; - case bsm_screensaver: bootsm_transition(bsm_userland); break; - case bsm_login: bootsm_transition(system_config.headless ? bsm_userland : bsm_screensaver); break; + bootsm_transition(bsm_services); break; + case bsm_screensaver: bootsm_transition(bsm_services); break; + case bsm_login: bootsm_transition(system_config.headless ? bsm_services : bsm_screensaver); break; + case bsm_services: bootsm_transition(bsm_userland); break; case bsm_userland: bootsm_transition(bsm_none); break; } } diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index ddd5e448..849dac11 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -692,7 +692,7 @@ void sync_el0_handler_c(){ while (true); } else { kprintf("Process has crashed. ESR: %llx. ELR: %llx. FAR: %llx. SP: %llx", esr, elr, far, current_thread->sp); - if (syscall_depth <= 2) coredump(esr, elr, far, current_thread->sp); + coredump(esr, elr, far, current_thread->sp); syscall_depth--; stop_current_process(ec); } diff --git a/kernel/tools/tools.c b/kernel/tools/tools.c index 4a00bc52..20208083 100644 --- a/kernel/tools/tools.c +++ b/kernel/tools/tools.c @@ -48,10 +48,14 @@ process_t* execute(const char* prog_name, int argc, const char* argv[], uint32_t i++; } - string executable = string_format("%s/%s.elf",prog_name,proc_name); - process_t *proc = load_elf_process_path(proc_name, prog_name, executable.data, argc, argv); - release(executable.data); - if (!proc) return 0; + process_t *proc = load_elf_process_path(proc_name, prog_name, prog_name, argc, argv); + if (!proc) { + //TODO: this should only be for .red + string executable = string_format("%s/%s.elf",prog_name,proc_name); + proc = load_elf_process_path(proc_name, prog_name, executable.data, argc, argv); + release(executable.data); + if (!proc) return 0; + } if (win_id) proc->win_id = win_id; if (transfer_focus) sys_set_focus(proc->id); diff --git a/services/Makefile b/services/Makefile new file mode 100644 index 00000000..85ecd230 --- /dev/null +++ b/services/Makefile @@ -0,0 +1,25 @@ +include ../common.mk + +SUBDIRS := $(wildcard */.) +SUBCLEAN = $(addsuffix .clean,$(SUBDIRS)) +SUBDUMP = $(addsuffix .dump,$(SUBDIRS)) +MAKEFILE := $(shell pwd)/ServiceMakefile + +all: $(SUBDIRS) + +dump: $(SUBDUMP) + +$(SUBDIRS): + $(MAKE) -f $(MAKEFILE) -C $@ + +clean: $(SUBCLEAN) + +$(SUBCLEAN): %.clean: + $(MAKE) -f $(MAKEFILE) -C $* clean + +$(SUBDUMP): %.dump: + $(MAKE) -f $(MAKEFILE) -C $* dump + +clean: $(SUBCLEAN) + +.PHONY: all $(SUBDIRS) diff --git a/services/ServiceMakefile b/services/ServiceMakefile new file mode 100644 index 00000000..a55630bd --- /dev/null +++ b/services/ServiceMakefile @@ -0,0 +1,48 @@ +include ../../common.mk + +CPPFLAGS := -I. -I../../shared -I../../libs +CFLAGS := $(CFLAGS_BASE) $(CPPFLAGS) +CXXFLAGS := $(CXXFLAGS_BASE) $(CPPFLAGS) +LDFLAGS := -emain + +CLEAN_OBJS := $(shell find . -name '*.o') +CLEAN_DEPS := $(shell find . -name '*.d') +C_SRC := $(shell find . -name '*.c') +OBJ := $(C_SRC:%.c=$(BUILD_DIR)/%.o) +DEP := $(C_SRC:%.c=$(BUILD_DIR)/%.d) + +NAME := $(notdir $(CURDIR)) +ELF := $(NAME).elf +TARGET := $(NAME).bin +LOCATION := ../../fs/redos/services/ +LIBRARIES := $(wildcard ../../libs/*.a) + +.PHONY: prepare all clean + +all: prepare $(TARGET) + +prepare: + mkdir -p $(LOCATION) + mkdir -p $(BUILD_DIR) + +$(TARGET): ../../shared/libshared.a $(OBJ) + $(VLD) $(LDFLAGS) -o $(ELF) $(addprefix $(BUILD_DIR)/,$(notdir $(OBJ))) $(LIBRARIES) ../../shared/libshared.a + $(OBJCOPY) -O binary $(ELF) $@ + cp -r $(ELF) $(LOCATION)/$(NAME) + +$(BUILD_DIR)/%.o: %.S + @mkdir -p $(dir $@) + $(VAS) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/%.o: %.c + @mkdir -p $(dir $@) + $(VCC) $(CFLAGS) -c -MMD -MP $< -o $@ + +clean: + $(RM) $(CLEAN_OBJS) $(CLEAN_DEPS) $(TARGET) $(ELF) + $(RM) -r $(BUILD_DIR) + +dump: all + $(ARCH)objdump -S $(ELF) > dump + +-include $(DEP) diff --git a/services/pacguy/main.c b/services/pacguy/main.c new file mode 100644 index 00000000..b6efb6b8 --- /dev/null +++ b/services/pacguy/main.c @@ -0,0 +1,70 @@ +#include "syscalls/syscalls.h" +#include "files/system_module.h" +#include "files/vfs.h" +#include "files/helpers.h" + +bool loaded = false; + +uint16_t find_extension(char *path){ + uint16_t count = 0; + while (*path && *path != '.'){ path++; count++; } + return path ? count : 0; +} + +void handle_entry(const char *directory, const char *file) { + if (!strcmp_case("launcher.red",file,true)) return; + if (strlen(file) && *file == '.') return; + string fullpath = string_format("%s/%s",directory, file); + uint16_t ext_loc = find_extension((char*)file); + string_slice name = make_string_slice(fullpath.data, fullpath.length - strlen(file), ext_loc); + uint16_t extra = ext_loc ? 1 : 0; + string_slice ext = make_string_slice(name.data + ext_loc + 1, 0, strlen(file)-ext_loc-extra); + if (slice_lit_match(ext,"red",true)){ + print("Found file %s/%s",directory,file); + make_complex_entry(file, backing_virtual, entry_directory, DATA_SIG_REDPKG, (file_actions){}, fullpath); + } else string_free(fullpath); +} + +void refresh_apps(){ + if (!entries) entries = stack_create(sizeof(module_file),32); + size_t count = stack_count(entries); + for (size_t i = 0; i < count; i++){ + string_free(STACK_GET(module_file, entries, i).name); + string_free(STACK_GET(module_file, entries, i).alias_info.alias_path); + } + stack_reset(entries); + traverse_directory("/home/applications", false, handle_entry); + traverse_directory("/boot/redos/system", false, handle_entry); + loaded = true; +} + +size_t custom_readdir(const char *path, void *buf, size_t size, file_offset *offset){ + refresh_apps(); + return vfs_readdir(path, buf, size, offset); +} + +bool custom_stat(const char *path, fs_stat *out_stat){ + return vfs_stat(path, out_stat); +} + +system_module apps_mod = { + .name = "apps folder", + .mount = "apps", + //TODO: can init be brought back now? + .version = VERSION_NUM(0, 1, 0, 0), + .open = vfs_open, + .read = vfs_read, + .write = vfs_write, + .getstat = vfs_stat, + .readdir = vfs_readdir, +}; + +int main(int argc, char* argv[]){ + print("Ello world mate"); + refresh_apps(); + load_fsmodule(&apps_mod, true); + + while (true){} + + return 0; +} \ No newline at end of file diff --git a/shared b/shared index 7449400a..76cb1495 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 7449400aae7e5d49d45497fa87f2ac46a3c2e44b +Subproject commit 76cb149514dd70ff2fab832e0675c1a99192b092 From 707d92765f7d5ec6c76c7a275462bcd53b96a3bc Mon Sep 17 00:00:00 2001 From: di Date: Sun, 2 Aug 2026 00:00:00 +0000 Subject: [PATCH 02/20] [JOB] always interrupt kernel Signed-off-by: di --- kernel/process/jobs/job_manager.c | 65 ++++++++++++++----------------- kernel/process/jobs/job_save.S | 5 +-- kernel/process/syscall.c | 1 + 3 files changed, 32 insertions(+), 39 deletions(-) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 7878d6e8..21e1c8a8 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -111,13 +111,11 @@ u64 create_new_job(job_application_t application, system_module *mod, thread_t * new_t->job_id = job->id; job->worker = new_t; requester->state = BLOCKED; - if (syscall_depth >= 1){ - print("[JOB debug] kstack has been saved to %llx - %x",job_kstack.ptr,job_kstack.size); - memcpy(&job->kernel_ctx, kthread, sizeof(thread_t)); - job->kernel_ctx.job_id = job->id; - job->kernel_ctx.pc = job_save_ret(); - job->kstack = job_kstack; - } else memset(&job->kernel_ctx, 0, sizeof(thread_t)); + print("[JOB debug] kstack has been saved to %llx - %x",job_kstack.ptr,job_kstack.size); + memcpy(&job->kernel_ctx, kthread, sizeof(thread_t)); + job->kernel_ctx.job_id = job->id; + job->kernel_ctx.pc = job_save_ret(); + job->kstack = job_kstack; schedule_thread(fs_owner, new_t); switch_proc(YIELD); return 0; @@ -177,35 +175,30 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ } } } - print("[JOB] %i fulfilled by %i",job_id,thread->tid); - if (st->kernel_ctx.job_id){ - st->kernel_ctx.PROC_X0 = ret; - job_kpec = (uptr)&st->kernel_ctx; - cpec = (uptr)st->requester; - - if (st->kstack.ptr){ - st->kernel_ctx.sp = translate_stack((st->kstack.ptr+0x10000), st->kernel_ctx.sp); - print("[JOB debug] Initial Address %llx",st->kernel_ctx.regs[29]); - st->kernel_ctx.regs[29] = translate_stack((st->kstack.ptr+0x10000), st->kernel_ctx.regs[29]); - - uptr addr = st->kernel_ctx.regs[29]; - uptr fp = 0; - do { - print("[JOB debug] Address %llx",addr); - fp = *(uptr*)addr; - print("[JOB debug] Link %llx",fp); - fp = translate_stack(st->kstack.ptr+0x10000, fp); - print("[JOB debug] In new stack %llx",fp); - *(uptr*)addr = fp; - addr = fp; - } while(addr && (addr & 0xfffff00000000000) == 0xffffc00000000000); - } - st->requester->state = RUNNING; - prepare_process_restore(proc); + print("[JOB] %i fulfilled by %i with return value %llx",job_id,thread->tid); + st->kernel_ctx.PROC_X0 = ret; + job_kpec = (uptr)&st->kernel_ctx; + cpec = (uptr)st->requester; + + if (st->kstack.ptr){ + st->kernel_ctx.sp = translate_stack((st->kstack.ptr+0x10000), st->kernel_ctx.sp); + print("[JOB debug] Initial Address %llx",st->kernel_ctx.regs[29]); + st->kernel_ctx.regs[29] = translate_stack((st->kstack.ptr+0x10000), st->kernel_ctx.regs[29]); + + uptr addr = st->kernel_ctx.regs[29]; + uptr fp = 0; + do { + print("[JOB debug] Address %llx",addr); + fp = *(uptr*)addr; + print("[JOB debug] Link %llx",fp); + fp = translate_stack(st->kstack.ptr+0x10000, fp); + print("[JOB debug] In new stack %llx",fp); + *(uptr*)addr = fp; + addr = fp; + } while(addr && (addr & 0xfffff00000000000) == 0xffffc00000000000); job_ksp = st->kstack.ptr+0x10000; - job_restore_kernel(); - } else { - ready_thread(st->requester); - st->requester->PROC_X0 = ret; } + st->requester->state = RUNNING; + prepare_process_restore(proc); + job_restore_kernel(); } \ No newline at end of file diff --git a/kernel/process/jobs/job_save.S b/kernel/process/jobs/job_save.S index 2cbfbb58..80a984b1 100644 --- a/kernel/process/jobs/job_save.S +++ b/kernel/process/jobs/job_save.S @@ -1,6 +1,5 @@ .global job_save_kernel job_save_kernel: - msr daifset, #2 stp x17, x18, [sp, #-16]! add x17, sp, #16 @@ -59,7 +58,7 @@ adrp x1, ksp add x1, x1, :lo12:ksp cmp x0, x1 -b.ne 2f +b.ne 1f mov x1, sp sub x21, x0, x1 @@ -77,7 +76,7 @@ mov x1, sp mov x2, x21 bl memcpy -2: +1: ldp x0, x1, [sp, #0] ldp x21,x30, [sp, #16] diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 87739089..ff53b2d6 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -707,6 +707,7 @@ void sync_el0_handler_c(){ //TODO: schedule kstack_top to cleanup, but don't do immediately as we're in it current_thread->kstack_top = 0; } + job_ksp = (uptr)ksp; process_restore(); } From bd268c270a9f8d8af61fa2a4749caf123154e6c4 Mon Sep 17 00:00:00 2001 From: di Date: Thu, 6 Aug 2026 00:00:00 +0000 Subject: [PATCH 03/20] [JOB] proper reuse of kstack Signed-off-by: di --- kernel/filesystem/filesystem.c | 1 + kernel/process/jobs/job_manager.c | 17 +++++++---------- kernel/process/jobs/job_manager.h | 4 +--- kernel/process/loading/elf_file.c | 4 +++- services/pacguy/main.c | 12 ++++++++++++ 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index e15488b1..32ae8fda 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -60,6 +60,7 @@ FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor job_serialize_str(&app, 0, search_path); job_serialize_fd(&app, 1, descriptor, copy_on_end); }); + *out_mod = mod; return j_ret; } else { result = mod->open(search_path, descriptor); diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 21e1c8a8..cfdfd3e4 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -99,7 +99,8 @@ u64 create_new_job(job_application_t application, system_module *mod, thread_t * job->type = application.type; job->mod = mod; thread_t *requester = (thread_t*)get_thread_from_proc(requesting_proc, application.requesting_tid); - if (job_ksp != (uptr)ksp) requester->kstack_top = job_ksp; + if (job_kstack.ptr) + requester->kstack_top = job_kstack.ptr+job_kstack.size; job->requester = requester; process_t *fs_owner = get_proc_by_pid(application.worker_pid); thread_t *new_t = alloc_thread(); @@ -162,17 +163,13 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ for (size_t i = 0; i < st->buffer_count; i++){ job_buffer buf = st->buffers[i]; if (buf.sync & copy_on_end && buf.worker_ptr.ptr){ - print("[JOB debug] Copy buffer %x into %x",buf.worker_ptr.ptr,buf.orig_ptr.ptr); + print("[JOB debug] Copy buffer %x into %llx",buf.worker_ptr.ptr,buf.orig_ptr.ptr); void* addr = quick_translate(st->requester, proc, buf.orig_ptr.ptr); - if (!addr) continue; - memcpy(addr, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); - file *fd = addr; - if (buf.fd){ - print("[JOB DEBUG] fd %i size %i signature %s",fd->id,fd->size,&fd->data_type); - if (st->type == job_open){ - instance_local_fd(st->mod, addr); - } + if (!addr){ + if (buf.orig_ptr.ptr & HIGH_VA) addr = (void*)buf.orig_ptr.ptr;//TODO: extra safety checks? + else continue; } + memcpy(addr, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); } } print("[JOB] %i fulfilled by %i with return value %llx",job_id,thread->tid); diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index f8842116..68c5a5a1 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -14,11 +14,9 @@ extern void save_kstack(); thread_t kthread = {};\ job_kstack = (sizedptr){};\ job_kpec = (uptr)&kthread;\ - if (!job_ksp) job_ksp = (uptr)ksp;\ + job_ksp = get_current_thread()->kstack_top ?: (uptr)ksp;\ job_save_kernel();\ - print("KStack save to %llx",job_ksp);\ save_kstack();\ - print("KStack saved to %llx of size %llx from %llx",job_kstack.ptr,job_kstack.size,ksp);\ process_t *owner_proc = get_proc_by_pid(mod->owner);\ job_application_t app = (job_application_t){\ .requesting_pid = get_current_proc()->id,\ diff --git a/kernel/process/loading/elf_file.c b/kernel/process/loading/elf_file.c index ad6e90b9..4acc856a 100644 --- a/kernel/process/loading/elf_file.c +++ b/kernel/process/loading/elf_file.c @@ -206,8 +206,10 @@ process_t* load_elf_process_path(const char *name, const char *bundle, const cha close_file(&fd); return 0; } + + size_t amt = read_file(&fd, program, fd.size); + bool ok = amt == fd.size; - bool ok = read_file(&fd, program, fd.size) == fd.size; close_file(&fd); if (!ok) { release(program); diff --git a/services/pacguy/main.c b/services/pacguy/main.c index b6efb6b8..3722a524 100644 --- a/services/pacguy/main.c +++ b/services/pacguy/main.c @@ -47,6 +47,18 @@ bool custom_stat(const char *path, fs_stat *out_stat){ return vfs_stat(path, out_stat); } +FS_RESULT custom_open(const char *path, file *fd){ + FS_RESULT res = vfs_open(path, fd); + print("Opened fd inside module with %i",fd->id); + return res; +} + +size_t custom_read(file *fd, char *buf, size_t size, file_offset off){ + size_t res = vfs_read(fd, buf, size, off); + print("Result on fid %i size %i",fd->id,size); + return res; +} + system_module apps_mod = { .name = "apps folder", .mount = "apps", From aa3e1eec7349e46c227847084aec128b06412227 Mon Sep 17 00:00:00 2001 From: di Date: Fri, 7 Aug 2026 00:00:00 +0000 Subject: [PATCH 04/20] [PACKAGEMAN] tools dir [TOOLS] ktools rename and listing [JOBS] added TODO since values within the stack might themselves need translation Signed-off-by: di --- kernel/filesystem/filesystem.c | 1 + kernel/process/jobs/job_manager.c | 6 +-- kernel/process/jobs/job_manager.h | 6 +++ kernel/tools/tools.c | 38 +++++++++++----- services/pacguy/apps.c | 39 ++++++++++++++++ services/pacguy/main.c | 75 +++---------------------------- services/pacguy/tools.c | 35 +++++++++++++++ shared | 2 +- 8 files changed, 118 insertions(+), 84 deletions(-) create mode 100644 services/pacguy/apps.c create mode 100644 services/pacguy/tools.c diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index 32ae8fda..5cf0b358 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -57,6 +57,7 @@ FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor FS_RESULT result = FS_RESULT_DRIVER_ERROR; if (mod->owner != get_kernel_proc()->id){ job_make(job_open, mod, { + //TODO: here, out_mod is in the stack, and we're referencing it through a pointer, which we of course lose as we move the stack the first time. job_serialize_str(&app, 0, search_path); job_serialize_fd(&app, 1, descriptor, copy_on_end); }); diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index cfdfd3e4..0ce6f28a 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -145,10 +145,6 @@ void* quick_translate(thread_t *thread, process_t *proc, uptr ptr){ extern uptr cpec; -static inline uptr translate_stack(uptr new_top, uptr ptr){ - return new_top-((uptr)ksp-ptr); -} - void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ job_state_t *st = get_job_state(job_id); if (!st) { @@ -163,7 +159,7 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ for (size_t i = 0; i < st->buffer_count; i++){ job_buffer buf = st->buffers[i]; if (buf.sync & copy_on_end && buf.worker_ptr.ptr){ - print("[JOB debug] Copy buffer %x into %llx",buf.worker_ptr.ptr,buf.orig_ptr.ptr); + print("[JOB debug] Copy buffer %llx into %llx",buf.worker_ptr.ptr,buf.orig_ptr.ptr); void* addr = quick_translate(st->requester, proc, buf.orig_ptr.ptr); if (!addr){ if (buf.orig_ptr.ptr & HIGH_VA) addr = (void*)buf.orig_ptr.ptr;//TODO: extra safety checks? diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index 68c5a5a1..363112ae 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -92,3 +92,9 @@ static inline void job_serialize_off(job_application_t *application, int arg_num u64 create_new_job(job_application_t application, system_module *mod, thread_t *kthread); void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread); + +extern char ksp[]; + +static inline uptr translate_stack(uptr new_top, uptr ptr){ + return new_top-((uptr)ksp-ptr); +} \ No newline at end of file diff --git a/kernel/tools/tools.c b/kernel/tools/tools.c index 20208083..cfedccc5 100644 --- a/kernel/tools/tools.c +++ b/kernel/tools/tools.c @@ -88,27 +88,45 @@ process_t* execute(const char* prog_name, int argc, const char* argv[], uint32_t return 0; } -FS_RESULT open_tools(){ - return FS_RESULT_DRIVER_ERROR; -} - -size_t read_tools(){ - return 0; +size_t ktools_list(const char *path, void *buf, size_t size, file_offset *offset){ + file_offset off = offset ? *offset : 0; + fs_dir_list_helper helper = create_dir_list_helper(buf, size); + for (u64 i = off; i < N_ARR(available_cmds); i++){ + if (!dir_list_fill(&helper, available_cmds[i].name)){ + if (offset) *offset = i; + return dir_buf_size(&helper); + } + } + return dir_buf_size(&helper); } -size_t list_tools(const char *path, void *buf, size_t size, file_offset offset){ - return 0; +bool ktools_stat(const char *path, fs_stat *out_stat){ + if (strlen(path) && *path == '/') path++; + if (!strlen(path)){ + stat_dir(out_stat); + return true; + } + for (u64 i = 0; i < N_ARR(available_cmds); i++){ + if (strncmp(available_cmds[i].name, path, strlen(available_cmds[i].name)) == 0){ + out_stat->size = 0; + out_stat->data_type = DATA_SIGNATURE("KPROC"); + out_stat->type = entry_file; + return true; + } + } + return true; } //TODO: finish listing tool module system_module tool_module = (system_module){ .name = "tools", - .mount = "tools", + .mount = "ktools", .version = VERSION_NUM(0, 1, 0, 1), .init = init_tools, .fini = 0, .open = 0, .read = 0, .write = 0, - .readdir = 0, + .getstat = ktools_stat, + .readdir = ktools_list, }; diff --git a/services/pacguy/apps.c b/services/pacguy/apps.c new file mode 100644 index 00000000..d29071e1 --- /dev/null +++ b/services/pacguy/apps.c @@ -0,0 +1,39 @@ +#include "files/vfs.h" +#include "files/helpers.h" + +void handle_entry(const char *directory, const char *file) { + if (strlen(file) && *file == '.') return; + string fullpath = string_format("%s/%s",directory, file); + uint16_t ext_loc = find_find_extension_index((char*)file); + string_slice name = make_string_slice(fullpath.data, fullpath.length - strlen(file), ext_loc); + uint16_t extra = ext_loc ? 1 : 0; + string_slice ext = make_string_slice(name.data + ext_loc + 1, 0, strlen(file)-ext_loc-extra); + if (slice_lit_match(ext,"red",true)){ + print("Found file %s/%s",directory,file); + make_complex_entry(file, backing_virtual, entry_directory, DATA_SIG_REDPKG, (file_actions){}, fullpath); + } else string_free(fullpath); +} + +void refresh_apps(){ + if (!entries) entries = stack_create(sizeof(module_file),32); + size_t count = stack_count(entries); + for (size_t i = 0; i < count; i++){ + string_free(STACK_GET(module_file, entries, i).name); + string_free(STACK_GET(module_file, entries, i).alias_info.alias_path); + } + stack_reset(entries); + traverse_directory("/home/applications", false, handle_entry); + traverse_directory("/boot/redos/system", false, handle_entry); +} + +system_module apps_mod = { + .name = "apps folder", + .mount = "apps", + //TODO: can init be brought back now? + .version = VERSION_NUM(0, 1, 0, 0), + .open = vfs_open, + .read = vfs_read, + .write = vfs_write, + .getstat = vfs_stat, + .readdir = vfs_readdir, +}; \ No newline at end of file diff --git a/services/pacguy/main.c b/services/pacguy/main.c index 3722a524..47dfd02d 100644 --- a/services/pacguy/main.c +++ b/services/pacguy/main.c @@ -1,81 +1,20 @@ #include "syscalls/syscalls.h" #include "files/system_module.h" -#include "files/vfs.h" #include "files/helpers.h" -bool loaded = false; +extern void refresh_apps(); +extern system_module apps_mod; -uint16_t find_extension(char *path){ - uint16_t count = 0; - while (*path && *path != '.'){ path++; count++; } - return path ? count : 0; -} - -void handle_entry(const char *directory, const char *file) { - if (!strcmp_case("launcher.red",file,true)) return; - if (strlen(file) && *file == '.') return; - string fullpath = string_format("%s/%s",directory, file); - uint16_t ext_loc = find_extension((char*)file); - string_slice name = make_string_slice(fullpath.data, fullpath.length - strlen(file), ext_loc); - uint16_t extra = ext_loc ? 1 : 0; - string_slice ext = make_string_slice(name.data + ext_loc + 1, 0, strlen(file)-ext_loc-extra); - if (slice_lit_match(ext,"red",true)){ - print("Found file %s/%s",directory,file); - make_complex_entry(file, backing_virtual, entry_directory, DATA_SIG_REDPKG, (file_actions){}, fullpath); - } else string_free(fullpath); -} - -void refresh_apps(){ - if (!entries) entries = stack_create(sizeof(module_file),32); - size_t count = stack_count(entries); - for (size_t i = 0; i < count; i++){ - string_free(STACK_GET(module_file, entries, i).name); - string_free(STACK_GET(module_file, entries, i).alias_info.alias_path); - } - stack_reset(entries); - traverse_directory("/home/applications", false, handle_entry); - traverse_directory("/boot/redos/system", false, handle_entry); - loaded = true; -} - -size_t custom_readdir(const char *path, void *buf, size_t size, file_offset *offset){ - refresh_apps(); - return vfs_readdir(path, buf, size, offset); -} - -bool custom_stat(const char *path, fs_stat *out_stat){ - return vfs_stat(path, out_stat); -} - -FS_RESULT custom_open(const char *path, file *fd){ - FS_RESULT res = vfs_open(path, fd); - print("Opened fd inside module with %i",fd->id); - return res; -} - -size_t custom_read(file *fd, char *buf, size_t size, file_offset off){ - size_t res = vfs_read(fd, buf, size, off); - print("Result on fid %i size %i",fd->id,size); - return res; -} - -system_module apps_mod = { - .name = "apps folder", - .mount = "apps", - //TODO: can init be brought back now? - .version = VERSION_NUM(0, 1, 0, 0), - .open = vfs_open, - .read = vfs_read, - .write = vfs_write, - .getstat = vfs_stat, - .readdir = vfs_readdir, -}; +extern void refresh_tools(); +extern system_module tools_mod; int main(int argc, char* argv[]){ - print("Ello world mate"); refresh_apps(); load_fsmodule(&apps_mod, true); + refresh_tools(); + load_fsmodule(&tools_mod, true); + while (true){} return 0; diff --git a/services/pacguy/tools.c b/services/pacguy/tools.c new file mode 100644 index 00000000..c803c2be --- /dev/null +++ b/services/pacguy/tools.c @@ -0,0 +1,35 @@ +#include "files/system_module.h" +#include "files/vfs.h" +#include "files/helpers.h" + +void tools_handle_entry(const char *directory, const char *file) { + print("Found tool %s",file); + if (strlen(file) && *file == '.') return; + string fullpath = string_format("%s/%s",directory, file); + make_complex_entry(file, backing_virtual, entry_file, DATA_SIG_REDPKG, (file_actions){}, fullpath); +} + +void refresh_tools(){ + if (!entries) entries = stack_create(sizeof(module_file),32); + size_t count = stack_count(entries); + for (size_t i = 0; i < count; i++){ + string_free(STACK_GET(module_file, entries, i).name); + string_free(STACK_GET(module_file, entries, i).alias_info.alias_path); + } + stack_reset(entries); + traverse_directory("/home/tools", false, tools_handle_entry); + traverse_directory("/boot/redos/tools", false, tools_handle_entry); + traverse_directory("/ktools", false, tools_handle_entry); +} + +system_module tools_mod = { + .name = "tools folder", + .mount = "tools", + //TODO: can init be brought back now? + .version = VERSION_NUM(0, 1, 0, 0), + .open = vfs_trace_open, + .read = vfs_trace_read, + .write = vfs_trace_write, + .getstat = vfs_trace_stat, + .readdir = vfs_trace_readdir, +}; \ No newline at end of file diff --git a/shared b/shared index 1442cef4..5444877f 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 1442cef44fcf72143332558c5f86be9f7d9f6ca6 +Subproject commit 5444877f6eac64d1ba799b8f19eebcf110189f96 From 543dd0d0e35ac73e84198c266b61e5d7673d9fd2 Mon Sep 17 00:00:00 2001 From: di Date: Sat, 8 Aug 2026 00:00:00 +0000 Subject: [PATCH 05/20] [FAT32] stat fix Signed-off-by: di --- kernel/filesystem/fat32.cpp | 4 ++-- kernel/process/jobs/job_manager.c | 1 + shared | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index 3ce9a314..b3338300 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -402,7 +402,7 @@ u32 FAT32FS::alloc_fat(){ f32_walk_result FAT32FS::read_entry_handler(FAT32FS *instance, f32file_entry *entry, char *filename, const char *seek) { if (entry->flags.volume_id) return {}; - + size_t name_len = strlen_max(filename, 0); int matched = strstart_case(seek, filename, true); if (matched != (int)name_len) return {}; @@ -417,7 +417,7 @@ f32_walk_result FAT32FS::read_entry_handler(FAT32FS *instance, f32file_entry *en uint32_t bpc = bps * spc; uint32_t count = entry->filesize > 0 ? ((entry->filesize + bpc - 1) / bpc) : instance->count_FAT(filecluster); - if (entry->flags.directory) return instance->walk_directory(count, filecluster, next, read_entry_handler); + if (entry->flags.directory && *next) return instance->walk_directory(count, filecluster, next, read_entry_handler); if (*next != '\0') return {}; return {.entry = *entry, .cluster = 0, .offset = 0, .found = true}; } diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 0ce6f28a..755493a4 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -173,6 +173,7 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ job_kpec = (uptr)&st->kernel_ctx; cpec = (uptr)st->requester; + //TODO: this entire thing is flimsy, we're only translating stack returns so we can make our way back to the userland proc, but any &values stored in the stack are not translated and risk corruption + failure if (st->kstack.ptr){ st->kernel_ctx.sp = translate_stack((st->kstack.ptr+0x10000), st->kernel_ctx.sp); print("[JOB debug] Initial Address %llx",st->kernel_ctx.regs[29]); diff --git a/shared b/shared index 5444877f..e407b15d 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 5444877f6eac64d1ba799b8f19eebcf110189f96 +Subproject commit e407b15d4bb3dfa86837bec7e9457a1029607d60 From 605df03b7fbb61d852ef88c9b56ef33aa628ede6 Mon Sep 17 00:00:00 2001 From: di Date: Sat, 8 Aug 2026 00:00:00 +0000 Subject: [PATCH 06/20] [APP_BUNDLE] added package identifiers (not yet parsed) Signed-off-by: di --- shared | 2 +- user/UserMakefile | 1 + user/demo/package.info | 8 ++++---- user/filebrowser/package.info | 3 +++ user/launcher/package.info | 3 +++ user/terminal/package.info | 3 +++ user/theme/package.info | 3 +++ 7 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 user/filebrowser/package.info create mode 100644 user/launcher/package.info create mode 100644 user/terminal/package.info create mode 100644 user/theme/package.info diff --git a/shared b/shared index e407b15d..9ca10745 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit e407b15d4bb3dfa86837bec7e9457a1029607d60 +Subproject commit 9ca10745fe148e79c545413b043c17bd73d8996d diff --git a/user/UserMakefile b/user/UserMakefile index da135fa9..921f4c48 100644 --- a/user/UserMakefile +++ b/user/UserMakefile @@ -27,6 +27,7 @@ prepare: mkdir -p $(BUILD_DIR) mkdir -p $(PACKAGE) cp -r resources $(PACKAGE) + cp package.info $(PACKAGE)/package.info 2>/dev/null || : $(PACKAGE)/$(TARGET): ../../shared/libshared.a $(OBJ) $(VLD) $(LDFLAGS) -o $(PACKAGE)/$(ELF) $(addprefix $(BUILD_DIR)/,$(notdir $(OBJ))) ../../shared/libshared.a diff --git a/user/demo/package.info b/user/demo/package.info index 09b2ff74..cbe80f6f 100644 --- a/user/demo/package.info +++ b/user/demo/package.info @@ -1,10 +1,10 @@ # Name app_name = "Demo" -app_author="[REDACTED]" # Comments are allowed -unknown values="will be ignored" +unknown_values="will be ignored" -// C-style comments are allowed too + indentation="is ok" +app_author="[REDACTED]" - "indentation"=and no quotes \ No newline at end of file +app_bundle_id="com.redos.demo" \ No newline at end of file diff --git a/user/filebrowser/package.info b/user/filebrowser/package.info new file mode 100644 index 00000000..62c72342 --- /dev/null +++ b/user/filebrowser/package.info @@ -0,0 +1,3 @@ +app_name="File browser" +app_author="[REDACTED]" +app_bundle_id="com.redos.filebrowser" \ No newline at end of file diff --git a/user/launcher/package.info b/user/launcher/package.info new file mode 100644 index 00000000..ce7b7cd0 --- /dev/null +++ b/user/launcher/package.info @@ -0,0 +1,3 @@ +app_name="App launcher" +app_author="[REDACTED]" +app_bundle_id="com.redos.launcher" \ No newline at end of file diff --git a/user/terminal/package.info b/user/terminal/package.info new file mode 100644 index 00000000..05091c24 --- /dev/null +++ b/user/terminal/package.info @@ -0,0 +1,3 @@ +app_name="Terminal" +app_author="[REDACTED]" +app_bundle_id="com.redos.legacy.terminal" \ No newline at end of file diff --git a/user/theme/package.info b/user/theme/package.info new file mode 100644 index 00000000..8a1c0613 --- /dev/null +++ b/user/theme/package.info @@ -0,0 +1,3 @@ +app_name="Theme selector" +app_author="[REDACTED]" +app_bundle_id="com.redos.theme" \ No newline at end of file From 3de0af4cf3096fefe73dbd046a86c28a0a12a660 Mon Sep 17 00:00:00 2001 From: di Date: Sat, 8 Aug 2026 00:00:00 +0000 Subject: [PATCH 07/20] [FS] added transform operations [BUNDLE] added package ids [TOOLS] added launch tool with pkg id [PACKAGEMAN] added resolve Signed-off-by: di --- kernel/filesystem/fat32.cpp | 1 + kernel/filesystem/filesystem.c | 22 +++++++++++++++++++ kernel/filesystem/filesystem.h | 1 + kernel/filesystem/virtio_9p_pci.cpp | 1 + kernel/networking/network.cpp | 1 + kernel/process/jobs/job_manager.c | 1 + kernel/process/kernel_syscall_impl.c | 8 ++++++- kernel/process/syscall.c | 17 ++++++++++++++ modules/audio/virt/audio.cpp | 1 + modules/disk/raspi/disk.cpp | 1 + modules/graph/raspi/graphics.cpp | 1 + modules/graph/virt/graphics.cpp | 1 + modules/usb/common/usb_common.cpp | 1 + services/pacguy/apps.c | 31 ++++++++++++++++++++++++++ shared | 2 +- tools/launch/launch.c | 33 ++++++++++++++++++++++++++++ user/launcher/main.c | 2 +- user/launcher/package_info.c | 18 --------------- user/launcher/package_info.h | 19 ---------------- 19 files changed, 122 insertions(+), 40 deletions(-) create mode 100644 tools/launch/launch.c delete mode 100644 user/launcher/package_info.c delete mode 100644 user/launcher/package_info.h diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index b3338300..519fd631 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -703,6 +703,7 @@ system_module boot_fs_module = (system_module){ .truncate = boot_truncate, .getstat = boot_stat, .readdir = boot_partition_readdir, + .transform = 0, .alias_info = {} }; diff --git a/kernel/filesystem/filesystem.c b/kernel/filesystem/filesystem.c index 5cf0b358..a70d849c 100644 --- a/kernel/filesystem/filesystem.c +++ b/kernel/filesystem/filesystem.c @@ -143,6 +143,28 @@ size_t read_file(file *descriptor, char* buf, size_t size){ return amount_read; } +size_t transform_file(module_root *root, const char* path, void* buf, size_t size){ + const char *search_path = path; + if (*search_path == '/') search_path++; + if (!*search_path) return FS_RESULT_NOTFOUND; + system_module *mod = get_module_from(root, &search_path); + if (!mod) return FS_RESULT_NOTFOUND; + if (!mod->transform) return FS_RESULT_NOTFOUND; + FS_RESULT result = FS_RESULT_DRIVER_ERROR; + if (mod->owner != get_kernel_proc()->id){ + job_make(job_transform, mod, { + job_serialize_str(&app, 0, search_path); + job_serialize_buf(&app, 1, true, (void*)buf, size, copy_on_start | copy_on_end); + }); + return j_ret; + } else { + result = mod->transform(search_path, buf, size); + } + if (result != FS_RESULT_SUCCESS) return result; + if (!open_files) return FS_RESULT_DRIVER_ERROR; + return FS_RESULT_SUCCESS; +} + void close_file(file *descriptor){ if (!open_files || !descriptor) return; open_file_descriptors *ofile = 0; diff --git a/kernel/filesystem/filesystem.h b/kernel/filesystem/filesystem.h index 54c2d786..2115d939 100644 --- a/kernel/filesystem/filesystem.h +++ b/kernel/filesystem/filesystem.h @@ -13,6 +13,7 @@ FS_RESULT open_file_global(module_root *root, const char* path, file* descriptor FS_RESULT open_file(module_root *root, const char* path, file* descriptor); FS_RESULT instance_local_fd(system_module *mod, file *descriptor); size_t read_file(file *descriptor, char* buf, size_t size); +size_t transform_file(module_root *root, const char* path, void* buf, size_t size); size_t write_file(file *descriptor, const char* buf, size_t size); void close_file_global(file *descriptor, system_module *mod); void close_file(file *descriptor); diff --git a/kernel/filesystem/virtio_9p_pci.cpp b/kernel/filesystem/virtio_9p_pci.cpp index f13b5718..2d10a8cb 100644 --- a/kernel/filesystem/virtio_9p_pci.cpp +++ b/kernel/filesystem/virtio_9p_pci.cpp @@ -606,6 +606,7 @@ system_module p9_fs_module = (system_module){ .truncate = shared_truncate, .getstat = shared_stat, .readdir = shared_readdir, + .transform = 0, .alias_info = {} }; diff --git a/kernel/networking/network.cpp b/kernel/networking/network.cpp index c1b7e87e..c4ff365a 100644 --- a/kernel/networking/network.cpp +++ b/kernel/networking/network.cpp @@ -100,5 +100,6 @@ system_module net_module = (system_module){ .truncate = 0, .getstat = 0, .readdir = 0, + .transform = 0, .alias_info = {} }; \ No newline at end of file diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 755493a4..305b282c 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -55,6 +55,7 @@ bool prepare_thread(job_state_t *job, system_module *mod, job_application_t appl case job_read: entry = (uptr)mod->read; break; case job_write: entry = (uptr)mod->write; break; case job_trunc: entry = (uptr)mod->truncate; break; + case job_transform: entry = (uptr)mod->transform; break; default: return false; } if (!entry) return false; diff --git a/kernel/process/kernel_syscall_impl.c b/kernel/process/kernel_syscall_impl.c index f9c35be9..f20fac4c 100644 --- a/kernel/process/kernel_syscall_impl.c +++ b/kernel/process/kernel_syscall_impl.c @@ -80,7 +80,6 @@ void resize_draw_ctx(draw_ctx* d_ctx, uint32_t width, uint32_t height){ gpu_flush(); } - uint32_t gpu_char_size(uint32_t scale){ return gpu_get_char_size(scale); } @@ -135,6 +134,13 @@ size_t readf(file *descriptor, char* buf, size_t size){ return read_file(descriptor, buf, size); } +size_t transformf(const char *path, void* buf, size_t size){ + module_root rootfs = {}; + string s = resolve_isolated_path(path, get_current_proc()->permissions.fs_id, &rootfs, true); + if (!s.data || !s.length) return transform_file(kernel_fs(), path, buf, size); + return transform_file(&rootfs, path, buf, size); +} + size_t writef(file *descriptor, const char* buf, size_t size){ return write_file(descriptor, buf, size); } diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index ff53b2d6..5b8c2d1b 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -379,6 +379,22 @@ u64 syscall_writef(process_t *ctx, thread_t *current_thread){ return write_file(descriptor, buf, size); } +u64 syscall_transf(process_t *ctx, thread_t *current_thread){ + SYSCALL_STR(path, PROC_X0, false); + size_t size = (size_t)current_thread->PROC_X2; + SYSCALL_ARG_SIZE(void, buf, size, PROC_X1, true); +#ifdef ISOLATEDFS + module_root rootfs = {}; + string s = resolve_isolated_path(path, ctx->permissions.fs_id, &rootfs, ISOLATEDFS_ALLOW_KFS); + if (!s.data || !s.length) return 0; + size_t ret = transform_file(&rootfs, s.data, buf, size); + string_free(s); + return ret; +#else + return transform_file(kernel_fs(), path, buf, size); +#endif +} + u64 syscall_sreadf(process_t *ctx, thread_t *current_thread){ SYSCALL_STR(path, PROC_X0, false); size_t size = (size_t)current_thread->PROC_X2; @@ -549,6 +565,7 @@ syscall_entry syscalls[] = { [DIR_LIST_CODE] = syscall_dir_list, [FILE_STAT_CODE] = syscall_stat, [FILE_TRNC_CODE] = syscall_trunc, + [FILE_TRANS_CODE] = syscall_transf, [LOAD_FSMODULE_CODE] = syscall_load_fsmod, [UNLOAD_FSMODULE_CODE] = syscall_unload_fsmod, diff --git a/modules/audio/virt/audio.cpp b/modules/audio/virt/audio.cpp index f6d38000..748a956a 100644 --- a/modules/audio/virt/audio.cpp +++ b/modules/audio/virt/audio.cpp @@ -314,5 +314,6 @@ system_module audio_module = (system_module){ .truncate = 0, .getstat = 0,//TODO: stat .readdir = 0, + .transform = 0, .alias_info = {} }; diff --git a/modules/disk/raspi/disk.cpp b/modules/disk/raspi/disk.cpp index 2d221c4b..ce9a1e36 100644 --- a/modules/disk/raspi/disk.cpp +++ b/modules/disk/raspi/disk.cpp @@ -36,5 +36,6 @@ system_module disk_module = (system_module){ .truncate = 0, .getstat = 0, .readdir = 0, + .transform = 0, .alias_info = {} }; \ No newline at end of file diff --git a/modules/graph/raspi/graphics.cpp b/modules/graph/raspi/graphics.cpp index 5f356d92..1ae8810e 100644 --- a/modules/graph/raspi/graphics.cpp +++ b/modules/graph/raspi/graphics.cpp @@ -121,5 +121,6 @@ system_module graphics_module = { .truncate = 0, .getstat = 0,//TODO: stat .readdir = 0, + .transform = 0, .alias_info = {} }; \ No newline at end of file diff --git a/modules/graph/virt/graphics.cpp b/modules/graph/virt/graphics.cpp index 0c0dad13..c3d53469 100644 --- a/modules/graph/virt/graphics.cpp +++ b/modules/graph/virt/graphics.cpp @@ -131,5 +131,6 @@ system_module graphics_module = { .truncate = 0, .getstat = 0, .readdir = 0, + .transform = 0, .alias_info = {} }; \ No newline at end of file diff --git a/modules/usb/common/usb_common.cpp b/modules/usb/common/usb_common.cpp index 9527131e..90cd8a0a 100644 --- a/modules/usb/common/usb_common.cpp +++ b/modules/usb/common/usb_common.cpp @@ -86,5 +86,6 @@ system_module usb_module = (system_module){ .truncate = 0, .getstat = 0,//TODO: stat .readdir = 0, + .transform = 0, .alias_info = {} }; \ No newline at end of file diff --git a/services/pacguy/apps.c b/services/pacguy/apps.c index d29071e1..5aecb508 100644 --- a/services/pacguy/apps.c +++ b/services/pacguy/apps.c @@ -1,5 +1,9 @@ #include "files/vfs.h" #include "files/helpers.h" +#include "utils/package_info.h" +#include "data/format/toml.h" + +int manual_entries = 0; void handle_entry(const char *directory, const char *file) { if (strlen(file) && *file == '.') return; @@ -14,6 +18,31 @@ void handle_entry(const char *directory, const char *file) { } else string_free(fullpath); } +size_t resolve_fs(const char *path, void* buf, size_t size){ + char *prompt = buf; + (void)prompt; + size_t count = stack_count(entries); + for (u32 i = manual_entries; i < count; i++){ + module_file *file = chunk_array_get(entries, i); + if (file->alias_info.alias_path.data){ + string s = string_format("%S/package.info",file->alias_info.alias_path); + char *package = read_full_file(s.data, 0); + package_info pkg_info = parse_package_info(package); + if (slice_lit_match(slice_from_string(pkg_info.id), prompt, true)){ + if (size < file->alias_info.alias_path.length) { + package_info_dispose(&pkg_info); + return 0; + } + memcpy(buf, file->alias_info.alias_path.data, file->alias_info.alias_path.length); + package_info_dispose(&pkg_info); + return file->alias_info.alias_path.length; + } else package_info_dispose(&pkg_info); + release(package); + } + } + return 0; +} + void refresh_apps(){ if (!entries) entries = stack_create(sizeof(module_file),32); size_t count = stack_count(entries); @@ -22,6 +51,7 @@ void refresh_apps(){ string_free(STACK_GET(module_file, entries, i).alias_info.alias_path); } stack_reset(entries); + manual_entries += make_complex_entry("resolve", backing_virtual, entry_file, 0, (file_actions){.transform = resolve_fs}, (string){}); traverse_directory("/home/applications", false, handle_entry); traverse_directory("/boot/redos/system", false, handle_entry); } @@ -36,4 +66,5 @@ system_module apps_mod = { .write = vfs_write, .getstat = vfs_stat, .readdir = vfs_readdir, + .transform = vfs_trace_transform, }; \ No newline at end of file diff --git a/shared b/shared index 9ca10745..de0cb5cb 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 9ca10745fe148e79c545413b043c17bd73d8996d +Subproject commit de0cb5cb7a5bc076ea0093145c7de19f083cc5bf diff --git a/tools/launch/launch.c b/tools/launch/launch.c new file mode 100644 index 00000000..164753e7 --- /dev/null +++ b/tools/launch/launch.c @@ -0,0 +1,33 @@ +#include "syscalls/syscalls.h" +#include "memory/memory.h" + +int main(int argc, const char* argv[]){ + + if (argc < 2){ + print("Usage: launch bundle.id"); + return -1; + } + + const char* bundle_id = argv[1]; + size_t bsize = strlen(bundle_id)+1; + + if (bsize > 64){ + print("Bundle id too large"); + return -1; + } + + char *buf = zalloc(512); + memcpy(buf, bundle_id, bsize); + + transformf("/apps/resolve", buf, 512); + + print("Resolved id to %s",buf); + + fs_stat out_stat = {}; + if (statf(buf, &out_stat)){ + exec(buf, 0, 0, EXEC_MODE_DEFAULT); + return 0; + } + + return -1; +} diff --git a/user/launcher/main.c b/user/launcher/main.c index 5ae2c64b..d0b9c444 100644 --- a/user/launcher/main.c +++ b/user/launcher/main.c @@ -6,7 +6,7 @@ #include "memory/memory.h" #include "input_keycodes.h" #include "string/slice.h" -#include "package_info.h" +#include "utils/package_info.h" #define MAX_COLS 3 #define MAX_ROWS 3 diff --git a/user/launcher/package_info.c b/user/launcher/package_info.c deleted file mode 100644 index 88182067..00000000 --- a/user/launcher/package_info.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "package_info.h" -#include "data/format/toml.h" - -static inline void handle_package_kvp(string_slice key, string_slice value, void* ctx){ - package_info *pkg_info = (package_info*)ctx; - if ((size_t)strstart_case("app_name", key.data,true) == key.length) - pkg_info->name = string_from_literal_length(value.data, value.length); - if ((size_t)strstart_case("app_author", key.data,true) == key.length) - pkg_info->author = string_from_literal_length(value.data, value.length); - if ((size_t)strstart_case("app_version", key.data,true) == key.length) - pkg_info->version = string_from_literal_length(value.data, value.length); -} - -package_info parse_package_info(char *info){ - package_info pkg_info = {}; - read_toml(info, handle_package_kvp, (void*)&pkg_info); - return pkg_info; -} \ No newline at end of file diff --git a/user/launcher/package_info.h b/user/launcher/package_info.h deleted file mode 100644 index 4a396f40..00000000 --- a/user/launcher/package_info.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "types.h" -#include "std/string.h" - -typedef struct { - bool valid; - string name; - string author; - string version; -} package_info; - -#ifdef __cplusplus -extern "C" { -#endif -package_info parse_package_info(char *info); -#ifdef __cplusplus -} -#endif \ No newline at end of file From 8248550053c1c6a276e62cb89225681431e77d9f Mon Sep 17 00:00:00 2001 From: di Date: Mon, 10 Aug 2026 00:00:00 +0000 Subject: [PATCH 08/20] [KBD] differentiate between key press and key continue --- kernel/usb/USBKeyboard.cpp | 2 +- shared | 2 +- user/launcher/main.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/usb/USBKeyboard.cpp b/kernel/usb/USBKeyboard.cpp index 4f613401..6d25083c 100644 --- a/kernel/usb/USBKeyboard.cpp +++ b/kernel/usb/USBKeyboard.cpp @@ -113,7 +113,7 @@ void USBKeyboard::process_keypress(keypress *rkp){ if (now < next_repeat[key]) continue; kbd_event event = {}; - event.type = KEY_PRESS; + event.type = KEY_CONTINUE; event.key = (char)key; register_event(event); diff --git a/shared b/shared index de0cb5cb..d4cf40ca 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit de0cb5cb7a5bc076ea0093145c7de19f083cc5bf +Subproject commit d4cf40cad57d761d0db01395c251e86aec6c50a5 diff --git a/user/launcher/main.c b/user/launcher/main.c index d0b9c444..c6508c37 100644 --- a/user/launcher/main.c +++ b/user/launcher/main.c @@ -117,7 +117,7 @@ void draw_desktop(){ gpu_point old_selected = selected; kbd_event event; while (read_event(&event)){ - if (event.type == KEY_PRESS){ + if (event.type == KEY_PRESS || event.type == KEY_CONTINUE){ switch (event.key) { case KEY_ENTER: case KEY_KPENTER: From ed8ecddeb0e9532244a7e7848010af7876db1cdb Mon Sep 17 00:00:00 2001 From: di Date: Mon, 10 Aug 2026 00:00:00 +0000 Subject: [PATCH 09/20] [SHARED] sign fix --- shared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared b/shared index d4cf40ca..2200ae41 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit d4cf40cad57d761d0db01395c251e86aec6c50a5 +Subproject commit 2200ae4183c1a473e942aef791eb4b99cef6c1c5 From 9cb5b038fc37c70b234a729afc0719f6a12800ab Mon Sep 17 00:00:00 2001 From: di Date: Tue, 11 Aug 2026 00:00:00 +0000 Subject: [PATCH 10/20] [JOB] replace the stack using virtual mapping --- kernel/memory/mmu.c | 58 ++++++++++++++++++++++--- kernel/memory/mmu.h | 3 ++ kernel/process/jobs/job_manager.c | 50 ++++++++++----------- kernel/process/jobs/job_manager.h | 12 ++--- kernel/process/jobs/job_save.S | 17 +++----- kernel/process/loading/elf_file.c | 4 +- kernel/process/loading/process_loader.c | 1 - kernel/process/process.h | 2 +- kernel/process/scheduler.c | 1 + kernel/process/syscall.c | 10 +++-- 10 files changed, 98 insertions(+), 60 deletions(-) diff --git a/kernel/memory/mmu.c b/kernel/memory/mmu.c index 27f06933..f5215c58 100644 --- a/kernel/memory/mmu.c +++ b/kernel/memory/mmu.c @@ -503,10 +503,7 @@ void mmu_init() { page_alloc_enable_high_va(); kernel_ttbr0_hw = pt_va_to_pa(kernel_ttbr0) & PTE_ADDR_MASK; - uint64_t ttbr1_pa = pt_va_to_pa(kernel_ttbr1) & PTE_ADDR_MASK; - asm volatile("msr ttbr1_el1, %0" :: "r"(ttbr1_pa)); - asm volatile("dsb ish"); - asm volatile("isb"); + mmu_swap_kttbr(0); mmu_swap_ttbr(0); @@ -538,6 +535,12 @@ void mmu_copy(uintptr_t *new_ttbr, uintptr_t *old_ttbr, int level){ } } +bool mmu_replace(uptr *table, uptr va, uptr new_pa){ + mmu_unmap_and_get_pa(table, va, 0); + mmu_map_4kb(table, va, new_pa, MAIR_IDX_NORMAL, MEM_RW | MEM_NORM, MEM_PRIV_KERNEL); + return true; +} + typedef struct { uintptr_t *table; int level; @@ -722,6 +725,44 @@ uintptr_t mmu_translate(uint64_t *root, uintptr_t va, int *status){ return (uintptr_t)((e3 & PTE_ADDR_MASK) | ((uint64_t)va & (GRANULE_4KB - 1))); } +//TODO: let's use this everywhere, to make code more readable +typedef union { + struct { + u64 vb: 1;//Validity descriptor + u64 tb: 1;//Table descriptor + u64 indx: 2;//Index into MAIR + u64 ns: 1; + u64 ap: 2; + u64 sh: 2; + u64 af: 1; + u64 rsvd3: 2; + u64 addr: 36; + u64 rsvd2: 5; + u64 pxn: 1; + u64 uxn: 1; + u64 sw: 4; + u64 rsvd: 5; + }; + u64 entry; +} +mmu_entry_t; + +void mmu_print_entry(mmu_entry_t entry){ + print("========="); + print("MMU entry %llb",entry); + print("UXN: %b",entry.uxn); + print("PXN: %b",entry.pxn); + print("ADDR: %llx",entry.addr); + print("AF: %b",entry.af); + print("SH: %b",entry.sh); + print("AP: %b",entry.ap); + print("NS: %b",entry.ns); + print("INDX: %i",entry.indx); + print("TB: %b",entry.tb); + print("VB: %b",entry.vb); + print("========="); +} + void debug_mmu_address(uint64_t va){ int tr = 0; uintptr_t pa = mmu_translate(0, (uintptr_t)va, &tr); @@ -771,7 +812,7 @@ void debug_mmu_address(uint64_t va){ if ((e2 & 0b11) == PD_BLOCK) { kprintf("Mapped as 2MB memory in L3"); - kprintf("Entry: %b", (uint64_t)e2); + mmu_print_entry((mmu_entry_t){ .entry = e2 }); return; } @@ -786,7 +827,7 @@ void debug_mmu_address(uint64_t va){ kprintf("L4 Table entry missing"); return; } - kprintf("Entry: %b", e3); + mmu_print_entry((mmu_entry_t){.entry = e3}); return; } @@ -803,6 +844,11 @@ void mmu_ttbr0_enable_user() { asm volatile("dsb ish\n\tisb" ::: "memory"); } +void mmu_swap_kttbr(uptr *ttbr){ + uint64_t ttbr1_pa = pt_va_to_pa(ttbr ?: kernel_ttbr1); + asm volatile("msr ttbr1_el1, %0" :: "r"(ttbr1_pa)); +} + void mmu_swap_ttbr(mm_struct *mm){ if (mm && mm->ttbr0) { pttbr = mm->ttbr0; diff --git a/kernel/memory/mmu.h b/kernel/memory/mmu.h index 80d150a1..5cb8f12c 100644 --- a/kernel/memory/mmu.h +++ b/kernel/memory/mmu.h @@ -45,6 +45,7 @@ void mmu_map_4kb(uint64_t *table, uint64_t va, uint64_t pa, uint64_t attr_index, void mmu_unmap_table(uint64_t *table, uint64_t va, uint64_t pa); void debug_mmu_address(uint64_t va); void mmu_enable_verbose(); +void mmu_swap_kttbr(uptr *ttbr); void mmu_swap_ttbr(mm_struct *mm); void mmu_ttbr0_disable_user(); void mmu_ttbr0_enable_user(); @@ -53,6 +54,8 @@ void mmu_asid_ensure(mm_struct *mm); void mmu_asid_release(mm_struct *mm); bool mmu_unmap_and_get_pa(uint64_t *table, uint64_t va, uint64_t *pa); bool mmu_set_access_flag(uint64_t *table, uint64_t va); +void mmu_copy(uintptr_t *new_ttbr, uintptr_t *old_ttbr, int level); +bool mmu_replace(uptr *ttbr, uptr va, uptr new_pa); uintptr_t* mmu_default_ttbr(); void mmu_free_ttbr(uintptr_t *ttbr); uintptr_t mmu_translate(uint64_t *root, uintptr_t va, int *status); diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 305b282c..02b4459d 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -20,7 +20,7 @@ typedef struct { thread_t *requester; thread_t *worker; thread_t kernel_ctx; - sizedptr kstack; + uptr* kttbr; job_id_t id; job_buffer buffers[8]; size_t buffer_count; @@ -94,20 +94,18 @@ u64 create_new_job(job_application_t application, system_module *mod, thread_t * process_t *requesting_proc = get_proc_by_pid(application.requesting_pid); if (!requesting_proc){ print("[JOB error] Unknown requesting proc %i",application.requesting_pid); - return (job_id_t){}; + return 0; } job_state_t *job = job_alloc(); job->type = application.type; job->mod = mod; thread_t *requester = (thread_t*)get_thread_from_proc(requesting_proc, application.requesting_tid); - if (job_kstack.ptr) - requester->kstack_top = job_kstack.ptr+job_kstack.size; job->requester = requester; process_t *fs_owner = get_proc_by_pid(application.worker_pid); thread_t *new_t = alloc_thread(); if (!prepare_thread(job, mod, application, fs_owner, new_t)){ print("[JOB error] failed to prepare thread for job %i",job->id); - return false; + return 0; } print("[JOB debug] Sync between %i - %i will happen with job %i of type %i using thread %i",requester->pid,application.worker_pid,job->id,application.type,new_t->tid); new_t->job_id = job->id; @@ -117,7 +115,19 @@ u64 create_new_job(job_application_t application, system_module *mod, thread_t * memcpy(&job->kernel_ctx, kthread, sizeof(thread_t)); job->kernel_ctx.job_id = job->id; job->kernel_ctx.pc = job_save_ret(); - job->kstack = job_kstack; + if (job_kstack.ptr && job_kstack.size){ + uptr* ttbr1k = mmu_default_ttbr(); + uptr* newttbr1 = mmu_new_ttbr(); + job->kttbr = newttbr1; + mmu_copy(newttbr1, ttbr1k, 0); + uptr base = (uptr)ksp - 0x10000; + for (uptr a = 0; a < 0x10000; a += PAGE_SIZE){ + int st = 0; + uptr addr = mmu_translate(newttbr1, job_kstack.ptr + a, &st); + if (st) return 0;//TODO: release table + mmu_replace(newttbr1, base + a, addr); + } + } schedule_thread(fs_owner, new_t); switch_proc(YIELD); return 0; @@ -163,9 +173,12 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ print("[JOB debug] Copy buffer %llx into %llx",buf.worker_ptr.ptr,buf.orig_ptr.ptr); void* addr = quick_translate(st->requester, proc, buf.orig_ptr.ptr); if (!addr){ - if (buf.orig_ptr.ptr & HIGH_VA) addr = (void*)buf.orig_ptr.ptr;//TODO: extra safety checks? - else continue; + if (buf.orig_ptr.ptr & HIGH_VA){ + int stb = 0; + addr = (void*)PHYS_TO_VIRT(mmu_translate(st->kttbr, buf.orig_ptr.ptr, &stb)); + } } + if (!addr) continue; memcpy(addr, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); } } @@ -174,26 +187,9 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ job_kpec = (uptr)&st->kernel_ctx; cpec = (uptr)st->requester; - //TODO: this entire thing is flimsy, we're only translating stack returns so we can make our way back to the userland proc, but any &values stored in the stack are not translated and risk corruption + failure - if (st->kstack.ptr){ - st->kernel_ctx.sp = translate_stack((st->kstack.ptr+0x10000), st->kernel_ctx.sp); - print("[JOB debug] Initial Address %llx",st->kernel_ctx.regs[29]); - st->kernel_ctx.regs[29] = translate_stack((st->kstack.ptr+0x10000), st->kernel_ctx.regs[29]); - - uptr addr = st->kernel_ctx.regs[29]; - uptr fp = 0; - do { - print("[JOB debug] Address %llx",addr); - fp = *(uptr*)addr; - print("[JOB debug] Link %llx",fp); - fp = translate_stack(st->kstack.ptr+0x10000, fp); - print("[JOB debug] In new stack %llx",fp); - *(uptr*)addr = fp; - addr = fp; - } while(addr && (addr & 0xfffff00000000000) == 0xffffc00000000000); - job_ksp = st->kstack.ptr+0x10000; - } st->requester->state = RUNNING; + st->requester->special_mm = st->kttbr; prepare_process_restore(proc); + mmu_swap_kttbr(st->kttbr); job_restore_kernel(); } \ No newline at end of file diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index 363112ae..18709484 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -14,9 +14,9 @@ extern void save_kstack(); thread_t kthread = {};\ job_kstack = (sizedptr){};\ job_kpec = (uptr)&kthread;\ - job_ksp = get_current_thread()->kstack_top ?: (uptr)ksp;\ job_save_kernel();\ - save_kstack();\ + if (!get_current_thread()->special_mm)\ + save_kstack();\ process_t *owner_proc = get_proc_by_pid(mod->owner);\ job_application_t app = (job_application_t){\ .requesting_pid = get_current_proc()->id,\ @@ -91,10 +91,4 @@ static inline void job_serialize_off(job_application_t *application, int arg_num } u64 create_new_job(job_application_t application, system_module *mod, thread_t *kthread); -void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread); - -extern char ksp[]; - -static inline uptr translate_stack(uptr new_top, uptr ptr){ - return new_top-((uptr)ksp-ptr); -} \ No newline at end of file +void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread); \ No newline at end of file diff --git a/kernel/process/jobs/job_save.S b/kernel/process/jobs/job_save.S index 80a984b1..c3c8759f 100644 --- a/kernel/process/jobs/job_save.S +++ b/kernel/process/jobs/job_save.S @@ -50,15 +50,8 @@ sub sp, sp, #32 stp x0, x1, [sp, #0] stp x21,x30, [sp, #16] -adrp x0, job_ksp -add x0, x0, :lo12:job_ksp -ldr x0, [x0] - -adrp x1, ksp -add x1, x1, :lo12:ksp -cmp x0, x1 - -b.ne 1f +adrp x0, ksp +add x0, x0, :lo12:ksp mov x1, sp sub x21, x0, x1 @@ -76,7 +69,6 @@ mov x1, sp mov x2, x21 bl memcpy -1: ldp x0, x1, [sp, #0] ldp x21,x30, [sp, #16] @@ -119,6 +111,11 @@ job_restore_kernel: ldr x30, [x18, #(8 * 32)] ldr x18, [x18, #(8 * 18)] + dsb ishst + tlbi vmalle1is + dsb ish + isb + ret .global job_save_ret diff --git a/kernel/process/loading/elf_file.c b/kernel/process/loading/elf_file.c index 4acc856a..c8f8da0d 100644 --- a/kernel/process/loading/elf_file.c +++ b/kernel/process/loading/elf_file.c @@ -199,7 +199,7 @@ process_t* load_elf_process_path(const char *name, const char *bundle, const cha if (!path || !*path) return 0; file fd = {}; - if (open_file(kernel_fs(), path, &fd) != FS_RESULT_SUCCESS) return 0; + if (open_file(kernel_fs(), path, &fd) != FS_RESULT_SUCCESS || fd.size == 0) return 0; char *program = (char*)zalloc(fd.size); if (!program) { @@ -208,7 +208,7 @@ process_t* load_elf_process_path(const char *name, const char *bundle, const cha } size_t amt = read_file(&fd, program, fd.size); - bool ok = amt == fd.size; + bool ok = amt && amt == fd.size; close_file(&fd); if (!ok) { diff --git a/kernel/process/loading/process_loader.c b/kernel/process/loading/process_loader.c index 9b1b74f5..b97b5326 100644 --- a/kernel/process/loading/process_loader.c +++ b/kernel/process/loading/process_loader.c @@ -405,7 +405,6 @@ process_t* create_process(const char *name, const char *bundle, program_load_dat proc->mm.rss_stack_pages = 0; - proc->shared_page = shared_base; proc->main_thread.regs[30] = proc->shared_page; kprintf("[NEW PROC:U]: %s (pid: %i, main tid: %i) allocated at %llx entry=%llx stack=%llx-%llx anon=%llx (phys=%llx)", name, proc->id, proc->main_thread.tid, proc, (uint64_t)proc->main_thread.pc, (uint64_t)proc->mm.stack_limit, (uint64_t)proc->mm.stack_top, (uint64_t)proc->mm.mmap_bottom, (uint64_t)proc->heap_phys); diff --git a/kernel/process/process.h b/kernel/process/process.h index b1a2a2cf..67c9afe7 100644 --- a/kernel/process/process.h +++ b/kernel/process/process.h @@ -72,7 +72,7 @@ struct thread_t { uint64_t spsr; //Not used in context saving stack_t stack_info; - uptr kstack_top; + uptr *special_mm; u16 pid; u16 tid; process_state state; diff --git a/kernel/process/scheduler.c b/kernel/process/scheduler.c index 5bab0b64..fb151713 100644 --- a/kernel/process/scheduler.c +++ b/kernel/process/scheduler.c @@ -172,6 +172,7 @@ void switch_proc(ProcSwitchReason reason) { } if (current_proc->mm.ttbr0) mmu_asid_ensure(¤t_proc->mm); + mmu_swap_kttbr(0); mmu_swap_ttbr(current_proc->mm.ttbr0 ? ¤t_proc->mm : 0); if (prev && prev != current_proc && prev != idle_proc && process_can_reset(prev)) reset_process(prev); diff --git a/kernel/process/syscall.c b/kernel/process/syscall.c index 5b8c2d1b..0ddb8a2e 100644 --- a/kernel/process/syscall.c +++ b/kernel/process/syscall.c @@ -705,7 +705,7 @@ void sync_el0_handler_c(){ if (syscall_depth < 3){ uint64_t ksp = 0; asm volatile ("mov %0, sp" : "=r"(ksp)); - kprintf("System has crashed. ESR: %llx. ELR: %llx. FAR: %llx. KSP: %llx", esr, elr, far, ksp); + kprintf("System has crashed. ESR: %llx. ELR: %llx. FAR: %llx. SP: %llx", esr, elr, far, ksp); coredump(esr, elr, far, ksp); } handle_exception("UNEXPECTED EXCEPTION", ec); @@ -719,10 +719,12 @@ void sync_el0_handler_c(){ } syscall_depth--; save_syscall_return(result); - // print("Return to %i",current_thread->pid); - if (current_thread->kstack_top) { + if (current_thread->special_mm) { //TODO: schedule kstack_top to cleanup, but don't do immediately as we're in it - current_thread->kstack_top = 0; + current_thread->special_mm = 0; + mmu_swap_kttbr(0); + mmu_flush_all(); + mmu_flush_icache(); } job_ksp = (uptr)ksp; process_restore(); From f7049b19de154f55d61883cbde479ee33d01892a Mon Sep 17 00:00:00 2001 From: di Date: Wed, 12 Aug 2026 00:00:00 +0000 Subject: [PATCH 11/20] [MMU] restored flushes to header --- kernel/memory/mmu.c | 20 -------------------- kernel/memory/mmu.h | 20 +++++++++++++++++++- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/kernel/memory/mmu.c b/kernel/memory/mmu.c index f5215c58..ff8dd0e7 100644 --- a/kernel/memory/mmu.c +++ b/kernel/memory/mmu.c @@ -38,8 +38,6 @@ static uintptr_t *kernel_ttbr1; static uint64_t kernel_ttbr0_hw; static bool mmu_verbose; -static inline void mmu_flush_icache(); -static inline void mmu_flush_all(); static uint64_t asid_shift; @@ -296,24 +294,6 @@ void mmu_map_4kb(uint64_t *table, uint64_t va, uint64_t pa, uint64_t attr_index, l3[l3_index] = want; } -static inline void mmu_flush_all() { - asm volatile ( - "dsb ishst\n" // Ensure all memory accesses complete - "tlbi vmalle1is\n" // Invalidate all EL1 TLB entries (Inner Shareable) - "dsb ish\n" // Ensure completion of TLB invalidation - "isb\n" // Synchronize pipeline - ::: "memory" - ); -} - -static inline void mmu_flush_icache() { - asm volatile ( - "ic iallu\n" // Invalidate all instruction caches to PoU - "isb\n" // Ensure completion before continuing - ::: "memory" - ); -} - uintptr_t* mmu_default_ttbr(){ return kernel_ttbr1; } diff --git a/kernel/memory/mmu.h b/kernel/memory/mmu.h index 5cb8f12c..9475d406 100644 --- a/kernel/memory/mmu.h +++ b/kernel/memory/mmu.h @@ -66,4 +66,22 @@ void mmu_map_all(paddr_t pa); void mmu_unmap(uint64_t va, uint64_t pa); -void mmu_init_kernel(); \ No newline at end of file +void mmu_init_kernel(); + +static inline void mmu_flush_all() { + asm volatile ( + "dsb ishst\n" // Ensure all memory accesses complete + "tlbi vmalle1is\n" // Invalidate all EL1 TLB entries (Inner Shareable) + "dsb ish\n" // Ensure completion of TLB invalidation + "isb\n" // Synchronize pipeline + ::: "memory" + ); +} + +static inline void mmu_flush_icache() { + asm volatile ( + "ic iallu\n" // Invalidate all instruction caches to PoU + "isb\n" // Ensure completion before continuing + ::: "memory" + ); +} \ No newline at end of file From de08b95eaa3c80e068e669a6692c86fbf0fbbfb6 Mon Sep 17 00:00:00 2001 From: di Date: Tue, 18 Aug 2026 00:00:00 +0000 Subject: [PATCH 12/20] [F32] using new allocator --- kernel/filesystem/fat32.cpp | 65 +++++++++++++++++-------------- kernel/process/jobs/job_manager.c | 2 +- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/kernel/filesystem/fat32.cpp b/kernel/filesystem/fat32.cpp index 519fd631..fbd179dc 100644 --- a/kernel/filesystem/fat32.cpp +++ b/kernel/filesystem/fat32.cpp @@ -1,15 +1,16 @@ #include "fat32.hpp" +#include "alloc/mem_types.h" #include "disk.h" -#include "memory/page_allocator.h" +#include "files/system_module.h" #include "console/kio.h" -#include "std/memory_access.h" -#include "std/string.h" -#include "std/memory.h" +#include "memory/memory.h" +#include "memory/memory_access.h" #include "math/math.h" #include "syscalls/syscalls.h" #include "exceptions/irq.h" #include "files/dir_list.h" #include "filesystem/modules/module_loader.h" +#include "alloc/allocate.h" #define kprintfv(fmt, ...) \ ({ \ @@ -18,10 +19,14 @@ }\ }) +void* f32palloc(size_t size){ + return palloc(size, MEM_PRIV_KERNEL, MEM_DEV | MEM_RW, true); +} + bool FAT32FS::init(uint32_t partition_sector){ - fs_page = palloc(0x1000, MEM_PRIV_KERNEL, MEM_DEV | MEM_RW, false); + fs_page = f32palloc(PAGE_SIZE); - mbs = (fat32_mbs*)kalloc(fs_page, 512, ALIGN_64B, MEM_PRIV_KERNEL); + mbs = (fat32_mbs*)allocate(fs_page, 512, f32palloc); if (!mbs) return false; partition_first_sector = partition_sector; @@ -65,7 +70,7 @@ sizedptr FAT32FS::read_cluster(uint32_t cluster_start, uint32_t cluster_size, ui if (root_index < 2 || root_index >= total_fat_entries) return (sizedptr){ 0, 0}; size_t size = cluster_count * cluster_size * 512; - void* buffer = kalloc(fs_page, size, ALIGN_64B, MEM_PRIV_KERNEL); + void *buffer = allocate(fs_page, size, f32palloc); if (!buffer) return (sizedptr){0, 0}; uint32_t next_index = root_index; @@ -114,7 +119,7 @@ bool FAT32FS::write_section_to_cluster(u32 cluster, u32 offset, void *buf, size_ u32 sector_count = ceil(((float)offset + size)/512); - void *initial = kalloc(fs_page, 512 * sector_count, ALIGN_64B, MEM_PRIV_KERNEL); + void *initial = allocate(fs_page, 512 * sector_count, f32palloc); disk_read(initial, sector, sector_count); @@ -175,7 +180,7 @@ f32_walk_result FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_in u32 cluster_byte_size = cluster_size * 512; for (uint64_t i = 0; i + sizeof(f32file_entry) <= buf_ptr.size;) { if (buffer[i] == 0) { - kfree(buffer, buf_ptr.size); + release(buffer); return {}; } if (buffer[i] == 0xE5){ @@ -183,7 +188,7 @@ f32_walk_result FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_in continue; } bool long_name = buffer[i + 0xB] == 0xF; - char filename[256] = {0}; + char filename[256] = {}; if (long_name){ f32longname *first_longname = (f32longname*)&buffer[i]; uint16_t count = 0; @@ -191,7 +196,7 @@ f32_walk_result FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_in i += sizeof(f32longname); count++; if (i + sizeof(f32file_entry) > buf_ptr.size) { - kfree(buffer, buf_ptr.size); + release(buffer); return {}; } } while (buffer[i + 0xB] == 0xF); @@ -215,16 +220,16 @@ f32_walk_result FAT32FS::walk_directory(uint32_t cluster_count, uint32_t root_in .offset = offset, .found = true, }; - kfree(buffer, buf_ptr.size); + release(buffer); return result; } - kfree(buffer, buf_ptr.size); + release(buffer); return found_entry; } i += sizeof(f32file_entry); } - kfree(buffer, buf_ptr.size); + release(buffer); return {}; } @@ -236,9 +241,9 @@ sizedptr FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { f32file_entry *entry = 0; if (!buffer || !buf_ptr.size) return { 0, 0}; size_t full_size = buf_ptr.size + 4; - void *list_buffer = kalloc(fs_page, full_size, ALIGN_64B, MEM_PRIV_KERNEL); + void *list_buffer = allocate(fs_page, full_size, f32palloc); if (!list_buffer) { - kfree(buffer, buf_ptr.size); + release(buffer); return { 0, 0}; } @@ -261,8 +266,8 @@ sizedptr FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { i += sizeof(f32longname); long_count++; if (i + sizeof(f32file_entry) > buf_ptr.size) { - kfree(buffer, buf_ptr.size); - kfree(list_buffer, full_size); + release(buffer); + release(list_buffer); return { 0, 0 }; } } while (buffer[i + 0xB] == 0xF); @@ -286,7 +291,7 @@ sizedptr FAT32FS::list_directory(uint32_t cluster_count, uint32_t root_index) { } *(uint32_t*)list_buffer = count; - kfree(buffer, buf_ptr.size); + release(buffer); return (sizedptr){(uintptr_t)list_buffer, full_size}; } @@ -299,22 +304,22 @@ sizedptr FAT32FS::read_full_file(uint32_t cluster_start, uint32_t cluster_size, char *buffer = (char*)buf_ptr.ptr; if (!buffer || !buf_ptr.size) return {0, 0}; - if (!file_page) file_page = page_alloc(PAGE_SIZE); + if (!file_page) file_page = f32palloc(PAGE_SIZE); - void *file = allocate(file_page, file_size ? file_size : 1, page_alloc); + void *file = allocate(file_page, file_size ? file_size : 1, f32palloc); if (!file) { - kfree(buffer, buf_ptr.size); + release(buffer); return {0, 0}; } if (file_size) memcpy(file, (void*)buffer, file_size); - kfree(buffer, buf_ptr.size); + release(buffer); return (sizedptr){(uintptr_t)file,file_size}; } void FAT32FS::read_FAT(uint32_t location, uint32_t size, uint8_t count){ - fat = (uint32_t*)kalloc(fs_page, size * 512, ALIGN_64B, MEM_PRIV_KERNEL); + fat = (uint32_t*)allocate(fs_page, size*512, f32palloc); if (!fat) { total_fat_entries = 0; return; @@ -448,9 +453,9 @@ FS_RESULT FAT32FS::open_file(const char* path, file* descriptor){ if (!buf || !buf_ptr.size) return FS_RESULT_NOTFOUND; descriptor->id = fid; descriptor->size = buf_ptr.size; - mfile = (module_file*)kalloc(fs_page, sizeof(module_file), ALIGN_64B, MEM_PRIV_KERNEL); + mfile = (module_file*)allocate(fs_page, sizeof(module_file), f32palloc); if (!mfile) { - kfree(buf, buf_ptr.size ? buf_ptr.size : 1); + release(buf); return FS_RESULT_DRIVER_ERROR; } memset(mfile, 0, sizeof(module_file)); @@ -472,8 +477,8 @@ FS_RESULT FAT32FS::open_file(const char* path, file* descriptor){ int ok = hash_map_put(open_files, &fid, sizeof(uint64_t), mfile); irq_restore(irq); if (ok < 0) { - kfree(mfile->file_buffer.buffer, mfile->file_size ? mfile->file_size : 1); - kfree(mfile, sizeof(module_file)); + release(mfile->file_buffer.buffer); + release(mfile); return FS_RESULT_DRIVER_ERROR; } return FS_RESULT_SUCCESS; @@ -524,7 +529,7 @@ void FAT32FS::close_file(file* descriptor){ hash_map_remove(open_files, &descriptor->id, sizeof(uint64_t), 0); irq_restore(irq); buffer_destroy(&mfile->file_buffer); - kfree(mfile, sizeof(module_file)); + release(mfile); return; } irq_restore(irq); @@ -605,7 +610,7 @@ size_t FAT32FS::list_contents(const char *path, void* buf, size_t size, uint64_t } *(uint32_t*)buf = count; - kfree((void*)ptr.ptr, ptr.size); + release((void*)ptr.ptr); return (uintptr_t)write_ptr-(uintptr_t)buf; } diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 02b4459d..9024dbf0 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -182,7 +182,7 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ memcpy(addr, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); } } - print("[JOB] %i fulfilled by %i with return value %llx",job_id,thread->tid); + print("[JOB] %i fulfilled by %i with return value %llx",job_id,thread->tid,thread->regs[0]); st->kernel_ctx.PROC_X0 = ret; job_kpec = (uptr)&st->kernel_ctx; cpec = (uptr)st->requester; From f0337d6571b8e2fccccfdb4297987540e721f2cc Mon Sep 17 00:00:00 2001 From: di Date: Tue, 18 Aug 2026 00:00:00 +0000 Subject: [PATCH 13/20] [JOB] fat32/stack fix --- kernel/process/jobs/job_manager.c | 2 +- kernel/process/jobs/job_manager.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 9024dbf0..3558202f 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -121,7 +121,7 @@ u64 create_new_job(job_application_t application, system_module *mod, thread_t * job->kttbr = newttbr1; mmu_copy(newttbr1, ttbr1k, 0); uptr base = (uptr)ksp - 0x10000; - for (uptr a = 0; a < 0x10000; a += PAGE_SIZE){ + for (uptr a = 0; a <= 0x10000; a += PAGE_SIZE){ int st = 0; uptr addr = mmu_translate(newttbr1, job_kstack.ptr + a, &st); if (st) return 0;//TODO: release table diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index 18709484..d497c1a5 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -10,6 +10,7 @@ extern void job_save_kernel(); extern void save_kstack(); //TODO: if the owner is the current process, we can downgrade the syscall into a function call without async +//TODO: in stack saving, just create the stack externally (belonging to proc 1), then pass it to save_kstack to copy into #define job_make(job_type,mod,action)\ thread_t kthread = {};\ job_kstack = (sizedptr){};\ From c09a1861a0f224dceb8ccdce1d261cdc2a4a7f1d Mon Sep 17 00:00:00 2001 From: di Date: Tue, 18 Aug 2026 00:00:00 +0000 Subject: [PATCH 14/20] [JOB, CORR] nvm --- kernel/process/jobs/job_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 3558202f..9024dbf0 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -121,7 +121,7 @@ u64 create_new_job(job_application_t application, system_module *mod, thread_t * job->kttbr = newttbr1; mmu_copy(newttbr1, ttbr1k, 0); uptr base = (uptr)ksp - 0x10000; - for (uptr a = 0; a <= 0x10000; a += PAGE_SIZE){ + for (uptr a = 0; a < 0x10000; a += PAGE_SIZE){ int st = 0; uptr addr = mmu_translate(newttbr1, job_kstack.ptr + a, &st); if (st) return 0;//TODO: release table From dd82b73be350235a0e8854f4496bbbe0eba3d183 Mon Sep 17 00:00:00 2001 From: di Date: Tue, 18 Aug 2026 00:00:00 +0000 Subject: [PATCH 15/20] [JOB] simplify stack creation and fix fat32 crash --- kernel/process/jobs/job_manager.c | 38 +++++++++++++++++++------------ kernel/process/jobs/job_manager.h | 12 +++++----- kernel/process/jobs/job_save.S | 23 ++++++------------- kernel/process/stack_manager.c | 18 ++++++++++----- kernel/process/stack_manager.h | 1 + user/launcher/main.c | 3 +-- 6 files changed, 50 insertions(+), 45 deletions(-) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 9024dbf0..5f80ec76 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -6,9 +6,18 @@ #include "memory/addr.h" #include "memory/memory.h" #include "filesystem/filesystem.h" +#include "process/stack_manager.h" job_id_t job_id_counter = 1; +// #define JOB_DEBUG + +#ifdef JOB_DEBUG +#define job_print(...) print(#__VA_ARGS__) +#else +#define job_print(...) +#endif + uptr job_kpec = 0; uptr job_ksp = 0; sizedptr job_kstack = {}; @@ -20,7 +29,6 @@ typedef struct { thread_t *requester; thread_t *worker; thread_t kernel_ctx; - uptr* kttbr; job_id_t id; job_buffer buffers[8]; size_t buffer_count; @@ -56,7 +64,7 @@ bool prepare_thread(job_state_t *job, system_module *mod, job_application_t appl case job_write: entry = (uptr)mod->write; break; case job_trunc: entry = (uptr)mod->truncate; break; case job_transform: entry = (uptr)mod->transform; break; - default: return false; + default: print("[JOB error] unknown type %i",application.type); return false; } if (!entry) return false; new_thread(proc, t, proc->spsr, entry); @@ -71,7 +79,7 @@ bool prepare_thread(job_state_t *job, system_module *mod, job_application_t appl register_proc_memory(PHYS_TO_VIRT(pbuffers + (i * PAGE_SIZE)), pbuffers + (i * PAGE_SIZE), MEM_RW, MEM_PRIV_KERNEL); } memset((void*)PHYS_TO_VIRT(pbuffers), 0, total_size); - print("[JOB debug] buffers will go to %llx - %llx",buffers,pbuffers); + job_print("[JOB debug] buffers will go to %llx - %llx",buffers,pbuffers); uptr next_addr_pa = PHYS_TO_VIRT(pbuffers); uptr next_addr_va = buffers; @@ -107,23 +115,24 @@ u64 create_new_job(job_application_t application, system_module *mod, thread_t * print("[JOB error] failed to prepare thread for job %i",job->id); return 0; } - print("[JOB debug] Sync between %i - %i will happen with job %i of type %i using thread %i",requester->pid,application.worker_pid,job->id,application.type,new_t->tid); + job_print("[JOB debug] Sync between %i - %i will happen with job %i of type %i using thread %i",requester->pid,application.worker_pid,job->id,application.type,new_t->tid); new_t->job_id = job->id; job->worker = new_t; requester->state = BLOCKED; - print("[JOB debug] kstack has been saved to %llx - %x",job_kstack.ptr,job_kstack.size); + job_print("[JOB debug] kstack has been saved to %llx - %x",kthread->stack_info.top,kthread->stack_info.size); memcpy(&job->kernel_ctx, kthread, sizeof(thread_t)); job->kernel_ctx.job_id = job->id; job->kernel_ctx.pc = job_save_ret(); - if (job_kstack.ptr && job_kstack.size){ + if (kthread->stack_info.top && kthread->stack_info.size){ uptr* ttbr1k = mmu_default_ttbr(); uptr* newttbr1 = mmu_new_ttbr(); - job->kttbr = newttbr1; + requester->special_mm = newttbr1; mmu_copy(newttbr1, ttbr1k, 0); - uptr base = (uptr)ksp - 0x10000; - for (uptr a = 0; a < 0x10000; a += PAGE_SIZE){ + uptr base = (uptr)ksp - kstack_max; + uptr stack = kthread->stack_info.top-kstack_max; + for (uptr a = 0; a < kstack_max; a += PAGE_SIZE){ int st = 0; - uptr addr = mmu_translate(newttbr1, job_kstack.ptr + a, &st); + uptr addr = mmu_translate(newttbr1, stack + a, &st); if (st) return 0;//TODO: release table mmu_replace(newttbr1, base + a, addr); } @@ -170,26 +179,25 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ for (size_t i = 0; i < st->buffer_count; i++){ job_buffer buf = st->buffers[i]; if (buf.sync & copy_on_end && buf.worker_ptr.ptr){ - print("[JOB debug] Copy buffer %llx into %llx",buf.worker_ptr.ptr,buf.orig_ptr.ptr); + job_print("[JOB debug] Copy buffer %llx into %llx",buf.worker_ptr.ptr,buf.orig_ptr.ptr); void* addr = quick_translate(st->requester, proc, buf.orig_ptr.ptr); if (!addr){ if (buf.orig_ptr.ptr & HIGH_VA){ int stb = 0; - addr = (void*)PHYS_TO_VIRT(mmu_translate(st->kttbr, buf.orig_ptr.ptr, &stb)); + addr = (void*)PHYS_TO_VIRT(mmu_translate(st->requester->special_mm, buf.orig_ptr.ptr, &stb)); } } if (!addr) continue; memcpy(addr, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); } } - print("[JOB] %i fulfilled by %i with return value %llx",job_id,thread->tid,thread->regs[0]); + job_print("[JOB] %i fulfilled by %i with return value %llx",job_id,thread->tid,thread->regs[0]); st->kernel_ctx.PROC_X0 = ret; job_kpec = (uptr)&st->kernel_ctx; cpec = (uptr)st->requester; st->requester->state = RUNNING; - st->requester->special_mm = st->kttbr; prepare_process_restore(proc); - mmu_swap_kttbr(st->kttbr); + mmu_swap_kttbr(st->requester->special_mm); job_restore_kernel(); } \ No newline at end of file diff --git a/kernel/process/jobs/job_manager.h b/kernel/process/jobs/job_manager.h index d497c1a5..54180866 100644 --- a/kernel/process/jobs/job_manager.h +++ b/kernel/process/jobs/job_manager.h @@ -2,22 +2,22 @@ #include "files/jobs.h" #include "process/process.h" +#include "process/stack_manager.h" extern uptr job_kpec; extern uptr job_ksp; -extern sizedptr job_kstack; extern void job_save_kernel(); -extern void save_kstack(); +extern void save_kstack(uptr stack); //TODO: if the owner is the current process, we can downgrade the syscall into a function call without async -//TODO: in stack saving, just create the stack externally (belonging to proc 1), then pass it to save_kstack to copy into #define job_make(job_type,mod,action)\ thread_t kthread = {};\ - job_kstack = (sizedptr){};\ job_kpec = (uptr)&kthread;\ job_save_kernel();\ - if (!get_current_thread()->special_mm)\ - save_kstack();\ + if (!get_current_thread()->special_mm){\ + kthread.stack_info = new_stack(get_proc_by_pid(1));\ + save_kstack(kthread.stack_info.top);\ + }\ process_t *owner_proc = get_proc_by_pid(mod->owner);\ job_application_t app = (job_application_t){\ .requesting_pid = get_current_proc()->id,\ diff --git a/kernel/process/jobs/job_save.S b/kernel/process/jobs/job_save.S index c3c8759f..77d257b6 100644 --- a/kernel/process/jobs/job_save.S +++ b/kernel/process/jobs/job_save.S @@ -44,32 +44,23 @@ add sp, sp, #16 ret .global save_kstack -save_kstack: +save_kstack: //x0 = new stack sub sp, sp, #32 -stp x0, x1, [sp, #0] +stp x2, x1, [sp, #0] stp x21,x30, [sp, #16] -adrp x0, ksp -add x0, x0, :lo12:ksp +adrp x2, ksp +add x2, x2, :lo12:ksp mov x1, sp -sub x21, x0, x1 -mov x0, #0x10000 -bl zalloc +sub x2, x2, x1 -adrp x1, job_kstack -add x1, x1, :lo12:job_kstack -stp x0, x21, [x1, #0] +sub x0,x0,x2 -add x0,x0,#0x10000 -sub x0,x0,x21 - -mov x1, sp -mov x2, x21 bl memcpy -ldp x0, x1, [sp, #0] +ldp x2, x1, [sp, #0] ldp x21,x30, [sp, #16] add sp, sp, #32 diff --git a/kernel/process/stack_manager.c b/kernel/process/stack_manager.c index aed049a5..06759085 100644 --- a/kernel/process/stack_manager.c +++ b/kernel/process/stack_manager.c @@ -1,6 +1,7 @@ #include "stack_manager.h" #include "exceptions/exception_handler.h" #include "memory/mmu.h" +#include uptr next_stack_addr(process_t *proc){ if (is_privileged(proc)) return 0; @@ -29,15 +30,20 @@ void unmap_stack(process_t *proc, stack_t stack){ stack_t new_stack(process_t *proc){ uptr stack_top = 0; + size_t size = 0; if (is_privileged(proc)) { - void *st = palloc(stack_max, MEM_PRIV_KERNEL, MEM_RW, true); - stack_top = (uptr)st + stack_max; - register_allocation(proc->alloc_map, st, stack_max); - } else stack_top = next_stack_addr(proc); + size = kstack_max; + void *st = palloc(size, MEM_PRIV_KERNEL, MEM_RW, true); + stack_top = (uptr)st + size; + register_allocation(proc->alloc_map, st, size); + } else { + stack_top = next_stack_addr(proc); + size = stack_max; + } if (!stack_top) return (stack_t){}; - uptr stack_limit = stack_top - stack_max; + uptr stack_limit = stack_top - size; print("New stack at %llx-%llx",stack_limit,stack_top); if (!is_privileged(proc) && !mm_add_vma(&proc->mm, stack_limit, stack_top, MEM_RW, VMA_KIND_STACK, VMA_FLAG_DEMAND)) return (stack_t){}; - return (stack_t){.top = stack_top, .size = stack_max, .max = stack_max}; + return (stack_t){.top = stack_top, .size = size, .max = size}; } \ No newline at end of file diff --git a/kernel/process/stack_manager.h b/kernel/process/stack_manager.h index 96e7883c..e6d8cd58 100644 --- a/kernel/process/stack_manager.h +++ b/kernel/process/stack_manager.h @@ -4,6 +4,7 @@ #include "process.h" #define stack_max 0x100000 +#define kstack_max 0x10000 #define stack_max_addr 0x7ffffffff000ULL #define stack_distance (stack_max + PAGE_SIZE) #define stack_min_addr 0x100000000000ULL diff --git a/user/launcher/main.c b/user/launcher/main.c index c6508c37..286aeda7 100644 --- a/user/launcher/main.c +++ b/user/launcher/main.c @@ -94,8 +94,7 @@ void load_entries(){ string_free(entry->info.author); } chunk_array_reset(entries); - traverse_directory("/home/applications", false, handle_entry); - traverse_directory("/boot/redos/system", false, handle_entry); + traverse_directory("/apps", false, handle_entry); } void draw_desktop(){ From ee3ed74701b77ed84b632cdc167f282a2bf6ad6c Mon Sep 17 00:00:00 2001 From: di Date: Tue, 18 Aug 2026 00:00:00 +0000 Subject: [PATCH 16/20] [SHARED] using diylib-compatible branch [ALLOC] remove some malloc/free_sized references --- kernel/process/debug.c | 2 +- kernel/tests/allocation/alloc_tests.c | 4 ++-- modules/audio/virt/audio.cpp | 2 +- shared | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/process/debug.c b/kernel/process/debug.c index bc0ce819..a47d6339 100644 --- a/kernel/process/debug.c +++ b/kernel/process/debug.c @@ -16,7 +16,7 @@ void debug_load(){ void *file = zalloc(fd.size); - kprintf("[DEBUG] Malloced %x",fd.size); + kprintf("[DEBUG] alloc'd %x",fd.size); readf(&fd, file, fd.size); closef(&fd); diff --git a/kernel/tests/allocation/alloc_tests.c b/kernel/tests/allocation/alloc_tests.c index fdbd86e0..f8e97087 100644 --- a/kernel/tests/allocation/alloc_tests.c +++ b/kernel/tests/allocation/alloc_tests.c @@ -102,9 +102,9 @@ bool test_kalloc_fragment_reuse() { } bool test_after_free(){ - uint64_t *a = malloc(64); + uint64_t *a = zalloc(64); a[3] = 12345678; - free_sized(a,64); + release(a); assert_eq(a[3], 0xDEADBEEFDEADBEEF, "Use after free failed: %x",a[3]); return true; } diff --git a/modules/audio/virt/audio.cpp b/modules/audio/virt/audio.cpp index 748a956a..00b26008 100644 --- a/modules/audio/virt/audio.cpp +++ b/modules/audio/virt/audio.cpp @@ -110,7 +110,7 @@ static inline void buffer_exhausted(mixer_line* line, sizedptr* inbuf){ break; case AUDIO_ONESHOT_FREE: inbuf->ptr = NULL; - free_sized((void*)line->source.ptr, line->source.size); + release((void*)line->source.ptr); mixer_reset_line(line - mixin); break; case AUDIO_LOOP: diff --git a/shared b/shared index 2200ae41..fb908857 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 2200ae4183c1a473e942aef791eb4b99cef6c1c5 +Subproject commit fb908857cc1ce843da10efc469d7eacf7b1a2c90 From 688eaad5b23ab56b396545ac24a90094590e01d1 Mon Sep 17 00:00:00 2001 From: di Date: Tue, 18 Aug 2026 00:00:00 +0000 Subject: [PATCH 17/20] [TERM] brought back c term [SHARED] init fixes --- kernel/utils/language_support/language.c | 1 + shared | 2 +- user/terminal/main.c | 357 ++++++++++++++++++++ user/terminal/main.cpp | 53 --- user/terminal/terminal.cpp | 400 ----------------------- user/terminal/terminal.hpp | 59 ---- 6 files changed, 359 insertions(+), 513 deletions(-) create mode 100644 user/terminal/main.c delete mode 100644 user/terminal/main.cpp delete mode 100644 user/terminal/terminal.cpp delete mode 100644 user/terminal/terminal.hpp diff --git a/kernel/utils/language_support/language.c b/kernel/utils/language_support/language.c index 69c6c0c2..42cf426a 100644 --- a/kernel/utils/language_support/language.c +++ b/kernel/utils/language_support/language.c @@ -1,5 +1,6 @@ #include "language.h" #include "files/vfs.h" +#include "draw/textdraw.h" #define DATA_SYNTAX DATA_SIGNATURE("CODESNTX") #define DATA_FORMAT DATA_SIGNATURE("CODEFMT") diff --git a/shared b/shared index fb908857..09c3d3b9 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit fb908857cc1ce843da10efc469d7eacf7b1a2c90 +Subproject commit 09c3d3b9decd497d6d6a9be53e3a3044e85dfdd8 diff --git a/user/terminal/main.c b/user/terminal/main.c new file mode 100644 index 00000000..4c24a9be --- /dev/null +++ b/user/terminal/main.c @@ -0,0 +1,357 @@ +#include "syscalls/syscalls.h" +#include "draw/textdraw.h" +#include "shell/shell.h" +#include "shell/sheldon/sheldon.h" +#include "environment/env_types.h" +#include "data/serialize/binary_serial.h" +#include "kbd_helper.h" +#include "memory/memory.h" +#include "utils/embedded_fmt/tcf.h" +#include "files/helpers.h" +#include "header_utils/screenprinter.h" +#include "header_utils/composite.h" +#include "files/system_module.h" +#include "files/stack_fs.h" + +embedded_fmt input_format = {}; + +#define INPUT_MARGIN 10 +#define INPUT_HEIGHT (line_height+(INPUT_MARGIN*2)) + +int history_ptr = 0; +int history_count = 0; + +bool headless = false; + +bool cursor_on = false; +u64 cursor_blink_time = 500; + +u32 bg_color; + +buffer input_buf = {}; + +draw_ctx ctx = {}; + +gpu_rect screen_rect = {}; + +shell_handle* main_shell; + +void flush(shell_handle *handle, bool can_scroll); + +static char log_buf[1024]; + +int debug_print(const char *fmt, ...){ + __attribute__((aligned(16))) va_list args; + va_start(args, fmt); + memset(log_buf, 0, 1024); + size_t n = string_format_va_buf(fmt, log_buf, sizeof(log_buf), args); + va_end(args); + if (n >= sizeof(log_buf)) log_buf[sizeof(log_buf)-1] = '\0'; + printl(log_buf); + return 0; +} + +shell_handle* make_default_shell(shell_bindings bindings){ + return create_sheldon(bindings, 0, 0); +} + +void clear(shell_handle *handle){ + if (main_shell && main_shell != handle) return; + // buffer_wipe(&contents); + fb_clear(&ctx, screen_printer_formatting.current_bg_color); +} + +bool return_from_parse = false; + +void put_char(shell_handle *handle, char c){ + // print("New char %c %x %x %i",c,handle,main_shell,contents.cursor); + if (!c || (main_shell && main_shell != handle)) return; + bool render = true; + if (embedded_fmt_parse(&screen_printer_formatting, c)){ + render = false; + return_from_parse = true; + if (screen_printer_formatting.wipe){ + screen_printer_formatting.wipe = false; + clear(handle); + return; + } + } + if (!render) + return; + if (headless) + serial_transmit(c); + else { + screen_printer_put_char(c); + if (return_from_parse) flush(handle, true); + return_from_parse = false; + } +} + +void flush(shell_handle *handle, bool can_scroll){ + // print("Flush %v {%i,%i}",slice_from_buffer(&contents),rerender_range.start,rerender_range.size); + if (main_shell && main_shell != handle) return; + + screen_print_flush(can_scroll); +} + +void refresh_input(){ + fb_fill_rect(&ctx, 0, ctx.height-INPUT_HEIGHT, ctx.width, INPUT_HEIGHT, input_format.current_bg_color); + gpu_size offset = fb_draw_slice(&ctx, SLICE("> "), 0, ctx.height-INPUT_HEIGHT+INPUT_MARGIN, TEXT_SCALE, input_format.current_text_color); + fb_draw_slice(&ctx, slice_from_buffer(&input_buf), offset.width, ctx.height-INPUT_HEIGHT+INPUT_MARGIN, TEXT_SCALE, input_format.current_text_color); + if (cursor_on) + fb_fill_rect(&ctx, offset.width + (char_width * input_buf.cursor), ctx.height-INPUT_HEIGHT+INPUT_MARGIN, char_width, INPUT_HEIGHT-(INPUT_MARGIN*2), input_format.current_text_color); + commit_draw_ctx(&ctx); +} + +void bell(shell_handle *handle){ + if (main_shell && main_shell != handle) return; + print("DING"); +} + +void ascii_cmd(shell_handle *handle, char cmd, u16 proc_id){ + if (main_shell && main_shell != handle) return; + switch (cmd){ + case ASCII_CMD_ETX: + send_signal(SIG_QUIT, proc_id); + break; + case ASCII_CMD_SUB: + send_signal(SIG_STOP, proc_id); + break; + case ASCII_CMD_CAN: + send_signal(SIG_CONT, proc_id); + break; + default: break; + } +} + +void console_ctrl(shell_handle *handle, console_ctrls ctrl){ + if (main_shell && main_shell != handle) return; + switch (ctrl) { + case console_ctrl_close: halt(0); + default: break; + } +} + +void emit_data(structdef field, sizedptr data, bool is_allocated){ + // if (main_shell && main_shell != handle) return; + print("[TERMINAL implementation error] structured data displaying not implemented"); + // if (!data.ptr || !data.size) return; + // switch (field.type) { + // case binary_type_i8: print("%S: %i",field.name,*(i8*)data.ptr); break; + // case binary_type_i16: print("%S: %i",field.name,*(i16*)data.ptr); break; + // case binary_type_i32: print("%S: %i",field.name,*(i32*)data.ptr); break; + // case binary_type_i64: print("%S: %i",field.name,*(i64*)data.ptr); break; + // case binary_type_float: print("%S: %f",field.name,*(float*)data.ptr); break; + // case binary_type_double: print("%S: %f",field.name,*(double*)data.ptr); break; + // case binary_type_string: print("%S: %v",field.name,data); break; + // default: return; + // } + // if (is_allocated) release((void*)data.ptr); +} + +void flush_proxy(shell_handle *handle){ + flush(handle, true); +} + +shell_bindings terminal_bindings = (shell_bindings){ + .console_output = put_char, + .console_flush = flush_proxy, + .console_clean = clear, + .console_bell = bell, + .console_ascii_cmd = ascii_cmd, + .console_control = console_ctrl +}; + +shell_handle* create_shell(){ + shell_handle *handle = make_default_shell(terminal_bindings); + if (!handle) return 0; + return handle; +} + +bool erase(bool forward){ + if (forward && input_buf.cursor >= input_buf.buffer_size) return false; + if (!buffer_delete(&input_buf, input_buf.cursor + forward, 1)) return false; + + refresh_input(); + return true; +} + +bool run_command(){ + + bool success = false; + + screen_printer_append("\r\n"); + + write_full_file("/termhistory", input_buf.buffer, input_buf.buffer_size); + history_count++; + history_ptr = history_count; + + if (run_cmd(main_shell, slice_from_buffer(&input_buf))) success = true; + + buffer_wipe(&input_buf); + return success; +} + +bool move_buf_cursor(i64 amount){ + if (!amount) return false; + uptr old_in_c = input_buf.cursor; + if (buffer_seek(&input_buf, amount, false) == old_in_c) return false; + refresh_input(); + return true; +} + +bool scroll_history(i64 amount){ + int new_history_ptr = history_ptr + amount; + if (new_history_ptr < 0) new_history_ptr = 0; + string file = string_format("/termhistory/%i",new_history_ptr); + fs_stat st = {}; + if (statf(file.data, &st)){ + size_t hist_size = 0; + char *history = read_full_file(file.data, &hist_size); + if (input_buf.buffer) buffer_destroy(&input_buf); + input_buf = (buffer){ + .buffer = history, + .buffer_size = hist_size, + .limit = hist_size, + .options = buffer_can_grow, + .cursor = hist_size + }; + history_ptr = new_history_ptr; + return true; + } + buffer_wipe(&input_buf); + return false; +} + +void handle_mouse(){ + mouse_data data = {}; + get_mouse_status(&data); + if (data.raw.scroll){ + screen_print_scroll(data.raw.scroll, false); + } +} + +bool handle_input(){ + + handle_mouse(); + + kbd_event event; + if (!read_event(&event)) return false; + if (event.type == KEY_RELEASE) return true; + if (handle_modifier(&event)) return true; + + char key = event.key; + char readable = hid_to_char((uint8_t)key, current_modifier, special_key); + + if (key == KEY_ENTER || key == KEY_KPENTER) return run_command(); + + if (key == KEY_BACKSPACE) return erase(false); + if (key == KEY_DELETE) return erase(true); + + if (key == KEY_UP) return scroll_history(-1); + if (key == KEY_DOWN) return scroll_history(1); + + if (key == KEY_LEFT) return move_buf_cursor(-1); + if (key == KEY_RIGHT) return move_buf_cursor(1); + + if (key == KEY_PAGEDOWN || key == KEY_PAGEUP) + screen_print_scroll(key == KEY_PAGEDOWN ? -1 : 1, false); + + if (!readable) return false; + + if (!input_buf.buffer) input_buf = buffer_create(0x100, buffer_can_grow); + + buffer_write_lim(&input_buf, &readable, 1); + refresh_input(); + + flush(main_shell, true); + + return true; + +} + +void toggle_cursor(){ + cursor_on = !cursor_on; + refresh_input(); +} + +bool quit = false; + +bool termhistory_init(system_module *mod){ + printl("Mounting mod"); + // while (true) printl("I'm told to quit %i"); + return true; +} + +bool custom_stat(const char *path, fs_stat *out_stat){ + print("Stat %s into %x",path, out_stat); + stat_dir(out_stat); + return true; +} + +size_t custom_readdir(const char *path, void *buf, size_t size, file_offset *offset){ + print("READDIR %s info %x (%i) (%x)",path,buf,size,offset); + fs_dir_list_helper helper = create_dir_list_helper(buf, size); + dir_list_fill(&helper, "test"); + return dir_buf_size(&helper); +} + +system_module termhistory_mod = { + .name = "terminal history", + .mount = "termhistory", + .version = VERSION_NUM(0, 1, 0, 0), + .open = stackfs_open, + .read = stackfs_read, + .write = stackfs_write, + .readdir = custom_readdir, + .getstat = custom_stat +}; + +int main(){ + request_app_ctx(&ctx); + + screen_printer_init(dummy_draw_ctx(ctx.width, ctx.height-INPUT_HEIGHT)); + + stackfs_init(); + load_fsmodule(&termhistory_mod, true); + + u32 color_buf[2] = {}; + sreadf("/theme", &color_buf, sizeof(uint64_t)); + if ((color_buf[0] & 0xFF000000) == 0) color_buf[0] |= 0xFF000000; + if ((color_buf[1] & 0xFF000000) == 0) color_buf[1] |= 0xFF000000; + screen_printer_formatting.default_bg_color = screen_printer_formatting.current_bg_color = color_buf[0]; + screen_printer_formatting.default_text_color = screen_printer_formatting.current_text_color = color_buf[1]; + + init_tcf(&screen_printer_formatting); + + memcpy(&input_format, &screen_printer_formatting, sizeof(text_format)); + + fb_clear(&ctx, screen_printer_formatting.current_bg_color); + + main_shell = create_shell(); + + current_shell = main_shell; + + u64 cursor_current = 0; + + u64 last_time = get_time(); + refresh_input(); + while (true){ + if (quit) halt(0); + // append("Bonjour %.3i \t",i++); + u64 current_time = get_time(); + cursor_current += (current_time-last_time); + if (cursor_current >= cursor_blink_time){ + toggle_cursor(); + cursor_current = 0; + } + last_time = current_time; + handle_input(); + msleep(1); + ctx.full_redraw = true; + composite(&printer_ctx, (int_point){}, 1, &ctx, draw_ctx_rect(&ctx)); + commit_draw_ctx(&ctx); + } + + return 0; +} \ No newline at end of file diff --git a/user/terminal/main.cpp b/user/terminal/main.cpp deleted file mode 100644 index f7c04074..00000000 --- a/user/terminal/main.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "terminal.hpp" -#include "string/string.h" - -Terminal *term; - -int main(int argc, char **argv){ - term = new Terminal(); - if (argc && strncmp_case(argv[0], "headless", true, 8) == 0){ - print("Terminal in headless mode"); - term->headless = true; - } - while (1){ - term->update(); - } -} - -void term_put_char(shell_handle *handle, char c){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - if (term->headless && c) - serial_transmit(c); - else - term->put_char(c); -} - -void term_clear(shell_handle *handle){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - term->clear(); -} - -void term_flush(shell_handle *handle){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - term->refresh(); -} - -void term_bell(shell_handle *handle){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - term->bell(); -} - -void term_ascii_cmd(shell_handle *handle, char cmd, u16 proc_id){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - term->interpret_cmd_code(cmd, proc_id); -} - -void term_console_ctrl(shell_handle *handle, console_ctrls ctrl){ - if (!term || (term->term_current_shell && term->term_current_shell != handle)) return; - term->ctrl(ctrl); -} - -void term_emit_data(structdef field, sizedptr data, bool is_allocated){ - if (!term) return; - term->emit_data(field,data,is_allocated); -} \ No newline at end of file diff --git a/user/terminal/terminal.cpp b/user/terminal/terminal.cpp deleted file mode 100644 index af67631c..00000000 --- a/user/terminal/terminal.cpp +++ /dev/null @@ -1,400 +0,0 @@ -#include "terminal.hpp" -#include "alloc/allocate.h" -#include "memory/memory.h" -#include "input_keycodes.h" -#include "shell/sheldon/sheldon.h" -#include "data/serialize/binary_serial.h" -#include "utils/embedded_fmt/tcf.h" - -Terminal::Terminal() : Console() { - uint32_t color_buf[2] = {}; - sreadf("/theme", &color_buf, sizeof(uint64_t)); - if ((color_buf[0] & 0xFF000000) == 0) color_buf[0] |= 0xFF000000; - current_format.default_bg_color = color_buf[0]; - current_format.current_bg_color = color_buf[0]; - current_format.default_text_color = color_buf[1]; - - char_scale = 2; - prompt_length = 2; - command_running = false; - - input_len = 0; - input_cursor = 0; - input_buf[0] = 0; - - history_len = 0; - history_index = 0; - for (uint32_t i = 0; i < history_max; i++) history[i] = nullptr; - - last_blink_ms = get_time(); - cursor_visible = true; - - dirty = false; - - term_current_shell = create_shell(); - init_tcf(¤t_format); - put_string("> "); - redraw_input_line(); - if (dirty) { - flush(dctx); - dirty = false; - } -} - -extern void term_put_char(shell_handle *handle, char c); -extern void term_clear(shell_handle *handle); -extern void term_flush(shell_handle *handle); -extern void term_bell(shell_handle *handle); -extern void term_ascii_cmd(shell_handle *handle, char cmd, u16 proc_id); -extern void term_console_ctrl(shell_handle *handle, console_ctrls ctrl); - -shell_handle* Terminal::create_shell(){ - shell_bindings terminal_bindings = (shell_bindings){ - .console_output = term_put_char, - .console_flush = term_flush, - .console_clean = term_clear, - .console_bell = term_bell, - .console_ascii_cmd = term_ascii_cmd, - .console_control = term_console_ctrl - }; - return create_sheldon(terminal_bindings, 0, 0); -} - -void Terminal::ctrl(console_ctrls ctrl){ - switch (ctrl) { - case console_ctrl_close: halt(0); - default: break; - } -} - -void Terminal::update(){ - if (!command_running) { - bool did = handle_input(); - if (!did) cursor_tick(); - } else { - end_command(); - } - - if (dirty) { - flush(dctx); - dirty = false; - } -} - -void Terminal::cursor_set_visible(bool visible){ - if (visible == cursor_visible) { - if (!visible) return; - if (last_drawn_cursor_x == (int32_t)current_format.cursor_x && last_drawn_cursor_y == (int32_t)current_format.cursor_y) return; - } - - cursor_visible = visible; - - if (last_drawn_cursor_x >= 0 && last_drawn_cursor_y >= 0) { - if ((uint32_t)last_drawn_cursor_x < columns && (uint32_t)last_drawn_cursor_y < rows) { - char *prev_line = &row_data[((scroll_row_offset + (u32)last_drawn_cursor_y) % rows) * columns]; - render_glyph(last_drawn_cursor_x*char_width, last_drawn_cursor_y * line_height, prev_line[last_drawn_cursor_x], current_format.current_text_color, current_format.current_bg_color, true); - } - last_drawn_cursor_x = -1; - last_drawn_cursor_y = -1; - } - - if (cursor_visible) { - fb_fill_rect(dctx, current_format.cursor_x * char_width, current_format.cursor_y * line_height, char_width, line_height, 0xFFFFFFFF); - last_drawn_cursor_x = (int32_t)current_format.cursor_x; - last_drawn_cursor_y = (int32_t)current_format.cursor_y; - } - - dirty = true; -} - -void Terminal::cursor_tick(){ - uint64_t now = get_time(); - if ((now - last_blink_ms) < 500) return; - last_blink_ms = now; - cursor_set_visible(!cursor_visible); -} - -void Terminal::redraw_input_line(){ - if (!check_ready()) return; - - uint32_t cw = (uint32_t)char_scale * CHAR_SIZE; - uint32_t lh = (uint32_t)char_scale * CHAR_SIZE * 2; - - fb_fill_rect(dctx, 0, current_format.cursor_y * lh, columns * cw, lh, current_format.current_bg_color); - - char* line = row_data + (((scroll_row_offset + current_format.cursor_y) % rows) * columns); - memset(line, 0, columns); - - if (columns == 0) return; - if (prompt_length >= (int)columns) return; - - line[0] = '>'; - line[1] = ' '; - - uint32_t max_input = columns - (uint32_t)prompt_length - 1; - uint32_t draw_len = input_len; - if (draw_len > max_input) draw_len = max_input; - - for (uint32_t i = 0; i < draw_len; i++) line[prompt_length + i] = input_buf[i]; - line[prompt_length + draw_len] = 0; - - uint32_t ypix = (current_format.cursor_y * lh) + (lh / 2); - fb_draw_char(dctx, 0, ypix, '>', char_scale, current_format.current_text_color); - fb_draw_char(dctx, cw, ypix, ' ', char_scale, current_format.current_text_color); - for (uint32_t i = 0; i < draw_len; i++) fb_draw_char(dctx, (prompt_length + i) * cw, ypix, input_buf[i], char_scale, current_format.current_text_color); - - if (input_cursor > draw_len) input_cursor = draw_len; - current_format.cursor_x = (uint32_t)prompt_length + input_cursor; - - last_blink_ms = get_time(); - cursor_set_visible(true); -} - -void Terminal::set_input_line(const char *s){ - input_len = 0; - input_cursor = 0; - - if (s) { - uint32_t i = 0; - while (s[i] && (i + 1) < input_max) { - input_buf[i] = s[i]; - i++; - } - input_len = i; - } - - input_buf[input_len] = 0; - input_cursor = input_len; - redraw_input_line(); -} - -void Terminal::end_command(){ - command_running = false; - if (last_char != '\r' && last_char != '\n'){ - put_char('\r'); - put_char('\n'); - } - put_string("> "); - prompt_length = 2; - - set_input_line(""); -} - -void Terminal::emit_data(structdef field, sizedptr data, bool is_allocated){ - if (!data.ptr || !data.size) return; - switch (field.type) { - case binary_type_i8: print("%S: %i",field.name,*(i8*)data.ptr); break; - case binary_type_i16: print("%S: %i",field.name,*(i16*)data.ptr); break; - case binary_type_i32: print("%S: %i",field.name,*(i32*)data.ptr); break; - case binary_type_i64: print("%S: %i",field.name,*(i64*)data.ptr); break; - case binary_type_float: print("%S: %f",field.name,*(float*)data.ptr); break; - case binary_type_double: print("%S: %f",field.name,*(double*)data.ptr); break; - case binary_type_string: print("%S: %v",field.name,data); break; - default: return; - } - if (is_allocated) release((void*)data.ptr); -} - -bool Terminal::exec_cmd(const char *cmd){ - if (!term_current_shell) return false; - - current_shell = term_current_shell; - - if (run_cmd(current_shell, slice_from_literal(cmd))) return true; - - return true; -} - -void Terminal::bell(){ - put_string("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); - refresh(); -} - -void Terminal::run_command(){ - if (input_len) { - if (history_len == history_max) { - if (history[0]) release(history[0]); - for (uint32_t i = 1; i < history_max; i++) history[i - 1] = history[i]; - history_len = history_max - 1; - } - - uint32_t n = input_len; - char *copy = (char*)zalloc(n + 1); - if (copy) { - memcpy(copy, input_buf, n); - copy[n] = 0; - history[history_len++] = copy; - } - } - history_index = history_len; - - put_char('\r'); - put_char('\n'); - - const char* fullcmd = input_buf; - while (*fullcmd == ' ' || *fullcmd == '\t') fullcmd++; - - if (*fullcmd == 0) { - command_running = true; - return; - } - - if (!exec_cmd(fullcmd)){ - const char *next = seek_to(fullcmd, ' '); - size_t len = next - fullcmd - (next && *(next-1) == ' ' ? 1 : 0); - string_slice cmd = (string_slice){ .data = (char*)fullcmd, .length = len }; - if (slice_lit_match(cmd, "exit", true) || slice_lit_match(cmd, "q", true)){ - halt(0); - } else { - string s = string_format("Unknown command %v", cmd); - put_string(s.data); - string_free(s); - } - } - - command_running = true; -} - -bool Terminal::interpret_cmd_code(char code, u16 proc){ - if (code == ASCII_CMD_ETX){ - send_signal(SIG_QUIT, proc); - return true; - } - if (code == ASCII_CMD_SUB){ - send_signal(SIG_STOP, proc); - return true; - } - if (code == ASCII_CMD_CAN){ - send_signal(SIG_CONT, proc); - } - return false; -} - -bool Terminal::handle_input(){ - kbd_event event; - if (!read_event(&event)) return false; - if (event.type == KEY_RELEASE) return true; - if (event.type != KEY_PRESS) return handle_modifier(&event); - - char key = event.key; - char readable = hid_to_char((uint8_t)key, current_modifier, special_key); - - if (command_running){ - return interpret_cmd_code(readable, 0); - } - - if (key == KEY_ENTER || key == KEY_KPENTER){ - run_command(); - return true; - } - - if (key == KEY_LEFT) { - if (input_cursor) input_cursor--; - current_format.cursor_x = (uint32_t)prompt_length + input_cursor; - last_blink_ms = get_time(); - cursor_set_visible(true); - return true; - } - - if (key == KEY_RIGHT) { - if (input_cursor < input_len) input_cursor++; - current_format.cursor_x = (uint32_t)prompt_length + input_cursor; - last_blink_ms = get_time(); - cursor_set_visible(true); - return true; - } - - if (key == KEY_UP) { - if (history_len && history_index) { - history_index--; - set_input_line(history[history_index]); - } - return true; - } - - if (key == KEY_DOWN) { - if (history_len) { - if (history_index + 1 < history_len) { - history_index++; - set_input_line(history[history_index]); - } else { - history_index = history_len; - set_input_line(""); - } - } - return true; - } - - if (key == KEY_BACKSPACE){ - if (!input_cursor) return true; - for (uint32_t i = input_cursor; i < input_len; i++) input_buf[i - 1] = input_buf[i]; - input_len--; - input_cursor--; - input_buf[input_len] = 0; - redraw_input_line(); - return true; - } - - if (key == KEY_DELETE) { - if (input_cursor >= input_len) return true; - for (uint32_t i = input_cursor + 1; i <= input_len; i++) input_buf[i - 1] = input_buf[i]; - input_len--; - redraw_input_line(); - return true; - } - - if (!readable) return true; - - uint32_t max_visible = 0; - if (columns > (uint32_t)prompt_length + 1) max_visible = columns - (uint32_t)prompt_length - 1; - if (input_len >= input_max - 1) return true; - if (max_visible && input_len >= max_visible) return true; - - for (uint32_t i = input_len; i > input_cursor; i--) input_buf[i] = input_buf[i - 1]; - input_buf[input_cursor] = readable; - input_len++; - input_cursor++; - input_buf[input_len] = 0; - redraw_input_line(); - return true; -} - -draw_ctx* Terminal::get_ctx(){ - if (dctx) release(dctx); - draw_ctx *ctx = (draw_ctx*)zalloc(sizeof(draw_ctx)); - if (!ctx) return nullptr; - request_draw_ctx(ctx); - return ctx; -} - -void Terminal::put_char(char c){ - if (headless){ - serial_transmit(c); - return; - } - Console::put_char(c); -} - -void Terminal::put_slice(string_slice slice){ - if (!check_ready()) return; - for (u32 i = 0; i < slice.length; i++) Terminal::put_char(slice.data[i]); - flush(dctx); -} - -void Terminal::put_string(const char* str){ - Terminal::put_slice(slice_from_literal(str)); -} - -void Terminal::flush(draw_ctx *ctx){ - if (headless) return; - commit_draw_ctx(ctx); -} - -void Terminal::refresh(){ - if (headless) return; - flush(dctx); -} - -bool Terminal::screen_ready(){ - return !headless; -} \ No newline at end of file diff --git a/user/terminal/terminal.hpp b/user/terminal/terminal.hpp deleted file mode 100644 index a0f6cd86..00000000 --- a/user/terminal/terminal.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include "utils/console.hpp" -#include "shell/shell.h" -#include "kbd_helper.h" -#include "environment/env_types.h" -#include "data/serialize/binary_serial.h" - -class Terminal: public Console { -public: - Terminal(); - void update(); - shell_handle *term_current_shell; - void emit_data(structdef, sizedptr, bool); - void refresh(); - void bell(); - bool interpret_cmd_code(char code, u16 proc); - void ctrl(console_ctrls ctrl); - void put_char(char c) override; - void put_string(const char* str) override; - void put_slice(string_slice slice) override; - bool headless; -protected: - bool handle_input(); - void repeat_tick(); - void end_command(); - int prompt_length; - void run_command(); - - void redraw_input_line(); - void set_input_line(const char *s); - void cursor_tick(); - void cursor_set_visible(bool visible); - - bool exec_cmd(const char *cmd); - - draw_ctx* get_ctx() override; - void flush(draw_ctx *ctx) override; - bool screen_ready() override; - - shell_handle* create_shell(); - - bool command_running; - - static constexpr uint32_t input_max = 1024; - char input_buf[input_max]; - uint32_t input_len; - uint32_t input_cursor; - - static constexpr uint32_t history_max = 32; - char *history[history_max]; - uint32_t history_len; - uint32_t history_index; - - uint64_t last_blink_ms; - bool cursor_visible; - - bool dirty; -}; \ No newline at end of file From bfb4687af7b626425ed03a83c366e44367cc75e0 Mon Sep 17 00:00:00 2001 From: di Date: Tue, 18 Aug 2026 00:00:00 +0000 Subject: [PATCH 18/20] [JOB] per-page buffer copying on fulfill --- kernel/process/jobs/job_manager.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/kernel/process/jobs/job_manager.c b/kernel/process/jobs/job_manager.c index 5f80ec76..7c4177c2 100644 --- a/kernel/process/jobs/job_manager.c +++ b/kernel/process/jobs/job_manager.c @@ -180,15 +180,26 @@ void fulfill_job(job_id_t job_id, u64 ret, thread_t *thread){ job_buffer buf = st->buffers[i]; if (buf.sync & copy_on_end && buf.worker_ptr.ptr){ job_print("[JOB debug] Copy buffer %llx into %llx",buf.worker_ptr.ptr,buf.orig_ptr.ptr); - void* addr = quick_translate(st->requester, proc, buf.orig_ptr.ptr); - if (!addr){ - if (buf.orig_ptr.ptr & HIGH_VA){ - int stb = 0; - addr = (void*)PHYS_TO_VIRT(mmu_translate(st->requester->special_mm, buf.orig_ptr.ptr, &stb)); + size_t size = buf.orig_ptr.size; + uptr src = buf.worker_ptr.ptr; + for (uptr page = buf.orig_ptr.ptr; page < buf.orig_ptr.ptr + buf.orig_ptr.size; page += PAGE_SIZE){ + job_print("[JOB debug] doing translation for %llx",page); + void* addr = quick_translate(st->requester, proc, page); + if (!addr){ + if (page & HIGH_VA){ + int stb = 0; + addr = (void*)PHYS_TO_VIRT(mmu_translate(st->requester->special_mm, page, &stb)); + } } + if (!addr){ + print("[JOB error] failed to translate destination va %llx",page); + continue; + } + size_t amount = size > PAGE_SIZE ? PAGE_SIZE : size; + memcpy(addr, (void*)src, amount); + src += amount; + size -= amount; } - if (!addr) continue; - memcpy(addr, (void*)buf.worker_ptr.ptr, buf.worker_ptr.size); } } job_print("[JOB] %i fulfilled by %i with return value %llx",job_id,thread->tid,thread->regs[0]); From 4220fe48b640137ce6ddf0036dabcc9d8c4faa50 Mon Sep 17 00:00:00 2001 From: di Date: Tue, 18 Aug 2026 00:00:00 +0000 Subject: [PATCH 19/20] [PROJ] moved shared back to main --- shared | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared b/shared index 09c3d3b9..97aa7618 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 09c3d3b9decd497d6d6a9be53e3a3044e85dfdd8 +Subproject commit 97aa7618066578a6595e65d65bbfa2e9640f3df4 From 0e12de3dd467b26a3ffd5c437dfb5027b1763b17 Mon Sep 17 00:00:00 2001 From: di Date: Sat, 29 Aug 2026 00:00:00 +0000 Subject: [PATCH 20/20] [SHARED] compatibility with new rendering and draw lib refactoring --- kernel/graph/graphics.h | 2 +- kernel/graph/tres.h | 2 +- kernel/kernel_processes/windows/dos.c | 4 ++-- kernel/tools/monitor_processes.c | 2 +- kernel/utils/cursor/cursor_manager.c | 1 + modules/graph/common/gpu_driver.hpp | 2 +- modules/graph/raspi/videocore.cpp | 2 +- modules/graph/virt/ramfb.cpp | 2 +- modules/graph/virt/virtio_gpu_pci.cpp | 2 +- shared | 2 +- 10 files changed, 11 insertions(+), 10 deletions(-) diff --git a/kernel/graph/graphics.h b/kernel/graph/graphics.h index 7143c6c3..c2e0893f 100644 --- a/kernel/graph/graphics.h +++ b/kernel/graph/graphics.h @@ -7,7 +7,7 @@ extern "C" { #include "types.h" #include "graphic_types.h" #include "std/string.h" -#include "ui/draw/draw.h" +#include "draw/draw.h" #include "files/system_module.h" bool gpu_ready(); diff --git a/kernel/graph/tres.h b/kernel/graph/tres.h index e1c37088..4d1a01b2 100644 --- a/kernel/graph/tres.h +++ b/kernel/graph/tres.h @@ -1,7 +1,7 @@ #pragma once #include "types.h" -#include "ui/draw/draw.h" +#include "draw/draw.h" #include "data/struct/linked_list.h" #include "process/process.h" diff --git a/kernel/kernel_processes/windows/dos.c b/kernel/kernel_processes/windows/dos.c index 6f02633f..8af22b13 100644 --- a/kernel/kernel_processes/windows/dos.c +++ b/kernel/kernel_processes/windows/dos.c @@ -45,11 +45,11 @@ static void draw_solid_window(window_frame *frame, draw_ctx *ctx, int_point fixe DRAW(rectangle(ctx, (rect_ui_config){ .border_size = BORDER_SIZE, - .border_color = saturate(system_theme.bg_color + 0x222222, focused ? 0 : -90), + .border_color = saturate_color(system_theme.bg_color + 0x222222, focused ? 0 : -90), }, (common_ui_config){ .point = fixed_point, .size = fixed_size, - .background_color = saturate(system_theme.bg_color + 0x111111, focused ? 0 : -90), + .background_color = saturate_color(system_theme.bg_color + 0x111111, focused ? 0 : -90), .foreground_color = COLOR_WHITE, }), { label(ctx, (text_ui_config){ diff --git a/kernel/tools/monitor_processes.c b/kernel/tools/monitor_processes.c index 24dee29a..7c7e73f1 100644 --- a/kernel/tools/monitor_processes.c +++ b/kernel/tools/monitor_processes.c @@ -5,7 +5,7 @@ #include "input_keycodes.h" #include "syscalls/syscalls.h" #include "input/input_dispatch.h" -#include "ui/draw/draw.h" +#include "draw/draw.h" #include "std/string.h" #include "theme/theme.h" #include "memory/addr.h" diff --git a/kernel/utils/cursor/cursor_manager.c b/kernel/utils/cursor/cursor_manager.c index 179d68e1..939f8cb7 100644 --- a/kernel/utils/cursor/cursor_manager.c +++ b/kernel/utils/cursor/cursor_manager.c @@ -2,6 +2,7 @@ #include "syscalls/syscalls.h" #include "files/helpers.h" #include "image/bmp.h" +#include "draw/draw.h" draw_ctx current_cursor; cursor_types current_cursor_type; diff --git a/modules/graph/common/gpu_driver.hpp b/modules/graph/common/gpu_driver.hpp index 73a37da3..2720d5a9 100644 --- a/modules/graph/common/gpu_driver.hpp +++ b/modules/graph/common/gpu_driver.hpp @@ -3,7 +3,7 @@ #include "types.h" #include "std/string.h" #include "graphic_types.h" -#include "ui/draw/draw.h" +#include "draw/draw.h" #define bpp 4 diff --git a/modules/graph/raspi/videocore.cpp b/modules/graph/raspi/videocore.cpp index 27b35e35..ddded7fc 100644 --- a/modules/graph/raspi/videocore.cpp +++ b/modules/graph/raspi/videocore.cpp @@ -2,7 +2,7 @@ #include "fw/fw_cfg.h" #include "memory/talloc.h" #include "console/kio.h" -#include "ui/draw/draw.h" +#include "draw/draw.h" #include "std/memory_access.h" #include "std/std.h" #include "std/memory.h" diff --git a/modules/graph/virt/ramfb.cpp b/modules/graph/virt/ramfb.cpp index 1bda5887..906efd09 100644 --- a/modules/graph/virt/ramfb.cpp +++ b/modules/graph/virt/ramfb.cpp @@ -1,6 +1,6 @@ #include "ramfb.hpp" #include "console/kio.h" -#include "ui/draw/draw.h" +#include "draw/draw.h" #include "std/memory_access.h" #include "std/std.h" #include "std/memory.h" diff --git a/modules/graph/virt/virtio_gpu_pci.cpp b/modules/graph/virt/virtio_gpu_pci.cpp index 77ec8429..6499cc4f 100644 --- a/modules/graph/virt/virtio_gpu_pci.cpp +++ b/modules/graph/virt/virtio_gpu_pci.cpp @@ -1,7 +1,7 @@ #include "virtio_gpu_pci.hpp" #include "pci.h" #include "console/kio.h" -#include "ui/draw/draw.h" +#include "draw/draw.h" #include "std/std.h" #include "theme/theme.h" #include "memory/page_allocator.h" diff --git a/shared b/shared index 97aa7618..9edc26d0 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 97aa7618066578a6595e65d65bbfa2e9640f3df4 +Subproject commit 9edc26d05e937f871ac06f18ece23b47862e37e1