// 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 #include #include "lwip/opt.h" #include "lwip/arch.h" #include "lwip/sys.h" #include "lwip/stats.h" extern int vprintf(const char *format, va_list args); // ========================================================= // 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) // ========================================================= // ========================================================= // Diagnostics // ========================================================= /** * lwip_platform_diag - Output diagnostic message * Used by LWIP_PLATFORM_DIAG() macro */ void lwip_platform_diag(const char *fmt, ...) { console_write("<<>> ", 11); va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); } // ========================================================= // Assertions (Contract Enforcement) // ========================================================= /** * lwip_platform_assert - Handle failed assertions * @param msg Assertion message * * Note: Mapped via LWIP_PLATFORM_ASSERT macro in cc.h */ void lwip_platform_assert_impl(const char *msg) { 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(); }