# SPDX-License-Identifier: LSL-1.0
# Copyright (c) 2026 Markus Maiwald
# Stewardship: Self Sovereign Society Foundation
#
# This file is part of the Nexus Sovereign Core.
# See legal/LICENSE_SOVEREIGN.md for license terms.

# Nexus Sovereign Core: Kernel Implementation
# target Bravo: Complete Build Unification

import ring, fiber, ion, sched, pty, cspace, ontology, channels, fastpath, utcp
import fs/vfs, fs/tar, fs/sfs
import loader/elf
import ../libs/membrane/term
import ../libs/membrane/libc as libc_impl

const
  MAX_WORKERS* = 8
  MAX_FIBER_STACK* = 128 * 1024
  SYSTABLE_BASE* = 0x83000000'u64

# Export Nim Timer Handler for HAL (Zig calls this)
proc rumpk_timer_handler() {.exportc, cdecl, used.} =
  discard

# --- EXTERNAL SYMBOLS ---
proc ion_get_phys(id: uint16): uint64 {.importc, cdecl.}
proc rumpk_net_init() {.importc, cdecl.}
proc virtio_net_poll() {.importc, cdecl.}
proc virtio_blk_read(sector: uint64, buf: ptr byte) {.importc, cdecl.}
proc virtio_blk_write(sector: uint64, buf: ptr byte) {.importc, cdecl.}
proc fb_kern_get_addr(): uint64 {.importc, cdecl.}
proc hal_io_init() {.importc, cdecl.}
proc console_write*(p: pointer, len: csize_t) {.importc, cdecl.}
proc nexshell_main() {.importc, cdecl.}
proc ion_get_virt(id: uint16): uint64 {.importc, cdecl.}

# InitRD Symbols
var initrd_start {.importc: "_initrd_start" .}: byte
var initrd_end {.importc: "_initrd_end" .}: byte

# Globals
var
  fiber_ion, fiber_subject, fiber_child, fiber_compositor, fiber_nexshell, fiber_netswitch: FiberObject
  stack_ion, stack_subject, stack_child, stack_compositor, stack_nexshell, stack_netswitch: array[MAX_FIBER_STACK, byte]
  subject_loading_path: array[64, char] = [ '/', 's', 'y', 's', 'r', 'o', '/', 'b', 'i', 'n', '/', 'm', 'k', 's', 'h', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' ]
  matrix_enabled: bool = false
  active_fibers_arr: array[16, ptr FiberObject]

# Trace logic
proc kprint*(s: cstring) {.exportc, cdecl.} =
  if s != nil: 
    var i = 0
    let p = cast[ptr UncheckedArray[char]](s)
    while p[i] != '\0': i += 1
    console_write(cast[pointer](s), csize_t(i))

proc kprintln*(s: cstring) {.exportc, cdecl.} =
  kprint(s); kprint("\n")

proc kprint_hex*(val: uint64) {.exportc, cdecl.} =
  proc uart_print_hex(val: uint64) {.importc, cdecl.}
  uart_print_hex(val)

proc kprint_hex8*(val: uint8) {.exportc, cdecl.} =
  proc uart_print_hex8(val: uint8) {.importc, cdecl.}
  uart_print_hex8(val)

# ION Unified Memory Manager shim
proc ion_alloc*(): IonPacket =
  var id: uint16
  let phys = ion_alloc_raw(addr id)
  if phys == 0: return IonPacket()
  let virt = ion_get_virt(id)
  return IonPacket(data: cast[ptr UncheckedArray[byte]](virt), phys: phys, len: 0, id: id)

# Helper: Fiber Sleep
proc fiber_sleep*(ms: uint64) {.exportc, cdecl.} =
  let now = sched_get_now_ns()
  current_fiber.sleep_until = now + (ms * 1_000_000)
  fiber_yield()

proc k_starts_with(s, prefix: cstring): bool =
  let ps = cast[ptr UncheckedArray[char]](s)
  let pp = cast[ptr UncheckedArray[char]](prefix)
  var i = 0
  while pp[i] != '\0':
    if ps[i] == '\0' or ps[i] != pp[i]: return false
    i += 1
  return true

proc k_zero_mem(p: pointer, size: uint64) =
  var addr_val = cast[uint64](p)
  var remaining = size
  
  # 1. Handle unaligned leading bytes
  while (addr_val mod 8 != 0) and (remaining > 0):
    cast[ptr byte](addr_val)[] = 0
    addr_val += 1
    remaining -= 1
    
  # 2. Optimized 64-bit stores for the bulk
  let count = remaining div 8
  if count > 0:
    let p64 = cast[ptr UncheckedArray[uint64]](addr_val)
    for i in 0 ..< int(count):
      p64[i] = 0
    
    addr_val += uint64(count * 8)
    remaining -= uint64(count * 8)
  
  # 3. Handle trailing bytes
  while remaining > 0:
    cast[ptr byte](addr_val)[] = 0
    addr_val += 1
    remaining -= 1

proc kload_phys(path: cstring, phys_offset: uint64): uint64 =
  # The Summoner: Load ELF from VFS into isolated physical memory
  let fd = ion_vfs_open(path, 0)
  if fd < 0:
    kprint("[Loader] Error: Could not open '"); kprint(path); kprintln("'")
    return 0
  
  var ehdr: Elf64_Ehdr
  if ion_vfs_read(fd, addr ehdr, uint64(sizeof(ehdr))) != int64(sizeof(ehdr)):
    kprintln("[Loader] Error: ELF header read failed")
    discard ion_vfs_close(fd)
    return 0
  
  if ehdr.e_ident[0] != 0x7F or ehdr.e_ident[1] != 'E'.uint8:
     kprintln("[Loader] Error: Invalid ELF magic")
     discard ion_vfs_close(fd)
     return 0

  # Programs are at /sysro in the TAR
  # We need to skip the /sysro prefix for tar.vfs_read_at
  # or better, just use the path as provided but tar.nim expects no leading /
  var tar_path = path
  if path[0] == '/':
     tar_path = cast[cstring](cast[uint64](path) + 1)
  if k_starts_with(path, "/sysro"):
     tar_path = cast[cstring](cast[uint64](path) + 6)
     if tar_path[0] == '/': tar_path = cast[cstring](cast[uint64](tar_path) + 1)

  for i in 0 ..< int(ehdr.e_phnum):
     var phdr: Elf64_Phdr
     let ph_offset = ehdr.e_phoff + uint64(i * int(ehdr.e_phentsize))
     if tar.vfs_read_at(tar_path, addr phdr, uint64(sizeof(phdr)), ph_offset) != int64(sizeof(phdr)):
        continue

     if phdr.p_type == PT_LOAD:
        # Enable S-mode access to U-mode pages (SUM=1)
        {.emit: """asm volatile ("li t1, 0x40000; csrs sstatus, t1" : : : "t1");""" .}
        
        let dest = cast[ptr UncheckedArray[byte]](phdr.p_vaddr)

        if phdr.p_filesz > 0:
           if tar.vfs_read_at(tar_path, dest, phdr.p_filesz, phdr.p_offset) != int64(phdr.p_filesz):
              kprintln("[Loader] Error: Segment load failed")
        
        if phdr.p_memsz > phdr.p_filesz:
           let bss_start = phdr.p_vaddr + phdr.p_filesz
           let bss_len = phdr.p_memsz - phdr.p_filesz
           kprint("  - Zeroing BSS: VA="); kprint_hex(bss_start); kprint(" Len="); kprint_hex(bss_len); kprintln("")
           k_zero_mem(cast[pointer](bss_start), bss_len)
        
        {.emit: """asm volatile ("li t1, 0x40000; csrc sstatus, t1" : : : "t1");""" .}
  
  # ⚡ ARCH-SYNC: Flush I-Cache after loading new code
  {.emit: """asm volatile ("fence.i" : : : "memory");""" .}
  
  discard ion_vfs_close(fd)
  return ehdr.e_entry

# --- FIBER ENTRIES ---

proc subject_fiber_entry() {.cdecl.} =
  let fid = current_fiber.id
  kprint("[Subject:"); kprint_hex(fid); kprint("] Fiber Entry reached. PA_Offset="); kprint_hex(current_fiber.phys_offset); kprintln("")
  
  # Use new robust loader
  kprint("[Loader:"); kprint_hex(fid); kprint("] Loading: "); kprintln(cast[cstring](addr subject_loading_path[0]))
  
  # Load into Cellular Slot (phys_offset)
  let entry_addr = kload_phys(cast[cstring](addr subject_loading_path[0]), current_fiber.phys_offset)
  
  if entry_addr != 0:
    kprint("[Subject:"); kprint_hex(fid); kprint("] Entering Payload at: "); kprint_hex(entry_addr); kprintln("")
    proc hal_enter_userland(entry, systable, sp: uint64) {.importc, cdecl.}
    var sp = current_fiber.user_sp_init
    if sp == 0:
       # Fallback (Legacy/Init) - Top of the 64MB Sentinel Cell
       sp = 0x8BFFFFF0'u64
    
    kprint("[Subject:"); kprint_hex(fid); kprint("] JUMPING to Userland. SP="); kprint_hex(sp); kprintln("")
    hal_enter_userland(entry_addr, SYSTABLE_BASE, sp)
  else:
    kprint("[Subject:"); kprint_hex(fid); kprintln("] Loader failed to find/load payload!")
  while true: fiber_sleep(1000)

proc compositor_fiber_entry() {.cdecl.} =
  kprintln("[Compositor] Fiber Entry reached.")
  while true:
    if matrix_enabled:
      fiber_sleep(100)
    else:
      term.term_render()
      fiber_sleep(33) # 30Hz

proc mm_create_worker_map(stack_base: uint64, stack_size: uint64, packet_addr: uint64, phys_base: uint64, region_size: uint64): uint64 {.importc, cdecl.}

proc setup_mksh_stack(stack_base: pointer, stack_size: int): uint64 =
  var sp = cast[uint64](stack_base) + cast[uint64](stack_size)
  sp = sp and not 15'u64 # Align 16
  
  # Term String
  let term_str = "TERM=nexus\0"
  sp -= uint64(term_str.len)
  copyMem(cast[pointer](sp), unsafeAddr term_str[0], term_str.len)
  let term_addr = sp
  
  # Path String
  let path_str = "/bin/mksh\0"
  sp -= uint64(path_str.len)
  copyMem(cast[pointer](sp), unsafeAddr path_str[0], path_str.len)
  let path_addr = sp
  
  sp = sp and not 15'u64 # Align 16
  
  # Auxv (0, 0)
  sp -= 16
  cast[ptr uint64](sp)[] = 0
  cast[ptr uint64](sp+8)[] = 0
  
  # Envp (term, NULL)
  sp -= 16
  cast[ptr uint64](sp)[] = term_addr
  cast[ptr uint64](sp+8)[] = 0
  
  # Argv (path, NULL)
  sp -= 16
  cast[ptr uint64](sp)[] = path_addr
  cast[ptr uint64](sp+8)[] = 0
  
  # Argc (1)
  sp -= 8
  cast[ptr uint64](sp)[] = 1
  
  return sp

proc ion_fiber_entry() {.cdecl.} =
  kprintln("[ION] Fiber Entry reached.")
  while true:
    var pkt: CmdPacket
    if chan_cmd.recv(pkt):
      case CmdType(pkt.kind):
      of CMD_SYS_EXIT:
         kprintln("[ION] Restarting Subject...")
         init_fiber(addr fiber_subject, subject_fiber_entry, addr stack_subject[0], sizeof(stack_subject))
      of CMD_ION_FREE:
         ion_free_raw(uint16(pkt.arg))
      of CMD_GPU_MATRIX:
         matrix_enabled = (pkt.arg != 0)
      of CMD_SPAWN_FIBER:
         # Fiber spawn requested 
         # Hardcoded for verification to confirm isolation
         let target = "/sysro/bin/mksh"
         kprint("[ION] Spawning child fiber for: "); kprintln(target)
         
         # Copy into loading path
         copyMem(addr subject_loading_path[0], unsafeAddr target[0], target.len + 1)
         
         # Allocate PTY
         let pid = pty_alloc()
         if pid < 0:
           kprintln("[ION] Failed to allocate PTY for child!")
         
         # Re-initialize fiber_child with the requested binary
         init_fiber(addr fiber_child, subject_fiber_entry, addr stack_child[0], sizeof(stack_child))
         
         # Phase 40: Set PTY & Stack
         fiber_child.pty_id = pid
         fiber_child.user_sp_init = setup_mksh_stack(addr stack_child[0], sizeof(stack_child))
         
         # 🏛️ CELLULAR ALLOCATION (SPEC-202 Rev 2)
         # Sentinel (Init) takes 0x88000000 - 0x8C000000 (64MB)
         # Mksh (First Child) starts in the 'Wild' at 0x8C000000
         let cell_base = 0x8C000000'u64
         fiber_child.phys_offset = cell_base
         
         # Allocate 64MB Slot for Mksh (Needs >32MB for BSS)
         let cell_size = 64 * 1024 * 1024'u64
         fiber_child.satp_value = mm_create_worker_map(cast[uint64](addr stack_child[0]), uint64(sizeof(stack_child)), SYSTABLE_BASE, cell_base, cell_size)
         kprintln("[ION] Child fiber spawned successfully")
      else: discard
    fiber_sleep(10_000_000) # 10ms

proc rumpk_yield_internal*() {.exportc, cdecl.} =
  # Switch back to the main dispatcher loop
  switch(active_fibers_arr[6])

proc fiber_yield*() {.exportc, cdecl.} =
  current_fiber.wants_yield = true
  rumpk_yield_internal()

proc fiber_netswitch_entry() {.cdecl.} =
  kprintln("[NetSwitch] Traffic Engine Online")
  
  # Iron Firewall: Verify channel sovereignty before operation
  if chan_netswitch_rx.ring == nil:
    kprintln("[CRITICAL] NetSwitch RX channel uninitialized - HALTING")
    while true: fiber_yield()
  
  if chan_net_rx.ring == nil or chan_net_tx.ring == nil:
    kprintln("[CRITICAL] Global net rings uninitialized - HALTING")
    while true: fiber_yield()
  
  kprintln("[NetSwitch] Channels verified. Sovereignty confirmed.")
  
  while true:
     var pkt: IonPacket
     
     # INGRESS: Driver -> NetSwitch -> Fast Path Filter
     if chan_netswitch_rx.recv(pkt):
        # SPEC-700: Fast Path Bypass for UTCP Tunnel (UDP/9999)
        if is_utcp_tunnel(pkt.data, pkt.len):
           # FAST PATH: Bypass LwIP entirely
           var utcp_len = pkt.len
           let utcp_data = strip_tunnel_headers(pkt.data, utcp_len)
           if utcp_data != nil:
              utcp_handle_packet(utcp_data, utcp_len)
              ion_free_raw(pkt.id)
           else:
              kprintln("[FastPath] Strip failed - dropping")
              ion_free_raw(pkt.id)
        else:
           # SLOW PATH: Route to LwIP via chan_net_rx
           if not chan_net_rx.send(pkt):
              ion_free_raw(pkt.id)
     
     # EGRESS: Subject (chan_net_tx) -> NetSwitch -> Driver (ion_tx_push)
     if chan_net_tx.recv(pkt):
        kprintln("[NetSwitch] Forwarding Egress")
        var res = ion_tx_push(pkt)
        if not res: kprintln("[NetSwitch] Drop (TX Full)")
     
     # Manual Polling (Interrupts Disabled)
     virtio_net_poll()
     
     # Prevent Starvation
     fiber_sleep(1)

proc ion_ingress*(id: uint16, len: uint16, offset: uint16) {.exportc, cdecl.} =
  ## Handle packet from Network Driver
  # Get actual physical address and apply driver offset
  let base_phys = ion_get_phys(id)
  let base_virt = ion_get_virt(id)
  
  # Create packet with pointers pointing DIRECTLY to the Ethernet frame
  let pkt = IonPacket(
    id: id, 
    len: len, 
    phys: base_phys + uint64(offset),
    data: cast[ptr UncheckedArray[byte]](cast[uint64](base_virt) + uint64(offset))
  )
  
  if not chan_netswitch_rx.send(pkt):
    ion_free_raw(id)

proc ion_push_stdin*(p: pointer, len: csize_t) {.exportc, cdecl.} =
  if chan_input.ring == nil: return
  var pkt = ion_alloc()
  if pkt.data == nil: return
  let to_copy = if int(len) < 2048: int(len) else: 2048
  copyMem(pkt.data, p, to_copy)
  pkt.len = uint16(to_copy)
  if fiber_subject.sleep_until == 0xFFFFFFFFFFFFFFFF'u64: fiber_subject.sleep_until = 0
  discard chan_input.send(pkt)

proc k_check_deferred_yield*() {.exportc, cdecl.} =
  if current_fiber != nil and current_fiber.wants_yield:
    current_fiber.wants_yield = false
    fiber_yield()

proc k_handle_exception*(scause, sepc, stval: uint) {.exportc, cdecl.} =
  kprint("[IMMUNE] EXCEPTION: scause="); kprint_hex(scause)
  kprint(" sepc="); kprint_hex(sepc)
  kprint(" stval="); kprint_hex(stval)
  kprintln("")
  kprintln("[IMMUNE] System HALTING (Trap Loop Prevention).")
  while true:
     {.emit: "asm volatile(\"wfi\");".}

proc wrapper_vfs_write(fd: int32, buf: pointer, count: uint64): int64 {.cdecl.} =
  return ion_vfs_write(fd, buf, count)

# --- SYSCALL HANDLER ---

proc k_handle_syscall*(nr, a0, a1, a2: uint): uint {.exportc, cdecl.} =
  # if nr != 0x100:
  #   kprint("[Syscall] NR: "); kprint_hex(nr); kprintln("")

  case nr:
  of 0x01: # EXIT
    var pkt = CmdPacket(kind: uint32(CmdType.CMD_SYS_EXIT), arg: a0)
    discard chan_cmd.send(pkt)
    current_fiber.wants_yield = true
    return 0
  of 0x65: # NANOSLEEP
    let now = sched_get_now_ns()
    kprint("Slp: "); kprint_hex(now); kprint(" "); kprint_hex(a0); kprint("\n")
    current_fiber.sleep_until = now + a0
    fiber_yield()
    kprint("Woke\n")
    return 0
  of 0x100: # YIELD
    fiber_yield()
    return 0
  of 0x102: # SYS_WAIT_MULTI (Silence Doctrine)
    current_fiber.blocked_on_mask = a0
    current_fiber.is_blocked = true
    fiber_yield()
    return 0
  of 0x200: # OPEN
    # return uint(libc_impl.libc_impl_open(cast[cstring](a0), int(a1)))
    return 0
  of 0x201: # CLOSE
    # return uint(libc_impl.libc_impl_close(int(a0)))
    return 0
  of 0x202: # LIST
    return uint(ion_vfs_list(cast[pointer](a0), uint64(a1)))
  of 0x203: # READ
    var vres = -2
    if a0 == 0 or vres == -2:
      let pid = if current_fiber.pty_id >= 0: current_fiber.pty_id else: 0
      while true:
        if pty_has_data_for_slave(pid):
          var buf: array[1, byte]
          let n = pty_read_slave(PTY_SLAVE_BASE + pid, addr buf[0], 1)
          if n > 0:
            cast[ptr UncheckedArray[byte]](a1)[0] = buf[0]
            return 1
        var pkt: IonPacket
        if chan_input.recv(pkt):
          let n = if uint64(pkt.len) < a2: uint64(pkt.len) else: a2
          if n > 0: 
            # copyMem(cast[pointer](a1), cast[pointer](pkt.data), int(n))
            # console_write(pkt.data, csize_t(n))
            let data = cast[ptr UncheckedArray[byte]](pkt.data)
            for i in 0 ..< int(n): pty_push_input(pid, char(data[i]))
          ion_free_raw(pkt.id)
          # Loop again to read from PTY
        else:
          current_fiber.sleep_until = 0xFFFFFFFFFFFFFFFF'u64
          fiber_yield()
    return uint(vres)
  of 0x204: # WRITE
    if a0 == 1 or a0 == 2:
       console_write(cast[pointer](a1), csize_t(a2))
       let pid = if current_fiber.pty_id >= 0: current_fiber.pty_id else: 0
       discard pty_write_slave(PTY_SLAVE_BASE + pid, cast[ptr byte](a1), int(a2))
       return a2
    # var vres = libc_impl.libc_impl_write(int(a0), cast[pointer](a1), uint64(a2))
    var vres = -1
    return uint(vres)
  of 0x205: return 0 # IOCTL stub
  of 0x600: # EXECV (Legacy - use SYS_SPAWN_FIBER instead)
    # Manual copy path to subject_loading_path
    let p = cast[ptr UncheckedArray[char]](a0)
    var i = 0
    while p[i] != '\0' and i < 63:
      subject_loading_path[i] = p[i]
      i += 1
    subject_loading_path[i] = '\0'
    var pkt = CmdPacket(kind: uint32(CmdType.CMD_SYS_EXIT), arg: 0)
    discard chan_cmd.send(pkt)
    current_fiber.wants_yield = true
    return 0
  of 0x300: # SYS_SPAWN_FIBER - Spawn new fiber with target binary
    # Copy path to subject_loading_path for next spawn
    let p = cast[ptr UncheckedArray[char]](a0)
    var i = 0
    while p[i] != '\0' and i < 63:
      subject_loading_path[i] = p[i]
      i += 1
    subject_loading_path[i] = '\0'
    kprint("[Kernel] Spawning fiber for: ")
    kprintln(cast[cstring](addr subject_loading_path[0]))
    # Re-initialize fiber_subject with new binary
    # The ION fiber will pick this up and restart the Subject fiber
    var pkt = CmdPacket(kind: uint32(CMD_SPAWN_FIBER), arg: 0)
    discard chan_cmd.send(pkt)
    # Return fiber ID (always 4 for Subject currently)
    return 4
  else: return 0

# --- KERNEL BOOT ---

proc ion_wait_multi*(mask: uint64): int32 {.exportc, cdecl.} =
  ## Block the current fiber until data is available on any of the masked slots
  current_fiber.blocked_on_mask = mask
  current_fiber.is_blocked = true
  fiber_yield()
  return 0

proc kmain() {.exportc, cdecl.} =
  var next_mmio_addr {.importc: "virtio_pci_next_mmio_addr", nodecl.}: uint32
  kprint("\n[Kernel] next_mmio_addr check: ")
  kprint_hex(uint64(next_mmio_addr))
  kprintln("\nNexus Sovereign Core v1.1.2 Starting...")
  
  # HAL Hardware Inits
  # rumpk_net_init() -- Moved below
  
  ion_pool_init()
  proc mm_init() {.importc, cdecl.}
  proc mm_enable_kernel_paging() {.importc, cdecl.}
  mm_init()
  mm_enable_kernel_paging()
  
  # HAL Hardware Inits (Moved after ION/MM init)
  rumpk_net_init()
  
  # Ground Zero Phase 1: Initialize Capability System (SPEC-051)
  init_cspace_subsystem()
  kprintln("[CSpace] Capability system initialized")
  
  # Ground Zero Phase 2: Initialize System Truth Ledger (SPEC-060)
  init_stl_subsystem()
  let boot_id = emit_system_boot()
  
  ion_init_input()
  ion_init_network() # Initialize net rings early
  hal_io_init()
  pty_init()
  discard pty_alloc()
  term.term_init()

  vfs_init(addr initrd_start, addr initrd_end)
  vfs_mount_init()
  
  # DEBUG: List Files
  kprintln("[VFS] Boot Inventory:")
  var buf: array[512, byte]
  let n = ion_vfs_list(addr buf[0], 512)
  if n > 0:
     kprintln(cast[cstring](addr buf[0]))
  
  # Set initial loading path for Init (Subject)
  let initial_path = "/sysro/init"
  copyMem(addr subject_loading_path[0], unsafeAddr initial_path[0], initial_path.len + 1)
  kprint("[ION] Subject Zero Path: "); kprintln(cast[cstring](addr subject_loading_path[0]))

  let sys = cast[ptr SysTable](SYSTABLE_BASE)
  sys.fn_vfs_open = ion_vfs_open
  sys.fn_vfs_read = ion_vfs_read
  sys.fn_vfs_list = ion_vfs_list
  sys.fn_vfs_write = wrapper_vfs_write
  sys.fn_wait_multi = ion_wait_multi
  # Point to user slab allocator (shared memory) instead of kernel pool
  sys.fn_ion_alloc = ion_user_alloc_systable
  sys.fn_ion_free = ion_user_free_systable
  
  # Populate Network MAC
  proc virtio_net_get_mac(out_mac: ptr byte) {.importc, cdecl.}
  virtio_net_get_mac(addr sys.net_mac[0])
  kprint("[Kernel] MAC Address: ")
  for i in 0 ..< 6:
    kprint_hex8(sys.net_mac[i])
    if i < 5: kprint(":")
  kprintln("")

  # Initialize user slab bitmap (at offset 0x100, 16 bytes for 128 slots)
  let bitmap = cast[ptr array[16, byte]](SYSTABLE_BASE + 0x100)
  for i in 0 ..< 16:
    bitmap[i] = 0  # All slots free

  # Shared Rings Setup (SYSTABLE area)
  # Layout: 0x0000=SysTable, 0x0100=Bitmap, 0x2000=RX, 0x4000=TX, 0x6000=Event, 0x8000=CMD, 0xA000=Input
  # 0xC000=Net_RX, 0xE000=Net_TX, 0x10000=User_Slab
  # Each ring is ~6KB-8KB, so we need 8KB (0x2000) spacing.
  chan_rx.ring = cast[ptr HAL_Ring[IonPacket]](SYSTABLE_BASE + 0x2000)
  chan_tx.ring = cast[ptr HAL_Ring[IonPacket]](SYSTABLE_BASE + 0x4000)
  let ring_event = cast[ptr HAL_Ring[IonPacket]](SYSTABLE_BASE + 0x6000)
  chan_cmd.ring = cast[ptr HAL_Ring[CmdPacket]](SYSTABLE_BASE + 0x8000)
  chan_input.ring = cast[ptr HAL_Ring[IonPacket]](SYSTABLE_BASE + 0xA000)
  
  # Network Rings (Shared with Userland)
  chan_net_rx.ring = cast[ptr HAL_Ring[IonPacket]](SYSTABLE_BASE + 0xC000)
  chan_net_tx.ring = cast[ptr HAL_Ring[IonPacket]](SYSTABLE_BASE + 0xE000)
  
  # Initialize Shared Memory Rings
  chan_rx.ring.mask = 255; chan_tx.ring.mask = 255
  ring_event.mask = 255; chan_cmd.ring.mask = 255
  chan_input.ring.mask = 255
  chan_net_rx.ring.mask = 255; chan_net_tx.ring.mask = 255
  # Force reset pointers to zero
  chan_rx.ring.head = 0; chan_rx.ring.tail = 0
  chan_tx.ring.head = 0; chan_tx.ring.tail = 0
  ring_event.head = 0; ring_event.tail = 0
  chan_cmd.ring.head = 0; chan_cmd.ring.tail = 0
  chan_input.ring.head = 0; chan_input.ring.tail = 0
  chan_net_rx.ring.head = 0; chan_net_rx.ring.tail = 0
  chan_net_tx.ring.head = 0; chan_net_tx.ring.tail = 0

  sys.s_rx = chan_rx.ring; sys.s_tx = chan_tx.ring; sys.s_event = ring_event
  sys.s_cmd = chan_cmd.ring; sys.s_input = chan_input.ring
  
  # Map Network Rings (Now in shared memory)
  sys.s_net_rx = chan_net_rx.ring
  sys.s_net_tx = chan_net_tx.ring

  sys.magic = 0x4E585553
  sys.fb_addr = fb_kern_get_addr()
  sys.fb_width = 1920; sys.fb_height = 1080; sys.fb_stride = 1920 * 4; sys.fb_bpp = 32

  # Spawn Fibers
  fiber_ion.id = 1; fiber_nexshell.id = 2; fiber_compositor.id = 3
  fiber_subject.id = 4; fiber_child.id = 5; fiber_netswitch.id = 6
  
  init_fiber(addr fiber_ion, ion_fiber_entry, addr stack_ion[0], sizeof(stack_ion))
  let ion_spawn_id = emit_fiber_spawn(1, 0, boot_id)  # ION fiber
  discard ion_spawn_id
  
  init_fiber(addr fiber_compositor, compositor_fiber_entry, addr stack_compositor[0], sizeof(stack_compositor))
  let compositor_spawn_id = emit_fiber_spawn(3, 0, boot_id)  # Compositor fiber
  discard compositor_spawn_id
  
  init_fiber(addr fiber_nexshell, nexshell_main, addr stack_nexshell[0], sizeof(stack_nexshell))
  let shell_spawn_id = emit_fiber_spawn(2, 0, boot_id)  # NexShell fiber
  
  # NetSwitch Spawn
  init_fiber(addr fiber_netswitch, fiber_netswitch_entry, addr stack_netswitch[0], sizeof(stack_netswitch))
  let netswitch_spawn_id = emit_fiber_spawn(6, 0, boot_id)  # NetSwitch fiber
  discard netswitch_spawn_id
  
  init_fiber(addr fiber_subject, subject_fiber_entry, addr stack_subject[0], sizeof(stack_subject))
  let subject_spawn_id = emit_fiber_spawn(4, 0, boot_id)  # Subject fiber
  
  # Ground Zero Phase 1: Grant Initial Capabilities (SPEC-051)
  # Grant console I/O to NexShell (fiber 2)
  discard fiber_grant_channel(2, 0x1000, PERM_READ or PERM_WRITE)  # console.input
  discard emit_capability_grant(2, 2, 0x1000, 0, shell_spawn_id)  # Log event
  
  discard fiber_grant_channel(2, 0x1001, PERM_READ or PERM_WRITE)  # console.output
  discard emit_capability_grant(2, 2, 0x1001, 1, shell_spawn_id)  # Log event
  kprintln("[CSpace] Granted console capabilities to NexShell")
  
  # Grant console output to Subject (fiber 4) 
  discard fiber_grant_channel(4, 0x1001, PERM_WRITE)  # console.output (write-only)
  discard emit_capability_grant(4, 2, 0x1001, 0, subject_spawn_id)  # Log event
  kprintln("[CSpace] Granted output capability to Subject")

  # Grant Network I/O (RX/TX)
  # NetSwitch (Fiber 6): Full access to shuttle packets
  discard fiber_grant_channel(6, 0x500, PERM_READ or PERM_WRITE) # CMD_NET_TX
  discard fiber_grant_channel(6, 0x501, PERM_READ or PERM_WRITE) # CMD_NET_RX
  
  # Subject (Fiber 4): Needs to READ RX (0x501) and WRITE TX (0x500)
  discard fiber_grant_channel(4, 0x500, PERM_WRITE) # Can send packets
  discard fiber_grant_channel(4, 0x501, PERM_READ)  # Can receive packets
  kprintln("[CSpace] Granted network capabilities to NetSwitch and Subject")
  
  # Init (Subject) lives in Cell 0 (0x88000000) - Needs 64MB for large BSS
  fiber_subject.phys_offset = 0x88000000'u64
  let init_size = 64 * 1024 * 1024'u64
  fiber_subject.satp_value = mm_create_worker_map(cast[uint64](addr stack_subject[0]), uint64(sizeof(stack_subject)), SYSTABLE_BASE, fiber_subject.phys_offset, init_size)

  # Interrupt Setup
  asm "csrsi sstatus, 2"
  {.emit: "asm volatile(\"csrs sie, %0\" : : \"r\"(1L << 9));".}
  let plic_base = 0x0c000000'u64
  # Priority (each IRQ has a 4-byte priority register)
  cast[ptr uint32](plic_base + 40)[] = 1 # UART (IRQ 10: 10*4 = 40)
  # cast[ptr uint32](plic_base + 128)[] = 1 # VirtIO-Net (IRQ 32: 32*4 = 128)
  # cast[ptr uint32](plic_base + 132)[] = 1 # VirtIO-Net (IRQ 33: 33*4 = 132)
  # cast[ptr uint32](plic_base + 136)[] = 1 # VirtIO-Net (IRQ 34: 34*4 = 136)
  # cast[ptr uint32](plic_base + 140)[] = 1 # VirtIO-Net (IRQ 35: 35*4 = 140)
  
  # Enable (Supervisor Context 1)
  # IRQs 0-31
  # cast[ptr uint32](plic_base + 0x2000 + 0x80)[] = (1'u32 shl 10)
  # IRQs 32-63
  # cast[ptr uint32](plic_base + 0x2000 + 0x80 + 4)[] = 0x0000000F # Enable 32,33,34,35
  
  # Threshold
  cast[ptr uint32](plic_base + 0x201000)[] = 0
  
  active_fibers_arr[0] = addr fiber_ion; active_fibers_arr[1] = addr fiber_nexshell
  active_fibers_arr[2] = addr fiber_compositor; active_fibers_arr[3] = addr fiber_netswitch
  active_fibers_arr[4] = addr fiber_subject
  active_fibers_arr[5] = addr fiber_child
  active_fibers_arr[6] = current_fiber
  
  # Set Spectrums (Priorities)
  (addr fiber_ion).setSpectrum(Spectrum.Photon)
  (addr fiber_compositor).setSpectrum(Spectrum.Photon)
  (addr fiber_netswitch).setSpectrum(Spectrum.Photon)
  (addr fiber_nexshell).setSpectrum(Spectrum.Matter) # Interactive
  (addr fiber_subject).setSpectrum(Spectrum.Void)    # Untrusted Background
  (addr fiber_child).setSpectrum(Spectrum.Void)      # Child process (spawned)
  current_fiber.setSpectrum(Spectrum.Void)           # Main loop (dispatcher)
  
  # Ground Zero Phase 2: Introspection
  stl_print_summary()

  kprintln("[Rumpk] Multi-Fiber Dispatcher starting...")
  switch(addr fiber_ion)
  while true:
    if not sched_tick_spectrum(active_fibers_arr.toOpenArray(0, 5)):
       # The Silence Doctrine: Wait for Interrupt
       let next_wake = sched_get_next_wakeup(active_fibers_arr.toOpenArray(0, 5))
       let now = sched_get_now_ns()

       if next_wake > now and next_wake != 0xFFFFFFFFFFFFFFFF'u64:
           proc rumpk_timer_set_ns(ns: uint64) {.importc, cdecl.}
           # kprint("Interval: "); kprint_hex(next_wake - now); kprintln("")
           rumpk_timer_set_ns(next_wake - now) # Pass interval
       else:
           # No timer needed (or overdue), just WFI for other interrupts (IO)
           discard

       asm "csrsi sstatus, 2"
       asm "wfi"
