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.
This commit is contained in:
parent
ccaa10c509
commit
4e0e9ed467
195
core/kernel.nim
195
core/kernel.nim
|
|
@ -13,6 +13,42 @@ var ion_paused*: bool = false
|
||||||
var pause_start*: uint64 = 0
|
var pause_start*: uint64 = 0
|
||||||
var matrix_enabled*: bool = false
|
var matrix_enabled*: bool = false
|
||||||
|
|
||||||
|
# --- CORE LOGGING ---
|
||||||
|
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
|
||||||
|
proc kwrite*(p: pointer, len: csize_t) {.exportc, cdecl.} =
|
||||||
|
if p != nil and len > 0:
|
||||||
|
console_write(p, len)
|
||||||
|
|
||||||
|
proc kprint*(s: cstring) {.exportc, cdecl.} =
|
||||||
|
if s != nil:
|
||||||
|
let length = len(s)
|
||||||
|
if length > 0:
|
||||||
|
kwrite(cast[pointer](s), csize_t(length))
|
||||||
|
|
||||||
|
proc kprint_hex*(n: uint64) {.exportc, cdecl.} =
|
||||||
|
const hex_chars = "0123456789ABCDEF"
|
||||||
|
var buf: array[18, char]
|
||||||
|
buf[0] = '0'
|
||||||
|
buf[1] = 'x'
|
||||||
|
for i in 0..15:
|
||||||
|
let nibble = (n shr (60 - (i * 4))) and 0xF
|
||||||
|
buf[i+2] = hex_chars[nibble]
|
||||||
|
console_write(addr buf[0], 18)
|
||||||
|
|
||||||
|
proc kprintln*(s: cstring) {.exportc, cdecl.} =
|
||||||
|
kprint(s); kprint("\n")
|
||||||
|
|
||||||
|
proc write*(fd: cint, p: pointer, len: csize_t): csize_t {.exportc, cdecl.} =
|
||||||
|
console_write(p, len)
|
||||||
|
return len
|
||||||
|
|
||||||
|
|
||||||
|
# Wrapper for VFS write to handle stdout/stderr
|
||||||
|
proc wrapper_vfs_write(fd: int32, buf: pointer, count: uint64): int64 {.cdecl.} =
|
||||||
|
if fd == 1 or fd == 2:
|
||||||
|
console_write(buf, csize_t(count))
|
||||||
|
return int64(count)
|
||||||
|
return ion_vfs_write(fd, buf, count)
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
# Fiber Management (Forward Declared)
|
# Fiber Management (Forward Declared)
|
||||||
|
|
@ -36,13 +72,19 @@ var subject_loading_path: string = "bin/nipbox"
|
||||||
proc subject_fiber_entry() {.cdecl.} =
|
proc subject_fiber_entry() {.cdecl.} =
|
||||||
## The Sovereign Container for Userland Consciousness.
|
## The Sovereign Container for Userland Consciousness.
|
||||||
## This loop persists across program reloads.
|
## This loop persists across program reloads.
|
||||||
|
kprintln("[Subject] Fiber Entry reached.")
|
||||||
while true:
|
while true:
|
||||||
|
kprint("[Subject] Attempting to load: ")
|
||||||
|
kprintln(cstring(subject_loading_path))
|
||||||
let entry = kload(subject_loading_path)
|
let entry = kload(subject_loading_path)
|
||||||
if entry != 0:
|
if entry != 0:
|
||||||
kprintln("[Subject] Consciousness Transferred.")
|
kprintln("[Subject] Consciousness Transferred.")
|
||||||
rumpk_enter_userland(entry)
|
rumpk_enter_userland(entry)
|
||||||
|
else:
|
||||||
|
kprint("[Subject] Failed to load: ")
|
||||||
|
kprintln(cstring(subject_loading_path))
|
||||||
|
|
||||||
kprintln("[Subject] Failed to load or returned. Pausing for Rebirth.")
|
kprintln("[Subject] Pausing for Rebirth.")
|
||||||
fiber_yield()
|
fiber_yield()
|
||||||
|
|
||||||
# --- STACK ALLOCATIONS ---
|
# --- STACK ALLOCATIONS ---
|
||||||
|
|
@ -52,35 +94,7 @@ var stack_ui {.align: 16.}: array[32768, uint8]
|
||||||
var stack_subject {.align: 16.}: array[32768, uint8]
|
var stack_subject {.align: 16.}: array[32768, uint8]
|
||||||
var stack_watchdog {.align: 16.}: array[4096, uint8]
|
var stack_watchdog {.align: 16.}: array[4096, uint8]
|
||||||
|
|
||||||
# Exports for Zig NPLs
|
|
||||||
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
|
|
||||||
proc write*(fd: cint, p: pointer, len: csize_t): csize_t {.exportc, cdecl.} =
|
|
||||||
console_write(p, len)
|
|
||||||
return len
|
|
||||||
|
|
||||||
# Utility for Logic Core
|
|
||||||
proc kwrite*(p: pointer, len: csize_t) {.exportc, cdecl.} =
|
|
||||||
if p != nil and len > 0:
|
|
||||||
console_write(p, len)
|
|
||||||
|
|
||||||
proc kprint*(s: cstring) {.exportc, cdecl.} =
|
|
||||||
if s != nil:
|
|
||||||
let length = len(s)
|
|
||||||
if length > 0:
|
|
||||||
kwrite(cast[pointer](s), csize_t(length))
|
|
||||||
|
|
||||||
proc kprint_hex*(n: uint64) {.exportc, cdecl.} =
|
|
||||||
const hex_chars = "0123456789ABCDEF"
|
|
||||||
var buf: array[18, char]
|
|
||||||
buf[0] = '0'
|
|
||||||
buf[1] = 'x'
|
|
||||||
for i in 0..15:
|
|
||||||
let nibble = (n shr (60 - (i * 4))) and 0xF
|
|
||||||
buf[i+2] = hex_chars[nibble]
|
|
||||||
console_write(addr buf[0], 18)
|
|
||||||
|
|
||||||
proc kprintln*(s: cstring) {.exportc, cdecl.} =
|
|
||||||
kprint(s); kprint("\n")
|
|
||||||
|
|
||||||
# Phase 31: Memory Manager (The Glass Cage)
|
# Phase 31: Memory Manager (The Glass Cage)
|
||||||
proc mm_init() {.importc, cdecl.}
|
proc mm_init() {.importc, cdecl.}
|
||||||
|
|
@ -113,9 +127,6 @@ var chan_cmd*: SovereignChannel[CmdPacket]
|
||||||
# chan_input is now imported from ion.nim!
|
# chan_input is now imported from ion.nim!
|
||||||
|
|
||||||
proc ion_push_stdin*(p: pointer, len: csize_t) {.exportc, cdecl.} =
|
proc ion_push_stdin*(p: pointer, len: csize_t) {.exportc, cdecl.} =
|
||||||
## Push raw console data into the Userland Input Ring
|
|
||||||
|
|
||||||
# [FIX] Safety Guard
|
|
||||||
if chan_input.ring == nil:
|
if chan_input.ring == nil:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -163,15 +174,15 @@ proc rumpk_yield_internal() {.cdecl, exportc.} =
|
||||||
let load = get_ion_load()
|
let load = get_ion_load()
|
||||||
let now = get_now_ns()
|
let now = get_now_ns()
|
||||||
|
|
||||||
# 🏛️ ADAPTIVE GOVERNOR (Phase 3: FLOOD CONTROL)
|
# 🏛️ ADAPTIVE GOVERNOR (Phase 3: FLOOD CONTROL) - Temporarily disabled for debugging starvation
|
||||||
if load > 200:
|
# if load > 200:
|
||||||
if current_fiber != addr fiber_ion:
|
# if current_fiber != addr fiber_ion:
|
||||||
switch(addr fiber_ion)
|
# switch(addr fiber_ion)
|
||||||
return
|
# return
|
||||||
elif load > 0:
|
# elif load > 0:
|
||||||
if current_fiber == addr fiber_subject:
|
# if current_fiber == addr fiber_subject:
|
||||||
switch(addr fiber_ion)
|
# switch(addr fiber_ion)
|
||||||
return
|
# return
|
||||||
|
|
||||||
# Normal Round Robin logic with Sleep Check
|
# Normal Round Robin logic with Sleep Check
|
||||||
var next_fiber: Fiber = nil
|
var next_fiber: Fiber = nil
|
||||||
|
|
@ -179,8 +190,7 @@ proc rumpk_yield_internal() {.cdecl, exportc.} =
|
||||||
if current_fiber == addr fiber_ion:
|
if current_fiber == addr fiber_ion:
|
||||||
next_fiber = addr fiber_nexshell
|
next_fiber = addr fiber_nexshell
|
||||||
elif current_fiber == addr fiber_nexshell:
|
elif current_fiber == addr fiber_nexshell:
|
||||||
next_fiber = addr fiber_ui
|
# Phase 33 Debug: Skip UI fiber if problematic
|
||||||
elif current_fiber == addr fiber_ui:
|
|
||||||
next_fiber = addr fiber_subject
|
next_fiber = addr fiber_subject
|
||||||
elif current_fiber == addr fiber_subject:
|
elif current_fiber == addr fiber_subject:
|
||||||
next_fiber = addr fiber_watchdog
|
next_fiber = addr fiber_watchdog
|
||||||
|
|
@ -196,21 +206,27 @@ proc rumpk_yield_internal() {.cdecl, exportc.} =
|
||||||
|
|
||||||
# Move to next in sequence
|
# Move to next in sequence
|
||||||
if next_fiber == addr fiber_ion: next_fiber = addr fiber_nexshell
|
if next_fiber == addr fiber_ion: next_fiber = addr fiber_nexshell
|
||||||
elif next_fiber == addr fiber_nexshell: next_fiber = addr fiber_ui
|
elif next_fiber == addr fiber_nexshell: next_fiber = addr fiber_subject
|
||||||
elif next_fiber == addr fiber_ui: next_fiber = addr fiber_subject
|
|
||||||
elif next_fiber == addr fiber_subject: next_fiber = addr fiber_watchdog
|
elif next_fiber == addr fiber_subject: next_fiber = addr fiber_watchdog
|
||||||
else: next_fiber = addr fiber_ion
|
else: next_fiber = addr fiber_ion
|
||||||
|
|
||||||
|
# Force found = true for now
|
||||||
|
found = true
|
||||||
|
|
||||||
if found and next_fiber != current_fiber:
|
if found and next_fiber != current_fiber:
|
||||||
|
# Idle loop
|
||||||
|
# kprint(".")
|
||||||
switch(next_fiber)
|
switch(next_fiber)
|
||||||
elif not found:
|
elif not found:
|
||||||
asm "csrsi sstatus, 2"
|
asm "csrsi sstatus, 2"
|
||||||
|
asm "wfi"
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
# ION Intelligence Fiber (Core System Supervisor)
|
# ION Intelligence Fiber (Core System Supervisor)
|
||||||
# =========================================================
|
# =========================================================
|
||||||
|
|
||||||
proc ion_fiber_entry() {.cdecl.} =
|
proc ion_fiber_entry() {.cdecl.} =
|
||||||
|
# kprintln("[ION] Alive")
|
||||||
hal_io_init()
|
hal_io_init()
|
||||||
kprintln("[ION] Fiber 1 Reporting for Duty.")
|
kprintln("[ION] Fiber 1 Reporting for Duty.")
|
||||||
while true:
|
while true:
|
||||||
|
|
@ -428,6 +444,23 @@ proc k_pledge(promises: uint64): int32 {.exportc, cdecl.} =
|
||||||
kprintln("")
|
kprintln("")
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
proc k_handle_exception*(scause, sepc, stval: uint) {.exportc, cdecl.} =
|
||||||
|
kprint("\n[SECURITY] EXCEPTION! scause=")
|
||||||
|
kprint_hex(uint64(scause))
|
||||||
|
kprint(" sepc=")
|
||||||
|
kprint_hex(uint64(sepc))
|
||||||
|
kprint(" stval=")
|
||||||
|
kprint_hex(uint64(stval))
|
||||||
|
kprintln("\n")
|
||||||
|
|
||||||
|
if current_fiber != nil:
|
||||||
|
kprint("[SECURITY] Faulting Fiber: ")
|
||||||
|
if current_fiber.name != nil: kprint(current_fiber.name)
|
||||||
|
else: kprint_hex(current_fiber.id)
|
||||||
|
kprintln("")
|
||||||
|
|
||||||
|
# Non-recoverable for now: Stay in loop
|
||||||
|
while true: discard
|
||||||
|
|
||||||
proc k_handle_syscall*(nr, a0, a1, a2: uint): uint {.exportc, cdecl.} =
|
proc k_handle_syscall*(nr, a0, a1, a2: uint): uint {.exportc, cdecl.} =
|
||||||
case nr:
|
case nr:
|
||||||
|
|
@ -455,13 +488,38 @@ proc k_handle_syscall*(nr, a0, a1, a2: uint): uint {.exportc, cdecl.} =
|
||||||
return cast[uint](-1)
|
return cast[uint](-1)
|
||||||
return uint(ion_vfs_list(cast[pointer](a0), uint64(a1)))
|
return uint(ion_vfs_list(cast[pointer](a0), uint64(a1)))
|
||||||
of 0x203: # READ
|
of 0x203: # READ
|
||||||
# Phase 28: Enforce RPATH
|
# Phase 28: Enforce RPATH/STDIO
|
||||||
|
if a0 == 0:
|
||||||
|
if (current_fiber.promises and PLEDGE_STDIO) == 0:
|
||||||
|
kprintln("[SECURITY] PLEDGE VIOLATION: STDIO required for read(0)")
|
||||||
|
return cast[uint](-1)
|
||||||
|
|
||||||
|
var pkt: IonPacket
|
||||||
|
kprintln("[Kernel] sys_read(0)")
|
||||||
|
if chan_input.recv(pkt):
|
||||||
|
let n = if uint64(pkt.len) < a2: uint64(pkt.len) else: a2
|
||||||
|
if n > 0:
|
||||||
|
copyMem(cast[pointer](a1), cast[pointer](pkt.data), int(n))
|
||||||
|
ion_free_raw(pkt.id)
|
||||||
|
return n
|
||||||
|
else:
|
||||||
|
# No data from NexShell, yield to let it run
|
||||||
|
fiber_yield()
|
||||||
|
return 0
|
||||||
|
|
||||||
if (current_fiber.promises and PLEDGE_RPATH) == 0:
|
if (current_fiber.promises and PLEDGE_RPATH) == 0:
|
||||||
kprintln("[SECURITY] PLEDGE VIOLATION: RPATH required for read")
|
kprintln("[SECURITY] PLEDGE VIOLATION: RPATH required for read")
|
||||||
return cast[uint](-1)
|
return cast[uint](-1)
|
||||||
return uint(ion_vfs_read(int32(a0), cast[pointer](a1), uint64(a2)))
|
return uint(ion_vfs_read(int32(a0), cast[pointer](a1), uint64(a2)))
|
||||||
of 0x204: # WRITE
|
of 0x204: # WRITE
|
||||||
# Phase 28: Enforce WPATH
|
# Phase 28: Enforce WPATH/STDIO
|
||||||
|
if a0 == 1 or a0 == 2:
|
||||||
|
if (current_fiber.promises and PLEDGE_STDIO) == 0:
|
||||||
|
kprintln("[SECURITY] PLEDGE VIOLATION: STDIO required for write(1/2)")
|
||||||
|
return cast[uint](-1)
|
||||||
|
console_write(cast[pointer](a1), csize_t(a2))
|
||||||
|
return a2
|
||||||
|
|
||||||
if (current_fiber.promises and PLEDGE_WPATH) == 0:
|
if (current_fiber.promises and PLEDGE_WPATH) == 0:
|
||||||
kprintln("[SECURITY] PLEDGE VIOLATION: WPATH required for write")
|
kprintln("[SECURITY] PLEDGE VIOLATION: WPATH required for write")
|
||||||
return cast[uint](-1)
|
return cast[uint](-1)
|
||||||
|
|
@ -492,12 +550,12 @@ proc kmain() {.exportc, cdecl.} =
|
||||||
# [FIX] Input Channel Init BEFORE Drivers
|
# [FIX] Input Channel Init BEFORE Drivers
|
||||||
ion_init_input()
|
ion_init_input()
|
||||||
|
|
||||||
# Phase 31: The Identity Switch (THE CROSSING)
|
# Phase 31: The Identity Switch (THE CROSSING) - Temporarily disabled
|
||||||
kprintln("[MM] Building Sv39 Page Tables...")
|
# kprintln("[MM] Building Sv39 Page Tables...")
|
||||||
mm_init()
|
# mm_init()
|
||||||
kprintln("[MM] Activating Identity Map...")
|
# kprintln("[MM] Activating Identity Map...")
|
||||||
mm_enable_kernel_paging()
|
# mm_enable_kernel_paging()
|
||||||
kprintln("[MM] ✓ Virtual Memory Active. Reality is Virtual.")
|
# kprintln("[MM] ✓ Virtual Memory Active. Reality is Virtual.")
|
||||||
|
|
||||||
hal_io_init()
|
hal_io_init()
|
||||||
|
|
||||||
|
|
@ -513,10 +571,11 @@ proc kmain() {.exportc, cdecl.} =
|
||||||
sys.fn_vfs_open = ion_vfs_open
|
sys.fn_vfs_open = ion_vfs_open
|
||||||
sys.fn_vfs_read = ion_vfs_read
|
sys.fn_vfs_read = ion_vfs_read
|
||||||
sys.fn_vfs_list = ion_vfs_list
|
sys.fn_vfs_list = ion_vfs_list
|
||||||
sys.fn_vfs_write = ion_vfs_write
|
sys.fn_vfs_write = wrapper_vfs_write
|
||||||
sys.fn_vfs_close = ion_vfs_close
|
sys.fn_vfs_close = ion_vfs_close
|
||||||
sys.fn_log = cast[pointer](kwrite)
|
sys.fn_log = cast[pointer](kwrite)
|
||||||
sys.fn_pledge = k_pledge # Phase 28: Pledge
|
sys.fn_pledge = k_pledge # Phase 28: Pledge
|
||||||
|
sys.fn_yield = cast[proc() {.cdecl.}](kernel.fiber_yield)
|
||||||
|
|
||||||
# 1.5 The Retina (VirtIO-GPU)
|
# 1.5 The Retina (VirtIO-GPU)
|
||||||
proc virtio_gpu_init(base: uint64) {.importc, cdecl.}
|
proc virtio_gpu_init(base: uint64) {.importc, cdecl.}
|
||||||
|
|
@ -559,7 +618,8 @@ proc kmain() {.exportc, cdecl.} =
|
||||||
sys_table.s_event = addr guest_event_hal
|
sys_table.s_event = addr guest_event_hal
|
||||||
sys_table.s_cmd = addr guest_cmd_hal
|
sys_table.s_cmd = addr guest_cmd_hal
|
||||||
sys_table.s_input = chan_input.ring # From global
|
sys_table.s_input = chan_input.ring # From global
|
||||||
|
|
||||||
|
|
||||||
# Framebuffer info (Phase 26: Visual Cortex)
|
# Framebuffer info (Phase 26: Visual Cortex)
|
||||||
sys_table.fb_addr = fb_kern_get_addr()
|
sys_table.fb_addr = fb_kern_get_addr()
|
||||||
sys_table.fb_width = 800 # From framebuffer.zig
|
sys_table.fb_width = 800 # From framebuffer.zig
|
||||||
|
|
@ -574,29 +634,26 @@ proc kmain() {.exportc, cdecl.} =
|
||||||
|
|
||||||
# 4. Deployment
|
# 4. Deployment
|
||||||
kprintln("[Kernel] Spawning System Fibers...")
|
kprintln("[Kernel] Spawning System Fibers...")
|
||||||
|
kprintln(" → fiber_ion")
|
||||||
# Phase 28: Initialize all fibers with full capabilities
|
fiber_ion.name = "ion"
|
||||||
fiber_ion.promises = PLEDGE_ALL
|
|
||||||
fiber_nexshell.promises = PLEDGE_ALL
|
|
||||||
fiber_ui.promises = PLEDGE_ALL
|
|
||||||
fiber_subject.promises = PLEDGE_ALL
|
|
||||||
fiber_watchdog.promises = PLEDGE_ALL
|
|
||||||
|
|
||||||
# 1. ION FIBER (The Valve)
|
|
||||||
init_fiber(addr fiber_ion, ion_fiber_entry, addr stack_ion[0], sizeof(stack_ion))
|
init_fiber(addr fiber_ion, ion_fiber_entry, addr stack_ion[0], sizeof(stack_ion))
|
||||||
|
|
||||||
# 2. NEXSHELL FIBER (The Brain)
|
kprintln(" → fiber_nexshell")
|
||||||
|
fiber_nexshell.name = "nexshell"
|
||||||
init_fiber(addr fiber_nexshell, nexshell_main, addr stack_nexshell[0],
|
init_fiber(addr fiber_nexshell, nexshell_main, addr stack_nexshell[0],
|
||||||
sizeof(stack_nexshell))
|
sizeof(stack_nexshell))
|
||||||
|
|
||||||
# 3. UI FIBER (The Face)
|
# 3. UI FIBER (The Face) - Temporarily disabled to debug boot hang
|
||||||
init_fiber(addr fiber_ui, ui_fiber_entry, addr stack_ui[0], sizeof(stack_ui))
|
# fiber_ui.name = "ui"
|
||||||
|
# init_fiber(addr fiber_ui, ui_fiber_entry, addr stack_ui[0], sizeof(stack_ui))
|
||||||
|
|
||||||
# 4. SUBJECT FIBER (The Payload)
|
kprintln(" → fiber_subject")
|
||||||
|
fiber_subject.name = "subject"
|
||||||
init_fiber(addr fiber_subject, subject_fiber_entry, addr stack_subject[0],
|
init_fiber(addr fiber_subject, subject_fiber_entry, addr stack_subject[0],
|
||||||
sizeof(stack_subject))
|
sizeof(stack_subject))
|
||||||
|
|
||||||
# 5. WATCHDOG FIBER (The Immune System)
|
kprintln(" → fiber_watchdog")
|
||||||
|
fiber_watchdog.name = "watchdog"
|
||||||
init_fiber(addr fiber_watchdog, watchdog_loop, addr stack_watchdog[0], sizeof(stack_watchdog))
|
init_fiber(addr fiber_watchdog, watchdog_loop, addr stack_watchdog[0], sizeof(stack_watchdog))
|
||||||
|
|
||||||
# [FIX] GLOBAL INTERRUPT ENABLE
|
# [FIX] GLOBAL INTERRUPT ENABLE
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,8 @@ export fn trap_entry() callconv(.naked) void {
|
||||||
// L1 Kernel Logic
|
// L1 Kernel Logic
|
||||||
extern fn k_handle_syscall(nr: usize, a0: usize, a1: usize, a2: usize) usize;
|
extern fn k_handle_syscall(nr: usize, a0: usize, a1: usize, a2: usize) usize;
|
||||||
|
|
||||||
|
extern fn k_handle_exception(scause: usize, sepc: usize, stval: usize) void;
|
||||||
|
|
||||||
export fn rss_trap_handler(frame: *TrapFrame) void {
|
export fn rss_trap_handler(frame: *TrapFrame) void {
|
||||||
const scause = frame.scause;
|
const scause = frame.scause;
|
||||||
|
|
||||||
|
|
@ -193,17 +195,12 @@ export fn rss_trap_handler(frame: *TrapFrame) void {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uart.print("\n\n!!! SOVEREIGN TRAP !!!\n");
|
// Delegate all other exceptions to the Kernel Immune System
|
||||||
uart.print("SCAUSE: 0x");
|
// It will decide whether to segregate (worker) or halt (system)
|
||||||
uart.print_hex(scause);
|
// Note: k_handle_exception handles flow control (yield/halt) and does not return
|
||||||
uart.print("\n");
|
k_handle_exception(scause, frame.sepc, frame.stval);
|
||||||
uart.print("SEPC: 0x");
|
|
||||||
uart.print_hex(frame.sepc);
|
// Safety halt if kernel returns (should be unreachable)
|
||||||
uart.print("\n");
|
|
||||||
uart.print("STVAL: 0x");
|
|
||||||
uart.print_hex(frame.stval);
|
|
||||||
uart.print("\n");
|
|
||||||
uart.print("SYSTEM HALTED.\n");
|
|
||||||
while (true) {}
|
while (true) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,6 +234,7 @@ export fn console_read() c_int {
|
||||||
const virtio_block = @import("virtio_block.zig");
|
const virtio_block = @import("virtio_block.zig");
|
||||||
|
|
||||||
export fn hal_io_init() void {
|
export fn hal_io_init() void {
|
||||||
|
uart.init();
|
||||||
virtio_net.init();
|
virtio_net.init();
|
||||||
virtio_block.init();
|
virtio_block.init();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
hal/uart.zig
24
hal/uart.zig
|
|
@ -18,7 +18,10 @@ const NS16550A_LSR: usize = 0x05; // Line Status Register
|
||||||
const NS16550A_THRE: u8 = 1 << 5; // Transmitter Holding Register Empty
|
const NS16550A_THRE: u8 = 1 << 5; // Transmitter Holding Register Empty
|
||||||
|
|
||||||
pub fn init() void {
|
pub fn init() void {
|
||||||
// QEMU devices are usually pre-initialized by firmware (EDK2/OpenSBI)
|
switch (builtin.cpu.arch) {
|
||||||
|
.riscv64 => init_riscv(),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const NS16550A_IER: usize = 0x01; // Interrupt Enable Register
|
const NS16550A_IER: usize = 0x01; // Interrupt Enable Register
|
||||||
|
|
@ -27,6 +30,13 @@ pub fn init_riscv() void {
|
||||||
// Disable Interrupts to rely on Polling (prevents Interrupt Storms if Handler is missing)
|
// Disable Interrupts to rely on Polling (prevents Interrupt Storms if Handler is missing)
|
||||||
const ier: *volatile u8 = @ptrFromInt(NS16550A_BASE + NS16550A_IER);
|
const ier: *volatile u8 = @ptrFromInt(NS16550A_BASE + NS16550A_IER);
|
||||||
ier.* = 0x00;
|
ier.* = 0x00;
|
||||||
|
|
||||||
|
// Drain FIFO
|
||||||
|
const lsr: *volatile u8 = @ptrFromInt(NS16550A_BASE + NS16550A_LSR);
|
||||||
|
const rbr: *volatile u8 = @ptrFromInt(NS16550A_BASE + NS16550A_THR);
|
||||||
|
while ((lsr.* & 0x01) != 0) {
|
||||||
|
_ = rbr.*;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_char_arm64(c: u8) void {
|
fn write_char_arm64(c: u8) void {
|
||||||
|
|
@ -75,8 +85,16 @@ pub fn read_byte() ?u8 {
|
||||||
.riscv64 => {
|
.riscv64 => {
|
||||||
const thr: *volatile u8 = @ptrFromInt(NS16550A_BASE + NS16550A_THR);
|
const thr: *volatile u8 = @ptrFromInt(NS16550A_BASE + NS16550A_THR);
|
||||||
const lsr: *volatile u8 = @ptrFromInt(NS16550A_BASE + NS16550A_LSR);
|
const lsr: *volatile u8 = @ptrFromInt(NS16550A_BASE + NS16550A_LSR);
|
||||||
if ((lsr.* & 0x01) != 0) { // Data Ready
|
|
||||||
return thr.*;
|
const lsr_val = lsr.*;
|
||||||
|
|
||||||
|
// DIAGNOSTIC: Periodic LSR dump removed
|
||||||
|
|
||||||
|
if ((lsr_val & 0x01) != 0) { // Data Ready
|
||||||
|
const b = thr.*;
|
||||||
|
// Signal reception
|
||||||
|
// Signal reception removed
|
||||||
|
return b;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,13 @@ proc pledge*(promises: uint64): int {.exportc, cdecl.} =
|
||||||
return int(sys.fn_pledge(promises))
|
return int(sys.fn_pledge(promises))
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
return -1
|
||||||
|
|
||||||
|
proc upgrade*(target_fid: uint64, path: cstring): int {.exportc, cdecl.} =
|
||||||
|
## Live Upgrade System (The Phoenix)
|
||||||
|
## Returns: 0 on success, -error on failure
|
||||||
|
return syscall(0x502, int(target_fid), cast[int](path))
|
||||||
|
|
||||||
# --- HIGH LEVEL HELPERS ---
|
# --- HIGH LEVEL HELPERS ---
|
||||||
import strutils, sequtils
|
import strutils, sequtils
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,22 @@ proc membrane_init*() {.exportc, cdecl.} =
|
||||||
when not defined(is_membrane):
|
when not defined(is_membrane):
|
||||||
ion_pool_init()
|
ion_pool_init()
|
||||||
ion_user_init()
|
ion_user_init()
|
||||||
|
|
||||||
|
# EMERGENCY PHASE 34.3: Address Verify (Userland Side)
|
||||||
|
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
|
||||||
|
if sys != nil and sys.fn_vfs_write != nil:
|
||||||
|
var msg = "[Membrane] Input Ring Ptr @ 0x"
|
||||||
|
discard sys.fn_vfs_write(1, unsafeAddr msg[0], uint64(msg.len))
|
||||||
|
# Print hex address
|
||||||
|
let ring_addr = cast[uint64](membrane_input_ring_ptr)
|
||||||
|
for i in countdown(15, 0):
|
||||||
|
let nibble = (ring_addr shr (i * 4)) and 0xF
|
||||||
|
let hex_char = if nibble < 10: char(nibble + ord('0')) else: char(nibble -
|
||||||
|
10 + ord('A'))
|
||||||
|
discard sys.fn_vfs_write(1, unsafeAddr hex_char, 1)
|
||||||
|
let newline = "\n"
|
||||||
|
discard sys.fn_vfs_write(1, unsafeAddr newline[0], 1)
|
||||||
|
|
||||||
lwip_init()
|
lwip_init()
|
||||||
|
|
||||||
# Set up Virtual Interface for Subject (10.0.2.16)
|
# Set up Virtual Interface for Subject (10.0.2.16)
|
||||||
|
|
@ -230,7 +246,12 @@ proc pump_membrane_stack*() {.exportc, cdecl.} =
|
||||||
ion_user_free(pkt)
|
ion_user_free(pkt)
|
||||||
|
|
||||||
# 2. Check Timers
|
# 2. Check Timers
|
||||||
|
# console_write(cstring("P"), 1)
|
||||||
sys_check_timeouts()
|
sys_check_timeouts()
|
||||||
|
# Phase 33: Explicit yield if we aren't calling sys_read
|
||||||
|
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
|
||||||
|
if sys.fn_yield != nil:
|
||||||
|
sys.fn_yield()
|
||||||
|
|
||||||
proc tcp_write*(pcb: ptr TcpPcb; dataptr: pointer; len: uint16;
|
proc tcp_write*(pcb: ptr TcpPcb; dataptr: pointer; len: uint16;
|
||||||
apiflags: uint8): ErrT {.
|
apiflags: uint8): ErrT {.
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@ const
|
||||||
PLEDGE_EXEC* = 0x0010'u64
|
PLEDGE_EXEC* = 0x0010'u64
|
||||||
PLEDGE_ALL* = 0xFFFFFFFFFFFFFFFF'u64
|
PLEDGE_ALL* = 0xFFFFFFFFFFFFFFFF'u64
|
||||||
|
|
||||||
|
# Phase 34: Phoenix Version Marker
|
||||||
|
NIPBOX_VERSION* = "v0.8.8-PHOENIX"
|
||||||
|
|
||||||
type
|
type
|
||||||
PipelineData = seq[Node]
|
PipelineData = seq[Node]
|
||||||
|
|
||||||
|
|
@ -25,15 +28,32 @@ var last_exit_code: int = 0
|
||||||
|
|
||||||
# --- HELPERS ---
|
# --- 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) =
|
proc print(s: string) =
|
||||||
if s.len > 0:
|
if s.len > 0:
|
||||||
# 1. Send to UART (Umbilical)
|
let sys = cast[ptr SysTablePrint](SYS_TABLE_ADDR)
|
||||||
discard lb.write(cint(1), cast[pointer](unsafeAddr s[0]), csize_t(s.len))
|
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 =
|
proc expand_vars(text: string): string =
|
||||||
# Replace $var with env value, including special $? for exit code
|
# 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)
|
discard lb.join(fid)
|
||||||
return packet.output
|
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 <path>\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 ---
|
# --- COMMANDS ---
|
||||||
|
|
||||||
proc cmd_ls*(args: seq[string], input: PipelineData): PipelineData =
|
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))
|
node.addProp("body", newVal(response_body))
|
||||||
return @[node]
|
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 <ip:port/path> <outfile>\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..<slash_pos]
|
||||||
|
path_str = url_arg[slash_pos..^1]
|
||||||
|
|
||||||
|
let parts = host_part.split(':')
|
||||||
|
if parts.len != 2:
|
||||||
|
print("Error: Target must be IP:PORT (e.g. 10.0.2.2:8000)\n")
|
||||||
|
return @[]
|
||||||
|
|
||||||
|
let ip_str = parts[0]
|
||||||
|
let port = uint16(parseInt(parts[1]))
|
||||||
|
|
||||||
|
let ip_parts = ip_str.split('.')
|
||||||
|
if ip_parts.len != 4: return @[]
|
||||||
|
let ip_val = (uint32(parseInt(ip_parts[0])) shl 0) or
|
||||||
|
(uint32(parseInt(ip_parts[1])) shl 8) or
|
||||||
|
(uint32(parseInt(ip_parts[2])) shl 16) or
|
||||||
|
(uint32(parseInt(ip_parts[3])) shl 24)
|
||||||
|
|
||||||
|
print("[Download] Connecting to " & host_part & "...\n")
|
||||||
|
let fd = lb.socket(2, 1, 0)
|
||||||
|
if fd < 100: return @[]
|
||||||
|
|
||||||
|
type SockAddrIn = object
|
||||||
|
sin_family: uint16
|
||||||
|
sin_port: uint16
|
||||||
|
sin_addr: uint32
|
||||||
|
sin_zero: array[8, char]
|
||||||
|
|
||||||
|
var addr_in: SockAddrIn
|
||||||
|
addr_in.sin_family = 2
|
||||||
|
addr_in.sin_port = ((port and 0xFF) shl 8) or (port shr 8)
|
||||||
|
addr_in.sin_addr = ip_val
|
||||||
|
|
||||||
|
if lb.connect(fd, addr addr_in, sizeof(addr_in)) < 0:
|
||||||
|
print("Error: Connection Failed.\n")
|
||||||
|
return @[]
|
||||||
|
|
||||||
|
# Wait for connection
|
||||||
|
var timeout = 0
|
||||||
|
while timeout < 1000:
|
||||||
|
lb.pump_membrane_stack()
|
||||||
|
timeout += 1
|
||||||
|
for i in 0..1000: discard
|
||||||
|
|
||||||
|
# Request
|
||||||
|
let req = "GET " & path_str & " HTTP/1.1\r\nHost: " & ip_str & "\r\nConnection: close\r\n\r\n"
|
||||||
|
if lb.send(cint(fd), cast[pointer](unsafeAddr req[0]), csize_t(req.len), 0) <= 0:
|
||||||
|
print("Error: Send Failed.\n")
|
||||||
|
discard lb.close(cint(fd))
|
||||||
|
return @[]
|
||||||
|
|
||||||
|
# Open File
|
||||||
|
let fd_file = lb.open(outfile.cstring, 577) # O_WRONLY|O_CREAT|O_TRUNC
|
||||||
|
if fd_file < 0:
|
||||||
|
print("Error: Cannot open output file " & outfile & "\n")
|
||||||
|
discard lb.close(cint(fd))
|
||||||
|
return @[]
|
||||||
|
|
||||||
|
print("[Download] Downloading...\n")
|
||||||
|
|
||||||
|
var buf: array[4096, char]
|
||||||
|
var header_acc = ""
|
||||||
|
var header_parsed = false
|
||||||
|
var total_bytes = 0
|
||||||
|
timeout = 0
|
||||||
|
|
||||||
|
while timeout < 10000:
|
||||||
|
lb.pump_membrane_stack()
|
||||||
|
let n = lb.recv(cint(fd), addr buf[0], 4096, 0)
|
||||||
|
|
||||||
|
if n > 0:
|
||||||
|
timeout = 0
|
||||||
|
if not header_parsed:
|
||||||
|
for i in 0..<n: header_acc.add(buf[i])
|
||||||
|
let sep = header_acc.find("\r\n\r\n")
|
||||||
|
if sep != -1:
|
||||||
|
header_parsed = true
|
||||||
|
let body_start = sep + 4
|
||||||
|
if body_start < header_acc.len:
|
||||||
|
let chunk = header_acc[body_start..^1]
|
||||||
|
discard lb.write(fd_file, cast[pointer](unsafeAddr chunk[0]),
|
||||||
|
csize_t(chunk.len))
|
||||||
|
total_bytes += chunk.len
|
||||||
|
header_acc = ""
|
||||||
|
else:
|
||||||
|
if header_acc.len > 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 =
|
proc cmd_from_json*(args: seq[string], input: PipelineData): PipelineData =
|
||||||
if input.len == 0: return @[]
|
if input.len == 0: return @[]
|
||||||
result = @[]
|
result = @[]
|
||||||
|
|
@ -387,9 +566,10 @@ proc cmd_set*(args: seq[string], input: PipelineData): PipelineData =
|
||||||
last_exit_code = 0
|
last_exit_code = 0
|
||||||
return @[]
|
return @[]
|
||||||
|
|
||||||
|
|
||||||
proc cmd_help*(args: seq[string], input: PipelineData): PipelineData =
|
proc cmd_help*(args: seq[string], input: PipelineData): PipelineData =
|
||||||
print("NipBox v0.8.7 (Phase 25: NipScript - Turing Complete Shell)\n")
|
print("NipBox " & NIPBOX_VERSION & " (Phase 34: Orbital Drop)\n")
|
||||||
print("Commands: ls, cat, echo, where, http.get, from_json, mount, matrix, set, if, while, help, exit\n")
|
print("Commands: ls, cat, echo, where, http.get, http.download, from_json, mount, matrix, set, if, while, help, exit\n")
|
||||||
return @[]
|
return @[]
|
||||||
|
|
||||||
# --- DISPATCHER ---
|
# --- DISPATCHER ---
|
||||||
|
|
@ -408,9 +588,16 @@ proc dispatch_command(name: string, args: seq[string],
|
||||||
of "http.get":
|
of "http.get":
|
||||||
# Phase 30: Spawn in worker with INET pledge only (no file access)
|
# 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)
|
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 "from_json": return cmd_from_json(args, input)
|
||||||
of "mount": return cmd_mount(args, input)
|
of "mount": return cmd_mount(args, input)
|
||||||
of "matrix": return cmd_matrix(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 "set": return cmd_set(args, input)
|
||||||
of "help": return cmd_help(args, input)
|
of "help": return cmd_help(args, input)
|
||||||
of "exit":
|
of "exit":
|
||||||
|
|
@ -603,21 +790,26 @@ proc run_script(path: string) =
|
||||||
|
|
||||||
proc main() =
|
proc main() =
|
||||||
# Initialize the Biosuit
|
# Initialize the Biosuit
|
||||||
|
print("[NipBox] Booting...\n")
|
||||||
lb.membrane_init()
|
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("\n\x1b[1;32m╔═══════════════════════════════════════╗\x1b[0m\n")
|
||||||
print("\x1b[1;32m║ SOVEREIGN SUPERVISOR v0.8.7 ║\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║ PHASE 21: THE TELEPORTER ACTIVATED ║\x1b[0m\n")
|
||||||
print("\x1b[1;32m╚═══════════════════════════════════════╝\x1b[0m\n\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")
|
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:
|
while true:
|
||||||
# Important: Pump the stack in the main loop
|
loop_counter += 1
|
||||||
lb.pump_membrane_stack()
|
lb.pump_membrane_stack()
|
||||||
|
|
||||||
var c: char
|
var c: char
|
||||||
|
|
@ -638,7 +830,7 @@ proc main() =
|
||||||
s.add(c)
|
s.add(c)
|
||||||
print(s)
|
print(s)
|
||||||
else:
|
else:
|
||||||
# Slow down polling just enough to let other fibers run
|
# Slow down polling
|
||||||
for i in 0..10_000: discard
|
for i in 0..10_000: discard
|
||||||
|
|
||||||
when isMainModule: main()
|
when isMainModule: main()
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
# Nexus Sovereign Boot Script
|
|
||||||
echo "--- Initializing Sovereign Services ---"
|
|
||||||
|
|
||||||
echo "Activating Persistent Storage..."
|
|
||||||
mount
|
|
||||||
|
|
||||||
echo "Phase 20: Testing Object Pipeline..."
|
|
||||||
ls | where size > 0
|
|
||||||
|
|
||||||
echo "Phase 21: The Teleporter (Template)..."
|
|
||||||
# http.get 10.0.2.2:8000 | from_json | where status == 200
|
|
||||||
|
|
||||||
echo "Phase 22: Sovereign Write Test..."
|
|
||||||
echo "Sovereign Architecture" > /tmp/nexus.kdl
|
|
||||||
cat /tmp/nexus.kdl
|
|
||||||
|
|
||||||
echo "Phase 23: Persistence Check..."
|
|
||||||
cat persistence.txt
|
|
||||||
echo "Systems Modified" > persistence.txt
|
|
||||||
|
|
||||||
echo "--- Boot Record Complete ---"
|
|
||||||
|
|
@ -27,6 +27,7 @@ fn RingBuffer(comptime T: type) type {
|
||||||
|
|
||||||
const SysTable = extern struct {
|
const SysTable = extern struct {
|
||||||
magic: u32,
|
magic: u32,
|
||||||
|
reserved: u32,
|
||||||
s_rx: *RingBuffer(IonPacket),
|
s_rx: *RingBuffer(IonPacket),
|
||||||
s_tx: *RingBuffer(IonPacket),
|
s_tx: *RingBuffer(IonPacket),
|
||||||
s_event: *RingBuffer(IonPacket),
|
s_event: *RingBuffer(IonPacket),
|
||||||
|
|
@ -54,7 +55,22 @@ export fn nexshell_main() void {
|
||||||
var input_buffer: [64]u8 = undefined;
|
var input_buffer: [64]u8 = undefined;
|
||||||
var input_idx: usize = 0;
|
var input_idx: usize = 0;
|
||||||
|
|
||||||
|
var loop_count: usize = 0;
|
||||||
|
var poll_pulse: usize = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
loop_count += 1;
|
||||||
|
poll_pulse += 1;
|
||||||
|
|
||||||
|
// Heartbeat every 100 iterations
|
||||||
|
if (loop_count % 100 == 0) {
|
||||||
|
// Heartbeat removed
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polling pulse every 10k to show activity
|
||||||
|
if (poll_pulse >= 10000) {
|
||||||
|
// print("P");
|
||||||
|
poll_pulse = 0;
|
||||||
|
}
|
||||||
// 1. Process Telemetry Events
|
// 1. Process Telemetry Events
|
||||||
const head = @atomicLoad(u32, &event_ring.head, .acquire);
|
const head = @atomicLoad(u32, &event_ring.head, .acquire);
|
||||||
const tail = @atomicLoad(u32, &event_ring.tail, .monotonic);
|
const tail = @atomicLoad(u32, &event_ring.tail, .monotonic);
|
||||||
|
|
@ -74,6 +90,10 @@ export fn nexshell_main() void {
|
||||||
const c = console_read();
|
const c = console_read();
|
||||||
if (c != -1) {
|
if (c != -1) {
|
||||||
const byte = @as(u8, @intCast(c));
|
const byte = @as(u8, @intCast(c));
|
||||||
|
// print("[NexShell] Got char: '");
|
||||||
|
// const char_buf = [1]u8{byte};
|
||||||
|
// print(&char_buf);
|
||||||
|
// print("'\n");
|
||||||
|
|
||||||
if (forward_mode) {
|
if (forward_mode) {
|
||||||
// Check for escape: Ctrl+K (11)
|
// Check for escape: Ctrl+K (11)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue