import socket import ../../core/ion/memory import ion_client proc console_write(p: pointer, len: csize_t) {.importc, cdecl.} #[ # --- Heap Allocator (Slab Backed) --- # DISABLED: Using stubs.zig heap for NipBox stability const HEADER_SIZE = 32 proc malloc*(size: csize_t): pointer {.exportc, cdecl.} = if size > (2048 - HEADER_SIZE): return nil var pkt: IonPacket if not ion_user_alloc(addr pkt): return nil if pkt.data == nil: return nil # Store metadata at the start of the slab var header_ptr = cast[ptr IonPacket](pkt.data) header_ptr[] = pkt # Return pointer after header return cast[pointer](cast[uint](pkt.data) + uint(HEADER_SIZE)) proc free*(p: pointer) {.exportc, cdecl.} = if p == nil: return # Recover Metadata let slab_addr = cast[uint](p) - uint(HEADER_SIZE) let header_ptr = cast[ptr IonPacket](slab_addr) # Free using the stored packet (contains correct ID) ion_user_free(header_ptr[]) ]# proc sleep*(seconds: uint32) {.exportc, cdecl.} = # Busy loop sleep var i: int = 0 let limit = int(seconds) * 50_000_000 while i < limit: i += 1 # Basic SockAddr struct match (IPv4) 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.} = # Domain=2 (AF_INET), Type=1 (SOCK_STREAM) # We ignore them for now and just give a Nexus Socket return new_socket() proc connect*(fd: int, sock_addr: pointer, len: int): int {.exportc, cdecl.} = if sock_addr == nil: return -1 # Cast raw pointer to SockAddrIn let sin = cast[ptr SockAddrIn](sock_addr) # Call the Shim # Note: Linux sockaddr_in is Big Endian for Port/IP usually # NPK is likely running the same endianness as Kernel (Little Endian on RISC-V/x86) # But `connect` expects Network Byte Order (Big Endian). # We pass it raw to connect_flow, which will store it. return connect_flow(fd, sin.sin_addr, sin.sin_port) proc write*(fd: cint, buf: pointer, count: csize_t): int {.exportc, cdecl.} = if fd == 1 or fd == 2: when defined(is_kernel): # 1. Allocate a Console Slab var pkt = ion_alloc() if pkt.data == nil: return -1 # 2. Copy the string (Cap at SLAB_SIZE) let safe_count = min(int(count), SLAB_SIZE) copyMem(pkt.data, buf, safe_count) pkt.len = uint16(safe_count) # 3. Push to KERNEL CONSOLE (Port 0) ion_egress_to_port(0, pkt) return int(safe_count) else: # Membrane side: Direct to UART for Phase 7 console_write(buf, count) return int(count) # Handle Sockets (fd > 2) return send_flow(int(fd), buf, int(count)) #[ proc read*(fd: int, buf: pointer, count: int): int {.exportc, cdecl.} = # TODO: Lookup socket, check RX ring return -1 # EBADF ]#