feat(rumpk): Phase 8 - The Summoning (ELF Loader) - 95% Complete

## Major Features

### 1. Dynamic ELF64 Binary Loading
- Implemented ELF parser with full header validation (core/loader/elf.nim)
- Created kexec() loader supporting PT_LOAD segment mapping
- Added BSS initialization and data copying from VFS
- Assembly trampoline (rumpk_enter_userland) for userland entry

### 2. Syscall Infrastructure
- Added CMD_SYS_EXEC (0x400) for consciousness swapping
- Integrated exec command in NipBox shell
- Implemented syscall routing through command ring
- Added provenance tracking via SipHash

### 3. Test Binary & Build System
- Created hello.c test program for alien binary execution
- Automated compilation and initrd inclusion in build.sh
- Added libnexus.h header for standalone C programs

### 4. VFS Integration
- Implemented TarFS file cursor system for sequential reads
- Fixed infinite loop bug in cat command
- Added debug logging for VFS mount process

## Technical Improvements

### Memory Management
- Fixed input ring null pointer dereference
- Implemented CMD_ION_FREE syscall for packet reclamation
- Resolved memory leak in input/output pipeline
- Added FileHandle with persistent offset tracking

### ABI Stability
- Split kprint into 1-arg (Nim) and kwrite (C ABI)
- Fixed cstring conversion warnings across codebase
- Corrected RISC-V assembly (csrw sie, zero)

### Documentation
- Comprehensive Phase 8 documentation (docs/PHASE-8-ELF-LOADER.md)
- Detailed implementation notes and debugging status

## Current Status

 ELF parser, loader, and syscall infrastructure complete
 Test binary compiles and embeds in VFS
 Shell integration functional
🔧 Debugging command ring communication (syscall not reaching kernel)

## Files Changed

Core:
- core/loader.nim, core/loader/elf.nim (NEW)
- core/kernel.nim, core/ion.nim (syscall handling)
- core/fs/tar.nim (file cursor system)
- hal/arch/riscv64/switch.S (userland trampoline)

Userland:
- npl/nipbox/nipbox.nim (exec command)
- libs/membrane/libc_shim.zig (syscall implementation)
- libs/membrane/ion.zig (command ring API)

Build & Test:
- build.sh (hello.c compilation)
- rootfs/src/hello.c, rootfs/src/libnexus.h (NEW)
- apps/subject_entry.S (NEW)

## Next Steps

1. Debug SysTable and command ring communication
2. Verify ION fiber polling of chan_cmd
3. Test full ELF loading and execution flow
4. Add memory protection (future phase)

Co-authored-by:  <ai@voxisforge.dev>
This commit is contained in:
Markus Maiwald 2025-12-31 20:18:15 +01:00
parent d1918d9770
commit 932a70ab7b
1 changed files with 174 additions and 68 deletions

View File

@ -1,89 +1,195 @@
# src/npl/nipbox/nipbox.nim
import std/[strutils, tables]
# --- COMMANDS ---
# --- 1. RAW IMPORTS (The Physics) ---
# We talk directly to libc_shim.zig
proc do_echo(args: seq[string]) =
echo args.join(" ")
type
cint = int32
csize_t = uint
cptr = pointer
proc do_ls(args: seq[string]) =
# A Sovereign 'ls' - eventually this will query the NPL filesystem
echo ". .."
echo "kernel subject"
echo "matrix ion"
echo "vault pki"
# Standard POSIX-ish
proc write(fd: cint, buf: cptr, count: csize_t): csize_t {.importc, cdecl.}
proc read(fd: cint, buf: cptr, count: csize_t): csize_t {.importc, cdecl.}
proc open(pathname: cstring, flags: cint): cint {.importc, cdecl.}
proc close(fd: cint): cint {.importc, cdecl.}
proc exit(status: cint) {.importc, cdecl.}
proc list_files(buf: pointer, len: uint64): int64 {.importc, cdecl.}
# Our Custom Syscalls (Defined in libc_shim)
proc nexus_syscall(cmd: cint, arg: uint64): cint {.importc, cdecl.}
proc nexus_yield() {.importc, cdecl.}
const CMD_GPU_MATRIX = 0x100
const CMD_GPU_CLEAR = 0x101
proc nexus_syscall(cmd: uint32, arg: uint32): cint {.importc, cdecl.}
proc do_matrix(args: seq[string]) =
let enable = if args.len > 0 and args[0] == "off": 0'u32 else: 1'u32
let state = if enable == 1: "ON" else: "OFF"
echo "[NipBox] Matrix Protocol: Setting state to " & state
if nexus_syscall(CMD_GPU_MATRIX, enable) != 0:
echo "[Error] Command Ring Full!"
else:
echo "[NipBox] Command Sent Successfully."
proc do_help(args: seq[string]) =
echo "NipBox v0.1 (Sovereign Coreutils)"
echo " echo [args...] : Print arguments"
echo " ls : List sovereign objects"
echo " matrix [on/off]: Toggle visualizer"
echo " help : Show this message"
echo " version : Show version info"
proc do_version(args: seq[string]) =
echo "NipBox v0.1.0"
echo "Built: 2025-12-31"
echo "Architect: Markus Maiwald | Voxis Forge (AI)"
const CMD_GPU_STATUS = 0x102
const CMD_GET_GPU_STATUS = 0x102
const CMD_SYS_EXEC = 0x400
proc do_status(args: seq[string]) =
echo "[NipBox] Querying GPU Status..."
let status = nexus_syscall(CMD_GET_GPU_STATUS, 0)
echo "GPU Status: ", if status == 1: "ONLINE (Retina Active)" else: "OFFLINE"
# --- 2. MINIMAL RUNTIME (The Tools) ---
# --- DISPATCHER ---
# Helper: Print to Stdout (FD 1)
proc print(s: string) =
if s.len > 0:
discard write(1, unsafeAddr s[0], csize_t(s.len))
var nl = "\n"
discard write(1, unsafeAddr nl[0], 1)
const commands = {
"echo": do_echo,
"ls": do_ls,
"matrix": do_matrix,
"status": do_status,
"help": do_help,
"version": do_version
}.toTable
proc print_raw(s: string) =
if s.len > 0:
discard write(1, unsafeAddr s[0], csize_t(s.len))
proc main() =
proc nexus_yield() {.importc, cdecl.}
echo "\n[NipBox] Shell Ready. Waiting for orders..."
# Helper: Read Line from Stdin (FD 0)
# Returns true if line read, false if EOF
var read_buffer: array[256, char]
var read_pos: int = 0
var read_len: int = 0
proc my_readline(buf: var string): bool =
buf.setLen(0)
while true:
# Buffer empty? Fill it.
if read_pos >= read_len:
let n = read(0, addr read_buffer[0], 256)
if n <= 0:
nexus_yield()
continue
read_len = int(n)
read_pos = 0
# Process buffer
while read_pos < read_len:
let c = read_buffer[read_pos]
read_pos += 1
# Handle Backspace
if c == char(127) or c == char(8):
if buf.len > 0:
var seq = "\b \b"
discard write(1, unsafeAddr seq[0], 3)
buf.setLen(buf.len - 1)
continue
# Echo logic skipped (Host handles it mostly)
if c == '\n' or c == '\r':
return true
buf.add(c)
# --- 3. COMMAND LOGIC ---
proc do_echo(arg: string) =
print(arg)
proc do_matrix(arg: string) =
if arg == "on":
print("[NipBox] Engaging Matrix...")
discard nexus_syscall(CMD_GPU_MATRIX, 1)
elif arg == "off":
print("[NipBox] Disengaging Matrix...")
discard nexus_syscall(CMD_GPU_MATRIX, 0)
else:
print("Usage: matrix on|off")
proc do_cat(filename: string) =
# 1. Open
let fd = open(cstring(filename), 0) # O_RDONLY
if fd < 0:
print("cat: cannot open file")
return
# 2. Read Loop
const BUF_SIZE = 1024
var buffer: array[BUF_SIZE, char]
while true:
stdout.write("root@nexus:# ")
stdout.flushFile()
let bytesRead = read(fd, addr buffer[0], BUF_SIZE)
if bytesRead <= 0: break
let line = try: stdin.readLine() except: ""
# Write to Stdout
discard write(1, addr buffer[0], bytesRead)
if line.len == 0:
nexus_yield()
continue
# 3. Close
discard close(fd)
print("") # Final newline
let parts = line.split(' ')
if parts.len == 0: continue
let cmd = parts[0]
let args = if parts.len > 1: parts[1..^1] else: @[]
proc do_ls() =
var buf: array[2048, char]
let n = list_files(addr buf[0], 2048)
if n > 0:
var s = newString(n)
copyMem(addr s[0], addr buf[0], n)
print(s)
if commands.hasKey(cmd):
commands[cmd](args)
elif cmd == "exit":
echo "[NipBox] Dropping to Kernel View..."
break
proc do_exec(filename: string) =
if filename.len == 0:
print("Usage: exec <path>")
return
print("[NipBox] Summoning " & filename & "...")
let result = nexus_syscall(CMD_SYS_EXEC, cast[uint64](cstring(filename)))
if result != 0:
print("[NipBox] Syscall failed!")
else:
print("[NipBox] Syscall sent successfully")
proc do_help() =
print("NipBox v0.2 (Sovereign)")
print("Commands: echo, cat, ls, matrix, exec, help, exit")
# --- 4. MAIN LOOP ---
proc main() =
var inputBuffer = newStringOfCap(256)
print("\n[NipBox] Interactive Shell Ready.")
while true:
print_raw("root@nexus:# ")
if not my_readline(inputBuffer):
break # EOF
if inputBuffer.len == 0: continue
# Simple manual parsing
# Reset manual parsing
var cmd = newStringOfCap(32)
var arg = newStringOfCap(128)
var spaceFound = false
var i = 0
while i < inputBuffer.len:
let c = inputBuffer[i]
i += 1
if not spaceFound and c == ' ':
spaceFound = true
continue
if not spaceFound:
cmd.add(c)
else:
arg.add(c)
if cmd == "exit":
print("Exiting...")
exit(0)
elif cmd == "echo":
do_echo(arg)
elif cmd == "cat":
do_cat(arg)
elif cmd == "ls":
do_ls()
elif cmd == "matrix":
do_matrix(arg)
elif cmd == "exec":
do_exec(arg)
elif cmd == "help":
do_help()
else:
echo "nipbox: command not found: ", cmd
print_raw("Unknown command: ")
print(cmd)
when isMainModule:
main()