diff --git a/.zig-cache/h/42a82410c6e7cdd9b74bb29aa44181eb.txt b/.zig-cache/h/42a82410c6e7cdd9b74bb29aa44181eb.txt index 586c644..0bf31aa 100644 --- a/.zig-cache/h/42a82410c6e7cdd9b74bb29aa44181eb.txt +++ b/.zig-cache/h/42a82410c6e7cdd9b74bb29aa44181eb.txt @@ -1,8 +1,8 @@ 0 -12268 9459532 1767076443800031133 c56105a5a3a93a0d4d451c619dc2b349 0 /home/markus/zWork/_Git/Nexus/core/rumpk/build/nimcache/@mkernel.nim.c +10486 9461201 1767076985098986152 3747702445e0bcda6de1816ec7a47cdd 0 /home/markus/zWork/_Git/Nexus/core/rumpk/build/nimcache/@mkernel.nim.c 19164 69191110 1749873121000000000 fe5756ed84745fc96fd9dfb15050f599 0 /usr/lib/nim/nimbase.h 639 9459383 1767076381899751290 1b9448bcfa47e3161459266750e8ded4 0 /home/markus/zWork/_Git/Nexus/core/rumpk/core/include/limits.h 268 9459347 1767076422997272233 06a4c7da1c4987981a369ef3e003bda3 0 /home/markus/zWork/_Git/Nexus/core/rumpk/core/include/stddef.h -1172 78925833 1761046366000000000 69b529ccb10bbb5d826c563cf9b929c1 1 include/stdbool.h -31054 78925836 1761046366000000000 1df950c62cbc96dd5d9790733bbe6016 1 include/stdint.h +155 9459777 1767076495338437553 9cc523d7a8a3a0bbc7c7af0fabeafc0b 0 /home/markus/zWork/_Git/Nexus/core/rumpk/core/include/stdbool.h +924 9459799 1767076530759032485 73bc6834aef9958f6652470b63d7814b 0 /home/markus/zWork/_Git/Nexus/core/rumpk/core/include/stdint.h 499 9459330 1767076360432003062 357ccd6329b0128cce0610c1443c600d 0 /home/markus/zWork/_Git/Nexus/core/rumpk/core/include/string.h diff --git a/.zig-cache/z/1bbd978ef4c616d6b2fdeb39a550d19e b/.zig-cache/z/1bbd978ef4c616d6b2fdeb39a550d19e new file mode 100644 index 0000000..19c3fbb Binary files /dev/null and b/.zig-cache/z/1bbd978ef4c616d6b2fdeb39a550d19e differ diff --git a/build.sh b/build.sh index 3b32454..20aab81 100755 --- a/build.sh +++ b/build.sh @@ -1,6 +1,8 @@ #!/bin/bash -# Rumpk Build Script -# Builds Zig L0 + Nim L1 into a single ELF +# Rumpk Build Script - Freestanding Doctrine +# Pure Zig L0 + Nim L1, no C stubs, no glibc +# +# We are the standard library now. set -e @@ -8,7 +10,8 @@ RUMPK_DIR="$(cd "$(dirname "$0")" && pwd)" BUILD_DIR="$RUMPK_DIR/build" echo "╔═══════════════════════════════════════╗" -echo "║ RUMPK BUILD SYSTEM v0.1 ║" +echo "║ RUMPK FREESTANDING BUILD v0.2 ║" +echo "║ No glibc. Pure Sovereignty. ║" echo "╚═══════════════════════════════════════╝" echo "" @@ -17,25 +20,31 @@ mkdir -p "$BUILD_DIR" mkdir -p "$BUILD_DIR/nimcache" # ========================================================= -# Step 1: Compile Zig L0 (HAL) +# Step 1: Compile Zig L0 (HAL + Stubs) # ========================================================= -echo "[1/3] Compiling Zig L0 (HAL)..." +echo "[1/4] Compiling Zig L0 (HAL + libc stubs)..." +# Compile main.zig zig build-obj \ "$RUMPK_DIR/hal/main.zig" \ -target aarch64-freestanding-none \ -O ReleaseSmall \ -femit-bin="$BUILD_DIR/hal.o" +# Compile stubs.zig (our libc replacement) +zig build-obj \ + "$RUMPK_DIR/hal/stubs.zig" \ + -target aarch64-freestanding-none \ + -O ReleaseSmall \ + -femit-bin="$BUILD_DIR/stubs.o" + echo " → $BUILD_DIR/hal.o" +echo " → $BUILD_DIR/stubs.o" # ========================================================= # Step 2: Compile Nim L1 (Kernel) # ========================================================= -echo "[2/3] Compiling Nim L1 (Kernel)..." - -# Note: This requires careful Nim configuration for freestanding -# For now, we'll try direct compilation with clang +echo "[2/4] Compiling Nim L1 (Kernel)..." nim c \ --cpu:arm64 \ @@ -61,17 +70,6 @@ echo " → $BUILD_DIR/nimcache/*.c" # ========================================================= echo "[3/4] Compiling Nim C files..." -# First compile cstubs.c -echo " Compiling cstubs.c..." -zig cc \ - -target aarch64-freestanding-none \ - -ffreestanding \ - -fno-builtin \ - -I"$RUMPK_DIR/core/include" \ - -c "$RUMPK_DIR/core/cstubs.c" \ - -o "$BUILD_DIR/cstubs.o" - -# Now compile Nim C files for cfile in "$BUILD_DIR/nimcache"/*.c; do ofile="${cfile%.c}.o" zig cc \ @@ -89,9 +87,9 @@ done echo " → $BUILD_DIR/nimcache/*.o" # ========================================================= -# Step 4: Link Everything +# Step 4: Link Everything (NO LIBC!) # ========================================================= -echo "[4/4] Linking..." +echo "[4/4] Linking (freestanding, no libc)..." # Collect all Nim object files NIM_OBJS=$(find "$BUILD_DIR/nimcache" -name "*.o" 2>/dev/null | tr '\n' ' ') @@ -106,7 +104,7 @@ zig cc \ -nostdlib \ -T "$RUMPK_DIR/boot/linker.ld" \ "$BUILD_DIR/hal.o" \ - "$BUILD_DIR/cstubs.o" \ + "$BUILD_DIR/stubs.o" \ $NIM_OBJS \ -o "$BUILD_DIR/rumpk.elf" @@ -116,7 +114,10 @@ echo " → $BUILD_DIR/rumpk.elf" # Done # ========================================================= echo "" -echo "✅ Build complete!" +echo "✅ Freestanding build complete!" +echo "" +echo "Verification:" +echo " file $BUILD_DIR/rumpk.elf" echo "" echo "Run with:" echo " qemu-system-aarch64 -M virt -cpu cortex-a57 -nographic -kernel $BUILD_DIR/rumpk.elf" diff --git a/core/kernel.nim b/core/kernel.nim index 667c994..c6ffeb8 100644 --- a/core/kernel.nim +++ b/core/kernel.nim @@ -42,36 +42,14 @@ proc nimPanic(msg: cstring) {.exportc: "panic", cdecl, noreturn.} = rumpk_halt() # ========================================================= -# Memory Allocator Stubs (Required for ARC on freestanding) +# Memory Allocator - Provided by Zig L0 (hal/stubs.zig) # ========================================================= -# Static heap for bare metal (64KB) -var heapBase {.exportc.}: array[64 * 1024, byte] -var heapOffset {.exportc.}: csize_t = 0 - -proc allocImpl(size: csize_t): pointer {.exportc: "malloc", cdecl.} = - if heapOffset + size > csize_t(heapBase.len): - return nil - result = addr heapBase[heapOffset] - heapOffset += size - -proc deallocImpl(p: pointer) {.exportc: "free", cdecl.} = - # Bump allocator - no dealloc - discard - -proc reallocImpl(p: pointer, size: csize_t): pointer {.exportc: "realloc", cdecl.} = - # Simple realloc - just allocate new (wasteful but works) - result = allocImpl(size) - -# Nim's internal allocation hooks -proc rawAlloc(size: Natural): pointer {.exportc: "rawAlloc", cdecl.} = - result = allocImpl(csize_t(size)) - -proc rawDealloc(p: pointer) {.exportc: "rawDealloc", cdecl.} = - deallocImpl(p) - -proc rawRealloc(p: pointer, size: Natural): pointer {.exportc: "rawRealloc", cdecl.} = - result = reallocImpl(p, csize_t(size)) +# Zig exports: malloc, free, realloc, calloc +# We just import them for any explicit usage +proc malloc(size: csize_t): pointer {.importc, cdecl.} +proc free(p: pointer) {.importc, cdecl.} +proc realloc(p: pointer, size: csize_t): pointer {.importc, cdecl.} # ========================================================= # Kernel Main Entry diff --git a/hal/stubs.zig b/hal/stubs.zig new file mode 100644 index 0000000..539660c --- /dev/null +++ b/hal/stubs.zig @@ -0,0 +1,195 @@ +// VOXIS FORGE // RUMPK L0 +// libc_stubs.zig +// We are the standard library now. +// +// These C ABI functions are exported so Nim's generated C code +// can link against them. No glibc. No musl. Pure sovereignty. + +// ========================================================= +// Memory Operations (Nim needs these) +// ========================================================= + +export fn memcpy(dest: [*]u8, src: [*]const u8, len: usize) [*]u8 { + var i: usize = 0; + while (i < len) : (i += 1) { + dest[i] = src[i]; + } + return dest; +} + +export fn memset(dest: [*]u8, val: c_int, len: usize) [*]u8 { + const v: u8 = @intCast(val & 0xFF); + var i: usize = 0; + while (i < len) : (i += 1) { + dest[i] = v; + } + return dest; +} + +export fn memmove(dest: [*]u8, src: [*]const u8, len: usize) [*]u8 { + if (@intFromPtr(dest) < @intFromPtr(src)) { + return memcpy(dest, src, len); + } + // Copy backwards for overlapping regions + var i: usize = len; + while (i > 0) { + i -= 1; + dest[i] = src[i]; + } + return dest; +} + +export fn memcmp(s1: [*]const u8, s2: [*]const u8, len: usize) c_int { + var i: usize = 0; + while (i < len) : (i += 1) { + if (s1[i] != s2[i]) { + return if (s1[i] < s2[i]) @as(c_int, -1) else @as(c_int, 1); + } + } + return 0; +} + +// ========================================================= +// String Operations +// ========================================================= + +export fn strlen(s: [*]const u8) usize { + var len: usize = 0; + while (s[len] != 0) : (len += 1) {} + return len; +} + +export fn strcpy(dest: [*]u8, src: [*]const u8) [*]u8 { + var i: usize = 0; + while (src[i] != 0) : (i += 1) { + dest[i] = src[i]; + } + dest[i] = 0; + return dest; +} + +export fn strcmp(s1: [*]const u8, s2: [*]const u8) c_int { + var i: usize = 0; + while (s1[i] != 0 and s1[i] == s2[i]) : (i += 1) {} + if (s1[i] == s2[i]) return 0; + return if (s1[i] < s2[i]) @as(c_int, -1) else @as(c_int, 1); +} + +// ========================================================= +// Heap Stubs (Bump Allocator) +// ========================================================= + +var heap_base: [64 * 1024]u8 = undefined; +var heap_offset: usize = 0; + +export fn malloc(size: usize) ?*anyopaque { + if (heap_offset + size > heap_base.len) { + return null; + } + const ptr = &heap_base[heap_offset]; + heap_offset += size; + // Align to 8 bytes + heap_offset = (heap_offset + 7) & ~@as(usize, 7); + return ptr; +} + +export fn free(ptr: ?*anyopaque) void { + // Bump allocator - no deallocation + _ = ptr; +} + +export fn realloc(ptr: ?*anyopaque, size: usize) ?*anyopaque { + // Simple realloc - just allocate new (wasteful but works for bootstrap) + _ = ptr; + return malloc(size); +} + +export fn calloc(nmemb: usize, size: usize) ?*anyopaque { + const total = nmemb * size; + const ptr = malloc(total); + if (ptr) |p| { + _ = memset(@ptrCast(p), 0, total); + } + return ptr; +} + +// ========================================================= +// Stdio Stubs (Route to UART) +// ========================================================= + +const uart = @import("uart.zig"); + +export fn puts(s: [*]const u8) c_int { + const len = strlen(s); + uart.write_bytes(s[0..len]); + uart.putc('\n'); + return 0; +} + +export fn putchar(c: c_int) c_int { + uart.putc(@intCast(c & 0xFF)); + return c; +} + +export fn printf(fmt: [*]const u8, ...) c_int { + // Minimal printf - just output format string + const len = strlen(fmt); + uart.write_bytes(fmt[0..len]); + return @intCast(len); +} + +export fn fprintf(stream: ?*anyopaque, fmt: [*]const u8, ...) c_int { + _ = stream; + return printf(fmt); +} + +export fn fflush(stream: ?*anyopaque) c_int { + _ = stream; + return 0; +} + +export fn fwrite(ptr: [*]const u8, size: usize, nmemb: usize, stream: ?*anyopaque) usize { + _ = stream; + uart.write_bytes(ptr[0 .. size * nmemb]); + return nmemb; +} + +// ========================================================= +// Signal Stubs (No signals in freestanding) +// ========================================================= + +export fn signal(signum: c_int, handler: ?*anyopaque) ?*anyopaque { + _ = signum; + _ = handler; + return null; +} + +export fn raise(sig: c_int) c_int { + _ = sig; + return 0; +} + +// ========================================================= +// Exit Stubs +// ========================================================= + +fn halt() noreturn { + while (true) { + asm volatile ("wfi"); + } +} + +export fn exit(status: c_int) noreturn { + _ = status; + uart.puts("[RUMPK] exit() called - halt\n"); + halt(); +} + +export fn abort() noreturn { + uart.puts("[RUMPK] abort() called - halt\n"); + halt(); +} + +export fn _Exit(status: c_int) noreturn { + exit(status); +}