// 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. /** * @file sys_arch.c * @brief lwIP System Architecture Layer (NO_SYS Mode) * * The Membrane Graft: This provides the minimal OS abstraction layer * required by lwIP in NO_SYS=1 mode (single-threaded, event-driven). * * Architecture Philosophy: * - NO threading primitives (NO_SYS=1) * - Time via kernel syscall (not rdtime) * - No critical sections needed (single fiber context) */ #include "lwip/opt.h" #include "lwip/arch.h" #include "lwip/sys.h" #include "lwip/stats.h" // ========================================================= // External Kernel Interface // ========================================================= // Syscall to get monotonic time in nanoseconds from kernel extern uint64_t syscall_get_time_ns(void); // Console output for diagnostics extern void console_write(const void* p, unsigned long len); // ========================================================= // Time Source (The Heartbeat) // ========================================================= /** * sys_now - Required by lwIP for timeout tracking * @return Current time in milliseconds * * CRITICAL: This must be monotonic and never wrap backwards. * We use the kernel's high-resolution timer via syscall. */ u32_t sys_now(void) { // Get nanoseconds from kernel, convert to milliseconds uint64_t ns = syscall_get_time_ns(); return (u32_t)(ns / 1000000ULL); } // ========================================================= // Initialization // ========================================================= /** * sys_init - Called once during lwIP startup * * In NO_SYS mode, this is a no-op. No threads to initialize. */ void sys_init(void) { // Membrane is already initialized by ion_user_init() // Nothing to do here for lwIP } // ========================================================= // Critical Sections (NO-OP in Single-Threaded Mode) // ========================================================= #if SYS_LIGHTWEIGHT_PROT /** * sys_arch_protect - Enter critical section * @return Protection state (unused in NO_SYS mode) * * NO_SYS mode runs in a single fiber context. * No preemption possible within the Membrane event loop. */ sys_prot_t sys_arch_protect(void) { return 0; } /** * sys_arch_unprotect - Exit critical section * @param pval Protection state to restore */ void sys_arch_unprotect(sys_prot_t pval) { (void)pval; // Unused } #endif /* SYS_LIGHTWEIGHT_PROT */ // ========================================================= // Diagnostics (Optional) // ========================================================= #if LWIP_PLATFORM_DIAG /** * lwip_platform_diag - Output diagnostic message * Used by LWIP_PLATFORM_DIAG() macro if enabled */ void lwip_platform_diag(const char *fmt, ...) { // For now, silent. Could use console_write for debug builds. (void)fmt; } #endif /* LWIP_PLATFORM_DIAG */ // ========================================================= // Assertions (Contract Enforcement) // ========================================================= /** * lwip_platform_assert - Handle failed assertions * @param msg Assertion message * @param line Line number * @param file File name * * In a production kernel, this should trigger a controlled panic. */ void lwip_platform_assert(const char *msg, int line, const char *file) { const char panic_msg[] = "[lwIP ASSERT FAILED]\n"; console_write(panic_msg, sizeof(panic_msg) - 1); console_write(msg, __builtin_strlen(msg)); // Trigger kernel panic via syscall extern void syscall_panic(void) __attribute__((noreturn)); syscall_panic(); }