247 lines
6.4 KiB
Nim
247 lines
6.4 KiB
Nim
# src/npl/nipbox/nipbox.nim
|
|
|
|
import strutils
|
|
import std
|
|
import editor
|
|
|
|
# --- SOVEREIGN NETWORKING TYPES ---
|
|
type
|
|
EthAddr = array[6, byte]
|
|
|
|
EthHeader {.packed.} = object
|
|
dest: EthAddr
|
|
src: EthAddr
|
|
ethertype: uint16
|
|
|
|
ArpPacket {.packed.} = object
|
|
htype: uint16
|
|
ptype: uint16
|
|
hlen: uint8
|
|
plen: uint8
|
|
oper: uint16
|
|
sha: EthAddr
|
|
spa: uint32
|
|
tha: EthAddr
|
|
tpa: uint32
|
|
|
|
IcmpPacket {.packed.} = object
|
|
const_type: uint8
|
|
code: uint8
|
|
checksum: uint16
|
|
id: uint16
|
|
seq: uint16
|
|
|
|
const
|
|
ETHERTYPE_ARP = 0x0608
|
|
ETHERTYPE_IP = 0x0008
|
|
ARP_OP_REQUEST = 0x0100
|
|
ARP_OP_REPLY = 0x0200
|
|
IP_PROTO_ICMP = 1
|
|
|
|
const MY_IP: uint32 = 0x0F02000A
|
|
const MY_MAC: EthAddr = [0x52.byte, 0x54.byte, 0x00.byte, 0x12.byte, 0x34.byte, 0x56.byte]
|
|
|
|
# --- 2. HELPERS ---
|
|
|
|
proc print(s: string) =
|
|
if s.len > 0:
|
|
discard write(cint(1), unsafeAddr s[0], csize_t(s.len))
|
|
var nl = "\n"
|
|
discard write(cint(1), unsafeAddr nl[0], 1)
|
|
|
|
proc print_raw(s: string) =
|
|
if s.len > 0:
|
|
discard write(cint(1), unsafeAddr s[0], csize_t(s.len))
|
|
|
|
# --- 3. LOGIC MODULES ---
|
|
|
|
var net_buf: array[1536, byte]
|
|
|
|
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])
|
|
if (len mod 2) != 0:
|
|
let ptr8 = cast[ptr UncheckedArray[byte]](buf)
|
|
sum += uint32(ptr8[len-1])
|
|
while (sum shr 16) > 0:
|
|
sum = (sum and 0xFFFF) + (sum shr 16)
|
|
return uint16(not sum)
|
|
|
|
proc handle_arp(rx_len: int) =
|
|
let eth = cast[ptr EthHeader](addr net_buf[0])
|
|
let arp = cast[ptr ArpPacket](addr net_buf[14])
|
|
if arp.tpa == MY_IP and arp.oper == ARP_OP_REQUEST:
|
|
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:
|
|
icmp.const_type = 0
|
|
icmp.checksum = 0
|
|
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))
|
|
|
|
# --- CMDS ---
|
|
|
|
proc do_mkfs() =
|
|
print("[mkfs] Partitioning Ledger...")
|
|
var sb: array[512, byte]
|
|
sb[0] = 0x53; sb[1] = 0x46; sb[2] = 0x53; sb[3] = 0x31
|
|
sb[4] = 0x00; sb[5] = 0x00; sb[6] = 0x00; sb[7] = 0x02
|
|
sb[12] = 0x01
|
|
nexus_blk_write(0, addr sb[0], 512)
|
|
var zero: array[512, byte]
|
|
for i in 0 ..< 512: zero[i] = 0
|
|
nexus_blk_write(1, addr zero[0], 512)
|
|
print("[mkfs] Complete.")
|
|
|
|
proc do_cat(filename: string) =
|
|
let fd = open(cstring(filename), 0)
|
|
if fd < 0:
|
|
print("cat: error opening " & filename)
|
|
return
|
|
var buf: array[1024, char]
|
|
while true:
|
|
let n = read(fd, addr buf[0], 1024)
|
|
if n <= 0: break
|
|
discard write(cint(1), addr buf[0], csize_t(n))
|
|
discard close(fd)
|
|
print("")
|
|
|
|
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)
|
|
|
|
proc start_editor(filename: string) =
|
|
editor.start_editor(filename)
|
|
|
|
# --- ENGINE ---
|
|
|
|
proc dispatch_command(input: string)
|
|
|
|
proc run_script(filename: string) =
|
|
if filename.len == 0: return
|
|
print("[Init] Sourcing " & filename & "...")
|
|
let fd = open(cstring(filename), 0)
|
|
if fd < 0:
|
|
print("[Init] Script not found: " & filename)
|
|
return
|
|
var line = ""
|
|
var buf: array[1, char]
|
|
while true:
|
|
let n = read(fd, addr buf[0], 1)
|
|
if n <= 0: break
|
|
if buf[0] == '\n':
|
|
let t = line.strip()
|
|
if t.len > 0 and not t.startsWith("#"):
|
|
print_raw("+ " & t & "\n")
|
|
dispatch_command(t)
|
|
line = ""
|
|
elif buf[0] != '\r':
|
|
line.add(buf[0])
|
|
|
|
let t = line.strip()
|
|
if t.len > 0 and not t.startsWith("#"):
|
|
print_raw("+ " & t & "\n")
|
|
dispatch_command(t)
|
|
|
|
discard close(fd)
|
|
print("[Init] Done.")
|
|
|
|
proc dispatch_command(input: string) =
|
|
let trimmed = input.strip()
|
|
if trimmed.len == 0: return
|
|
|
|
var cmd = ""
|
|
var arg = ""
|
|
var space = false
|
|
for c in trimmed:
|
|
if not space and c == ' ': space = true
|
|
elif not space: cmd.add(c)
|
|
else: arg.add(c)
|
|
|
|
if cmd == "exit": exit(0)
|
|
elif cmd == "echo": print(arg)
|
|
elif cmd == "cat": do_cat(arg)
|
|
elif cmd == "ls": do_ls()
|
|
elif cmd == "mkfs": do_mkfs()
|
|
elif cmd == "mount": discard nexus_syscall(0x204, 0)
|
|
elif cmd == "matrix":
|
|
if arg == "on": discard nexus_syscall(0x100, 1)
|
|
else: discard nexus_syscall(0x100, 0)
|
|
elif cmd == "ed": start_editor(arg)
|
|
elif cmd == "source": run_script(arg)
|
|
elif cmd == "help":
|
|
print("NipBox v0.4 (Sovereign Supervisor)")
|
|
print("echo, cat, ls, mkfs, mount, matrix, ed, source, exit")
|
|
else:
|
|
print("Unknown command: " & cmd)
|
|
|
|
proc main() =
|
|
print("\n╔═══════════════════════════════════════╗")
|
|
print("║ SOVEREIGN SUPERVISOR v0.4 ACTIVE ║")
|
|
print("╚═══════════════════════════════════════╝")
|
|
|
|
# Auto-Mount
|
|
discard nexus_syscall(0x204, 0)
|
|
|
|
# Init
|
|
run_script("/etc/init.nsh")
|
|
|
|
print_raw("\nroot@nexus:# ")
|
|
var inputBuffer = ""
|
|
while true:
|
|
poll_network()
|
|
var c: char
|
|
if nexus_read_nonblock(0, addr c, 1) > 0:
|
|
if c == '\n' or c == '\r':
|
|
print_raw("\n")
|
|
dispatch_command(inputBuffer)
|
|
inputBuffer = ""
|
|
print_raw("root@nexus:# ")
|
|
elif c == '\b' or c == char(127):
|
|
if inputBuffer.len > 0:
|
|
print_raw("\b \b")
|
|
inputBuffer.setLen(inputBuffer.len - 1)
|
|
else:
|
|
inputBuffer.add(c)
|
|
var s = ""
|
|
s.add(c)
|
|
print_raw(s)
|
|
nexus_yield()
|
|
|
|
when isMainModule: main()
|