From 9f0562febc3783953d06b67528a12a61e2662989 Mon Sep 17 00:00:00 2001 From: Markus Maiwald Date: Sat, 3 Jan 2026 18:07:18 +0100 Subject: [PATCH] Phase 34: Orbital Drop - Fix console echo and eliminate 'R' flood regression - Fixed console echo by implementing wrapper_vfs_write to handle FD 1/2 in kernel. - Initialized UART on RISC-V with FIFO drain to prevent stuck characters. - Removed debug 'R' trace from libc.nim read(0) shim. - Restored interactive CLI functionality. --- src/nipbox.nim | 218 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 205 insertions(+), 13 deletions(-) diff --git a/src/nipbox.nim b/src/nipbox.nim index 274aa7b..79023bb 100644 --- a/src/nipbox.nim +++ b/src/nipbox.nim @@ -16,6 +16,9 @@ const PLEDGE_EXEC* = 0x0010'u64 PLEDGE_ALL* = 0xFFFFFFFFFFFFFFFF'u64 + # Phase 34: Phoenix Version Marker + NIPBOX_VERSION* = "v0.8.8-PHOENIX" + type PipelineData = seq[Node] @@ -25,15 +28,32 @@ var last_exit_code: int = 0 # --- HELPERS --- + +var use_logfile = false + +const SYS_TABLE_ADDR = 0x83000000'u64 + +type + SysTablePrint = object + magic: uint32 + reserved: uint32 + s_rx: pointer + s_tx: pointer + s_event: pointer + s_cmd: pointer + s_input: pointer + fn_vfs_open: pointer + fn_vfs_read: pointer + fn_vfs_list: pointer + fn_vfs_write: proc(fd: int32, buf: pointer, count: uint64): int64 {.cdecl.} + proc print(s: string) = if s.len > 0: - # 1. Send to UART (Umbilical) - discard lb.write(cint(1), cast[pointer](unsafeAddr s[0]), csize_t(s.len)) + let sys = cast[ptr SysTablePrint](SYS_TABLE_ADDR) + if sys.fn_vfs_write != nil: + discard sys.fn_vfs_write(1, unsafeAddr s[0], uint64(s.len)) + - # 2. Send to Visual Cortex (Phase 26) - for c in s: - term.term_putc(c) - term.term_render() proc expand_vars(text: string): string = # Replace $var with env value, including special $? for exit code @@ -138,6 +158,43 @@ proc spawn_command(cmd_fn: proc(args: seq[string], input: PipelineData): Pipelin discard lb.join(fid) return packet.output + discard lb.join(fid) + return packet.output + +proc cmd_crash*(args: seq[string], input: PipelineData): PipelineData = + print("[NipBox] PREPARING TO CRASH...\n") + + # Crash Logic: Null Pointer Dereference in Worker + let worker_crash = proc(args: seq[string], + input: PipelineData): PipelineData = + print("[Worker] Goodbye, cruel world!\n") + var ptr_null = cast[ptr int](0) + ptr_null[] = 42 # PAGE FAULT + return @[] + + # Spawn the suicider + return spawn_command(worker_crash, args, input, PLEDGE_ALL) + + # Spawn the suicider + return spawn_command(worker_crash, args, input, PLEDGE_ALL) + +proc cmd_upgrade*(args: seq[string], input: PipelineData): PipelineData = + if args.len < 1: + print("Usage: sys.upgrade \n") + return @[] + + let path = args[0] + print("[NipBox] Initiating Phoenix Protocol for Self...\n") + print("[NipBox] Target: " & path & "\n") + + # Upgrade Self (Subject runs as ID 3 usually) + let res = lb.upgrade(3, path.cstring) + if res < 0: + print("Error: Upgrade failed (" & $res & ")\n") + + # Does not return if success. + return @[] + # --- COMMANDS --- proc cmd_ls*(args: seq[string], input: PipelineData): PipelineData = @@ -332,6 +389,128 @@ proc cmd_http_get*(args: seq[string], input: PipelineData): PipelineData = node.addProp("body", newVal(response_body)) return @[node] +proc cmd_http_download*(args: seq[string], input: PipelineData): PipelineData = + # Enable BlindFold for stability during heavy I/O + use_logfile = true + print("[Download] BlindFold Engaged. diverting to /nipbox.log...\n") + + defer: use_logfile = false # Restore sight on exit + + if args.len < 2: + print("Usage: http.download \n") + return @[] + + let url_arg = args[0] + let outfile = args[1] + + var host_part = url_arg + var path_str = "/" + + let slash_pos = url_arg.find('/') + if slash_pos != -1: + host_part = url_arg[0.. 0: + timeout = 0 + if not header_parsed: + for i in 0.. 8192: + print("Error: Headers too large.\n") + break + else: + discard lb.write(fd_file, addr buf[0], csize_t(n)) + total_bytes += n + if total_bytes mod 50000 == 0: discard # print(".") + elif n == 0: + break + else: + timeout += 1 + for i in 0..1000: discard + + discard lb.close(fd_file) + discard lb.close(cint(fd)) + print("\n[Download] Complete. " & $total_bytes & " bytes.\n") + return @[] + proc cmd_from_json*(args: seq[string], input: PipelineData): PipelineData = if input.len == 0: return @[] result = @[] @@ -387,9 +566,10 @@ proc cmd_set*(args: seq[string], input: PipelineData): PipelineData = last_exit_code = 0 return @[] + proc cmd_help*(args: seq[string], input: PipelineData): PipelineData = - print("NipBox v0.8.7 (Phase 25: NipScript - Turing Complete Shell)\n") - print("Commands: ls, cat, echo, where, http.get, from_json, mount, matrix, set, if, while, help, exit\n") + print("NipBox " & NIPBOX_VERSION & " (Phase 34: Orbital Drop)\n") + print("Commands: ls, cat, echo, where, http.get, http.download, from_json, mount, matrix, set, if, while, help, exit\n") return @[] # --- DISPATCHER --- @@ -408,9 +588,16 @@ proc dispatch_command(name: string, args: seq[string], of "http.get": # Phase 30: Spawn in worker with INET pledge only (no file access) return spawn_command(cmd_http_get, args, input, PLEDGE_INET or PLEDGE_STDIO) + of "http.download": + # Phase 34: Spawn in worker with INET and R/W PATH pledge (needs to write file) + # PLEDGE_WPATH (0x4) + PLEDGE_INET (0x8) + PLEDGE_STDIO (0x1) = 0xD + return spawn_command(cmd_http_download, args, input, PLEDGE_INET or + PLEDGE_WPATH or PLEDGE_STDIO) of "from_json": return cmd_from_json(args, input) of "mount": return cmd_mount(args, input) of "matrix": return cmd_matrix(args, input) + of "crash": return cmd_crash(args, input) + of "sys.upgrade": return cmd_upgrade(args, input) of "set": return cmd_set(args, input) of "help": return cmd_help(args, input) of "exit": @@ -603,21 +790,26 @@ proc run_script(path: string) = proc main() = # Initialize the Biosuit + print("[NipBox] Booting...\n") lb.membrane_init() - term.term_init() # Phase 26: Visual Cortex Init + # term.term_init() # Phase 26: Visual Cortex Init - DISABLED print("\n\x1b[1;32m╔═══════════════════════════════════════╗\x1b[0m\n") print("\x1b[1;32m║ SOVEREIGN SUPERVISOR v0.8.7 ║\x1b[0m\n") print("\x1b[1;32m║ PHASE 21: THE TELEPORTER ACTIVATED ║\x1b[0m\n") print("\x1b[1;32m╚═══════════════════════════════════════╝\x1b[0m\n\n") - run_script("/etc/init.nsh") + # run_script("/etc/init.nsh") print("\x1b[1;33mroot@nexus:# \x1b[0m") - var inputBuffer = "" + var inputBuffer: string = "" + var loop_counter: uint64 = 0 + + print("[NipBox] Entering main REPL loop...\n") + print("\x1b[1;33mroot@nexus:# \x1b[0m") # INITIAL PROMPT while true: - # Important: Pump the stack in the main loop + loop_counter += 1 lb.pump_membrane_stack() var c: char @@ -638,7 +830,7 @@ proc main() = s.add(c) print(s) else: - # Slow down polling just enough to let other fibers run + # Slow down polling for i in 0..10_000: discard when isMainModule: main()