188 lines
5.5 KiB
Nim
188 lines
5.5 KiB
Nim
import socket
|
|
import ../../core/ion/memory
|
|
import ion_client
|
|
|
|
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
|
|
proc membrane_init*() {.importc, cdecl.}
|
|
proc pump_membrane_stack*() {.importc, cdecl.}
|
|
|
|
# --- SYSCALL PRIMITIVE ---
|
|
|
|
proc syscall*(nr: int, a0: int = 0, a1: int = 0, a2: int = 0): int {.inline.} =
|
|
var res: int
|
|
asm """
|
|
mv a7, %1
|
|
mv a0, %2
|
|
mv a1, %3
|
|
mv a2, %4
|
|
ecall
|
|
mv %0, a0
|
|
: "=r"(`res`)
|
|
: "r"(`nr`), "r"(`a0`), "r"(`a1`), "r"(`a2`)
|
|
: "a0", "a7", "memory"
|
|
"""
|
|
return res
|
|
|
|
# --- POSIX SOCKET API SHIMS ---
|
|
|
|
type
|
|
SockAddrIn = object
|
|
sin_family: uint16
|
|
sin_port: uint16
|
|
sin_addr: uint32
|
|
sin_zero: array[8, char]
|
|
|
|
proc socket*(domain, sock_type, protocol: int): int {.exportc, cdecl.} =
|
|
return new_socket()
|
|
|
|
proc connect*(fd: int, sock_addr: pointer, len: int): int {.exportc, cdecl.} =
|
|
if sock_addr == nil: return -1
|
|
let sin = cast[ptr SockAddrIn](sock_addr)
|
|
return connect_flow(fd, sin.sin_addr, sin.sin_port)
|
|
|
|
proc send*(fd: cint, buf: pointer, count: csize_t, flags: cint): int {.exportc, cdecl.} =
|
|
return send_flow(int(fd), buf, int(count))
|
|
|
|
proc recv*(fd: cint, buf: pointer, count: csize_t, flags: cint): int {.exportc, cdecl.} =
|
|
return recv_flow(int(fd), buf, int(count))
|
|
|
|
# --- LIBC IO SHIMS ---
|
|
|
|
proc write*(fd: cint, buf: pointer, count: csize_t): int {.exportc, cdecl.} =
|
|
if fd == 1 or fd == 2:
|
|
when defined(is_kernel):
|
|
return -1
|
|
else:
|
|
console_write(buf, count)
|
|
return int(count)
|
|
|
|
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
|
|
if sys.fn_vfs_write != nil:
|
|
let f = cast[proc(fd: int32, buf: pointer, count: uint64): int64 {.cdecl.}](
|
|
sys.fn_vfs_write)
|
|
return int(f(int32(fd), buf, uint64(count)))
|
|
|
|
if fd >= 100:
|
|
return send_flow(int(fd), buf, int(count))
|
|
|
|
# File Write (Syscall 0x204)
|
|
return syscall(0x204, int(fd), cast[int](buf), int(count))
|
|
|
|
# Stdin buffer for input packets
|
|
var stdin_buf: array[128, byte]
|
|
var stdin_len: int = 0
|
|
var stdin_pos: int = 0
|
|
|
|
proc read*(fd: cint, buf: pointer, count: csize_t): int {.exportc, cdecl.} =
|
|
if fd == 0:
|
|
if stdin_pos < stdin_len:
|
|
let remaining = stdin_len - stdin_pos
|
|
let to_copy = if remaining > int(count): int(count) else: remaining
|
|
copyMem(buf, addr stdin_buf[stdin_pos], to_copy)
|
|
stdin_pos += to_copy
|
|
if stdin_pos >= stdin_len:
|
|
stdin_len = 0
|
|
stdin_pos = 0
|
|
return to_copy
|
|
|
|
# Poll input ring
|
|
var pkt: IonPacket
|
|
if ion_user_input(addr pkt):
|
|
let len = min(int(pkt.len), 128)
|
|
copyMem(addr stdin_buf[0], pkt.data, len)
|
|
stdin_len = len
|
|
stdin_pos = 0
|
|
ion_user_return(pkt.id)
|
|
let to_copy = if stdin_len > int(count): int(count) else: stdin_len
|
|
copyMem(buf, addr stdin_buf[0], to_copy)
|
|
stdin_pos += to_copy
|
|
return to_copy
|
|
return 0
|
|
|
|
if fd >= 100: return recv(fd, buf, count, 0)
|
|
|
|
# Try SysTable first
|
|
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
|
|
if sys.fn_vfs_read != nil:
|
|
let f = cast[proc(fd: int32, buf: pointer, count: uint64): int64 {.cdecl.}](
|
|
sys.fn_vfs_read)
|
|
return int(f(int32(fd), buf, uint64(count)))
|
|
|
|
return syscall(0x203, int(fd), cast[int](buf), int(count))
|
|
|
|
proc exit*(status: cint) {.exportc, cdecl.} =
|
|
discard syscall(0, 0)
|
|
while true: discard
|
|
|
|
proc open*(pathname: cstring, flags: cint): cint {.exportc, cdecl.} =
|
|
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
|
|
if sys.fn_vfs_open != nil:
|
|
return cint(sys.fn_vfs_open(pathname, int32(flags)))
|
|
|
|
return cint(syscall(0x200, cast[int](pathname), int(flags)))
|
|
|
|
proc close*(fd: cint): cint {.exportc, cdecl.} =
|
|
if fd >= 100: return 0
|
|
# Try SysTable first
|
|
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
|
|
if sys.fn_vfs_close != nil:
|
|
let f = cast[proc(fd: int32): int32 {.cdecl.}](sys.fn_vfs_close)
|
|
return cint(f(int32(fd)))
|
|
return cint(syscall(0x201, int(fd)))
|
|
|
|
proc nexus_list*(buf: pointer, len: int): int {.exportc, cdecl.} =
|
|
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
|
|
if sys.fn_vfs_list != nil:
|
|
let f = cast[proc(buf: pointer, max_len: uint64): int64 {.cdecl.}](
|
|
sys.fn_vfs_list)
|
|
return int(f(buf, uint64(len)))
|
|
return syscall(0x202, cast[int](buf), len)
|
|
|
|
# moved to top
|
|
|
|
proc sleep*(seconds: uint32) {.exportc, cdecl.} =
|
|
var i: int = 0
|
|
let limit = int(seconds) * 50_000_000
|
|
while i < limit:
|
|
i += 1
|
|
|
|
# --- PHASE 29: WORKER MODEL (THE HIVE) ---
|
|
|
|
proc spawn*(entry: proc(arg: uint64) {.cdecl.}, arg: uint64 = 0): int {.exportc, cdecl.} =
|
|
## Spawn a new worker fiber
|
|
## Returns: Fiber ID on success, -1 on failure
|
|
return syscall(0x500, cast[int](entry), int(arg))
|
|
|
|
proc join*(fid: int): int {.exportc, cdecl.} =
|
|
## Wait for worker fiber to complete
|
|
## Returns: 0 on success, -1 on failure
|
|
return syscall(0x501, fid)
|
|
|
|
# --- PHASE 28: PLEDGE ---
|
|
|
|
proc pledge*(promises: uint64): int {.exportc, cdecl.} =
|
|
## Reduce capabilities (one-way ratchet)
|
|
## Returns: 0 on success, -1 on failure
|
|
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
|
|
if sys.fn_pledge != nil:
|
|
return int(sys.fn_pledge(promises))
|
|
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 ---
|
|
import strutils, sequtils
|
|
|
|
proc get_vfs_listing*(): seq[string] =
|
|
var buf = newString(4096)
|
|
let n = nexus_list(addr buf[0], 4096)
|
|
if n > 0:
|
|
buf.setLen(n)
|
|
return buf.splitLines().filterIt(it.strip().len > 0)
|
|
return @[]
|