diff --git a/nipbox.nim b/nipbox.nim index 14e597a..b41f8d4 100644 --- a/nipbox.nim +++ b/nipbox.nim @@ -19,13 +19,56 @@ 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.} +proc nexus_net_tx(buf: cptr, len: uint64) {.importc, cdecl.} +proc nexus_net_rx(buf: cptr, max_len: uint64): uint64 {.importc, cdecl.} +proc nexus_blk_read(sector: uint64, buf: cptr, len: uint64) {.importc, cdecl.} +proc nexus_blk_write(sector: uint64, buf: cptr, len: uint64) {.importc, cdecl.} const CMD_GPU_MATRIX = 0x100 const CMD_GPU_STATUS = 0x102 const CMD_GET_GPU_STATUS = 0x102 const CMD_SYS_EXEC = 0x400 -# --- 2. MINIMAL RUNTIME (The Tools) --- +# --- SOVEREIGN NETWORKING TYPES --- +type + EthAddr = array[6, byte] + + EthHeader {.packed.} = object + dest: EthAddr + src: EthAddr + ethertype: uint16 + + ArpPacket {.packed.} = object + htype: uint16 # Hardware type (Ethernet = 1) + ptype: uint16 # Protocol type (IPv4 = 0x0800) + hlen: uint8 # Hardware addr len (6) + plen: uint8 # Protocol addr len (4) + oper: uint16 # Operation (Request=1, Reply=2) + sha: EthAddr # Sender HW addr + spa: uint32 # Sender IP addr + tha: EthAddr # Target HW addr + tpa: uint32 # Target IP addr + + IcmpPacket {.packed.} = object + const_type: uint8 + code: uint8 + checksum: uint16 + id: uint16 + seq: uint16 + # payload follows + +const + ETHERTYPE_ARP = 0x0608 # Big Endian 0x0806 + ETHERTYPE_IP = 0x0008 # Big Endian 0x0800 + ARP_OP_REQUEST = 0x0100 # Big Endian 1 + ARP_OP_REPLY = 0x0200 # Big Endian 2 + IP_PROTO_ICMP = 1 + +# My IP: 10.0.2.15 +const MY_IP: uint32 = 0x0F02000A +const MY_MAC: EthAddr = [0x52.byte, 0x54.byte, 0x00.byte, 0x12.byte, 0x34.byte, 0x56.byte] + +# --- 2. HELPERS --- # Helper: Print to Stdout (FD 1) proc print(s: string) = @@ -38,45 +81,88 @@ proc print_raw(s: string) = if s.len > 0: discard write(1, unsafeAddr s[0], csize_t(s.len)) -# 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 +# Helper: Swap Bytes 16 +proc swap16(x: uint16): uint16 = + return (x shl 8) or (x shr 8) -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 +# Calculate Checksum (Standard Internet Checksum) +proc calc_checksum(buf: cptr, len: int): uint16 = + var sum: uint32 = 0 + let ptr16 = cast[ptr UncheckedArray[uint16]](buf) + for i in 0 ..< (len div 2): + sum += uint32(ptr16[i]) - # Process buffer - while read_pos < read_len: - let c = read_buffer[read_pos] - read_pos += 1 + if (len mod 2) != 0: + let ptr8 = cast[ptr UncheckedArray[byte]](buf) + sum += uint32(ptr8[len-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 + while (sum shr 16) > 0: + sum = (sum and 0xFFFF) + (sum shr 16) - # Echo logic skipped (Host handles it mostly) + return uint16(not sum) - if c == '\n' or c == '\r': - return true +# Utility: Parse Int simple +proc parseIntSimple(s: string): uint64 = + var res: uint64 = 0 + for c in s: + if c >= '0' and c <= '9': + res = res * 10 + uint64(ord(c) - ord('0')) + return res - buf.add(c) +proc toHexChar(b: byte): char = + if b < 10: return char(ord('0') + b) + else: return char(ord('A') + (b - 10)) + +# --- 3. LOGIC MODULES --- + +# Network Buffer (Shared for RX/TX) +var net_buf: array[1536, byte] + +proc handle_arp(rx_len: int) = + let eth = cast[ptr EthHeader](addr net_buf[0]) + let arp = cast[ptr ArpPacket](addr net_buf[14]) # Valid only if ethertype is ARP + + if arp.tpa == MY_IP and arp.oper == ARP_OP_REQUEST: + print("[Net] ARP Request for me! Replying...") + # Construct Reply + arp.tha = arp.sha + arp.tpa = arp.spa + arp.sha = MY_MAC + arp.spa = MY_IP + arp.oper = ARP_OP_REPLY + eth.dest = eth.src + eth.src = MY_MAC + nexus_net_tx(addr net_buf[0], 42) + +proc handle_ipv4(rx_len: int) = + let eth = cast[ptr EthHeader](addr net_buf[0]) + if net_buf[23] == IP_PROTO_ICMP: + let dst_ip_ptr = cast[ptr uint32](addr net_buf[30]) + if dst_ip_ptr[] == MY_IP: + let icmp = cast[ptr IcmpPacket](addr net_buf[34]) + if icmp.const_type == 8: # Echo Request + print("[Net] ICMP Ping from Gateway. PONG!") + icmp.const_type = 0 # Echo Reply + icmp.checksum = 0 # Recalc + let icmp_len = rx_len - 34 + icmp.checksum = calc_checksum(addr net_buf[34], icmp_len) + let src_ip_ptr = cast[ptr uint32](addr net_buf[26]) + let tmp = src_ip_ptr[] + src_ip_ptr[] = dst_ip_ptr[] + dst_ip_ptr[] = tmp + eth.dest = eth.src + eth.src = MY_MAC + nexus_net_tx(addr net_buf[0], uint64(rx_len)) + +proc poll_network() = + let len = nexus_net_rx(addr net_buf[0], 1536) + if len > 0: + let eth = cast[ptr EthHeader](addr net_buf[0]) + if eth.ethertype == ETHERTYPE_ARP: + handle_arp(int(len)) + elif eth.ethertype == ETHERTYPE_IP: + handle_ipv4(int(len)) -# --- 3. COMMAND LOGIC --- proc do_echo(arg: string) = print(arg) @@ -92,26 +178,18 @@ proc do_matrix(arg: string) = print("Usage: matrix on|off") proc do_cat(filename: string) = - # 1. Open - let fd = open(cstring(filename), 0) # O_RDONLY + let fd = open(cstring(filename), 0) if fd < 0: print("cat: cannot open file") return - - # 2. Read Loop const BUF_SIZE = 1024 var buffer: array[BUF_SIZE, char] - while true: let bytesRead = read(fd, addr buffer[0], BUF_SIZE) if bytesRead <= 0: break - - # Write to Stdout discard write(1, addr buffer[0], bytesRead) - - # 3. Close discard close(fd) - print("") # Final newline + print("") proc do_ls() = var buf: array[2048, char] @@ -132,64 +210,144 @@ proc do_exec(filename: string) = else: print("[NipBox] Syscall sent successfully") +proc do_dd(arg: string) = + var subcmd = newStringOfCap(32) + var rest = newStringOfCap(128) + var i = 0 + var space = false + while i < arg.len: + if not space and arg[i] == ' ': + space = true + elif not space: + subcmd.add(arg[i]) + else: + rest.add(arg[i]) + i += 1 + + if subcmd == "read": + let sector = parseIntSimple(rest) + print("[dd] Reading Sector " & $sector) + var buf: array[512, byte] + nexus_blk_read(sector, addr buf[0], 512) + var hex = "" + for j in 0 ..< 16: + let b = buf[j] + hex.add(toHexChar((b shr 4) and 0xF)) + hex.add(toHexChar(b and 0xF)) + hex.add(' ') + print("HEX: " & hex & "...") + elif subcmd == "write": + var sectorStr = newStringOfCap(32) + var payload = newStringOfCap(128) + var j = 0 + var space2 = false + while j < rest.len: + if not space2 and rest[j] == ' ': + space2 = true + elif not space2: + sectorStr.add(rest[j]) + else: + payload.add(rest[j]) + j += 1 + let sector = parseIntSimple(sectorStr) + print("[dd] Writing Sector " & $sector & ": " & payload) + var buf: array[512, byte] + for k in 0 ..< 512: buf[k] = 0 + for k in 0 ..< payload.len: + if k < 512: buf[k] = byte(payload[k]) + nexus_blk_write(sector, addr buf[0], 512) + else: + print("Usage: dd read | dd write ") + proc do_help() = print("NipBox v0.2 (Sovereign)") - print("Commands: echo, cat, ls, matrix, exec, help, exit") + print("Commands: echo, cat, ls, matrix, exec, dd, help, exit") # --- 4. MAIN LOOP --- +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: + if read_pos >= read_len: + read_pos = 0 + poll_network() # Keep network alive while waiting + read_len = int(read(0, addr read_buffer[0], 128)) + if read_len <= 0: return false # Or yield/retry? + let c = read_buffer[read_pos] + read_pos += 1 + if c == '\n': return true + elif c != '\r': buf.add(c) + 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 + break if inputBuffer.len == 0: continue - # Simple manual parsing - - # Reset manual parsing + # Parse Cmd/Arg 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 not spaceFound: cmd.add(c) + else: arg.add(c) + # DEBUG PARSING + print_raw("CMD_DEBUG: '") + print_raw(cmd) + print_raw("' LEN: ") + # print($cmd.len) # Need int to string conversion if $ not working + # Manual int string + var ls = "" + var l = cmd.len + if l == 0: ls = "0" + while l > 0: + ls.add(char(l mod 10 + 48)) + l = l div 10 + # Reverse + var lsr = "" + var z = ls.len - 1 + while z >= 0: + lsr.add(ls[z]) + z -= 1 + print(lsr) + + # HEX DUMP CMD + var h = "" + for k in 0 ..< cmd.len: + let b = byte(cmd[k]) + h.add(toHexChar((b shr 4) and 0xF)) + h.add(toHexChar(b and 0xF)) + h.add(' ') + print("CMD_HEX: " & h) 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: - print_raw("Unknown command: ") - print(cmd) + elif cmd == "echo": do_echo(arg) + elif cmd == "matrix": do_matrix(arg) + elif cmd == "cat": do_cat(arg) + elif cmd == "ls": do_ls() + elif cmd == "exec": do_exec(arg) + elif cmd == "dd": do_dd(arg) + elif cmd == "help": do_help() + else: print("Unknown command: " & cmd) when isMainModule: main()